diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..2f86eb9 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,67 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Compute Guard: Check command", + "type": "shell", + "command": "${workspaceFolder}/scripts/check-compute-distribution.sh \"${input:guardCommand}\"", + "problemMatcher": [] + }, + { + "label": "Remote Compute: Dry run command", + "type": "shell", + "command": "${env:HOME}/.codex/bin/remote-compute-run --dry-run -- ${input:remoteCommand}", + "problemMatcher": [] + }, + { + "label": "Remote Compute: Run command on Hetzner", + "type": "shell", + "command": "${env:HOME}/.codex/bin/remote-compute-run -- ${input:remoteCommand}", + "problemMatcher": [] + }, + { + "label": "Remote Compute: Provision workspace", + "type": "shell", + "command": "${env:HOME}/.codex/bin/remote-compute-provision", + "problemMatcher": [] + }, + { + "label": "Remote Compute: Git status on Hetzner", + "type": "shell", + "command": "${env:HOME}/.codex/bin/remote-compute-run --no-update -- git status --short --branch", + "problemMatcher": [] + }, + { + "label": "Remote Compute: Doctor", + "type": "shell", + "command": "${env:HOME}/.codex/bin/remote-compute-doctor --quick ${workspaceFolder}", + "problemMatcher": [] + }, + { + "label": "Remote Compute: Inventory", + "type": "shell", + "command": "${env:HOME}/.codex/bin/remote-compute-inventory ${workspaceFolder}", + "problemMatcher": [] + }, + { + "label": "Local Sovereignty Audit", + "type": "shell", + "command": "${env:HOME}/.codex/bin/local-sovereignty-audit", + "problemMatcher": [] + } + ], + "inputs": [ + { + "id": "guardCommand", + "type": "promptString", + "description": "Workload or local command to classify", + "default": "pnpm test" + }, + { + "id": "remoteCommand", + "type": "promptString", + "description": "Command to run on Hetzner from this repo's remote workspace", + "default": "git status --short --branch" + } + ] +} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..5a10597 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,72 @@ +# Remote Compute Distribution + +This project follows the Mac Mini / Hetzner compute boundary. + +## Execution Identity + +- `Mac_Mini`: local control surface only. +- `Hetzner_AX102`: remote metabolic infrastructure. + +## Mac Mini Allowed + +- VS Code GUI +- editing +- code navigation +- git status, diff, branch, commit, push, pull, PR metadata +- local secrets and signing material +- lightweight smoke checks that finish quickly and do not create sustained memory, swap, thermal, Docker, indexing, OCR, embedding, build, or test load + +## Hetzner Required + +- dependency installs +- Docker and devcontainers +- full test suites +- CI reproduction +- heavy builds and release packaging +- long-running dev servers +- database services +- embeddings, vectorization, semantic indexing +- OCR and batch document processing +- coverage generation +- benchmark gates +- background inference + +## Required Workflow + +Open the project through VS Code Remote SSH when doing real implementation: + +```text +VS Code GUI: Mac Mini +Workspace: Hetzner +Terminal: Hetzner +Heavy proof: GitHub Actions or Hetzner +``` + +Local Mac checkouts are for navigation, small edits, and emergency fixes only. Do not present heavy local execution as completion proof. + +## Proof Integrity + +Remote proof must correspond to explicit project state. If the local worktree is +dirty, `remote-compute-run` refuses by default because the Hetzner workspace may +represent stale code. Commit or stash the local changes, use +`remote-compute-provision` for a clean bundle, or use `--allow-dirty-local` +only as an explicit human-approved non-proof override. + +## Versionability + +The compute-distribution contract surfaces must be versionable: + +- `docs/compute-distribution.md` +- `docs/operator-tooling.md` +- `docs/remote-workspace.md` +- `docs/novaforge-ax102-stack.md` +- `scripts/check-compute-distribution.sh` +- `AGENTS.md` +- `.vscode/tasks.json` + +Do not hide these files behind `.gitignore`. `remote-compute-audit` treats +ignored contract files as invalid even when they exist locally. + +## Override + +Local heavy compute requires explicit human override for the specific task. Hidden fallback to the Mac Mini is invalid. diff --git a/README.md b/README.md index f096d93..ced6f45 100644 --- a/README.md +++ b/README.md @@ -189,3 +189,9 @@ Current CI enforces: - typecheck (`pnpm typecheck`) - build (`pnpm build`) - baseline tests (`pnpm test`) + +## Compute Distribution + +This project follows the Mac Mini / Hetzner split documented in `docs/compute-distribution.md`. +Use VS Code Remote SSH for normal implementation and use GitHub Actions or Hetzner output as proof for heavy gates. +See `docs/operator-tooling.md` and `docs/remote-workspace.md` for the operator contract and remote workspace proof rules. diff --git a/docs/compute-distribution.md b/docs/compute-distribution.md new file mode 100644 index 0000000..3d0412d --- /dev/null +++ b/docs/compute-distribution.md @@ -0,0 +1,129 @@ +# Compute Distribution + +This project uses the global Mac Mini / Hetzner workload split. + +## Rule + +The Mac Mini is the local control surface. Hetzner is the compute substrate. + +## Local Safe + +- VS Code GUI +- code reading and editing +- `git status` +- `git diff` +- `git log` +- small targeted smoke checks +- secrets/signing operations that must remain local + +## Remote Required + +- dependency installation +- Docker and devcontainers +- full test suites +- CI reproduction +- release builds and packaging +- coverage +- benchmarks +- OCR +- embeddings +- vector indexing +- long-running servers +- databases +- background inference + +## Operator Workflow + +Use VS Code Remote SSH for normal work: + +```text +Remote host: hetzner-server +Remote workspace: /home/krille/workspaces/selectpilot +``` + +Use GitHub Actions or Hetzner terminal output as proof for heavy gates. Local Mac output is valid only for bounded smoke checks. + +Remote proof is valid only when it corresponds to the explicit project state. +If the local worktree is dirty, `remote-compute-run` must refuse by default +because the Hetzner workspace may represent stale code. Commit or stash the +local changes, use `remote-compute-provision` for a clean bundle, or make an +explicit human-approved non-proof override with `--allow-dirty-local`. + +Dirty protected repositories require read-only reconciliation evidence before +any merge, stash, branch, reset, or manual integration strategy is selected. +Use `remote-compute-reconcile-report` to surface upstream delta, dirty count, +local-only contract files, changed paths, and a recommended next step without +mutating the worktree. The same evidence is available with +`remote-compute-reconcile-report --json`. +Use `remote-compute-inventory-summary` before broad adoption decisions to expose +protected, dirty-protected, external, container/no-origin, and auto-adopt +candidate counts without mutating repositories. +Use `remote-compute-inventory-action-plan` to convert inventory state into a +read-only per-repository action plan before deciding whether a repo needs +reconcile approval, fork/ownership decision, project identity decision, or no +action. +Use `remote-compute-inventory-decision-template` to turn unresolved action-plan +rows into a read-only, human-fillable decision template. Unresolved decisions +must remain `selected_decision: null` and `mutation_allowed: false` until a +separate human review fills the template. +Use `remote-compute-reconcile-plan` to inspect the read-only phase plan before +any human-approved local mutation. +Use `remote-compute-reconcile-preservation-plan` to inspect the dirty head, +dirty count, suggested preservation branch, verified-export requirement, and +human-approval requirement before any dirty protected repository is mutated. +Use `remote-compute-reconcile-export --out ` to write patches and evidence +outside the source repository before a manual reconcile. +Exported reconcile evidence must include checksums for replayability and +integrity review. +Verify exported reconcile evidence with +`remote-compute-reconcile-verify-export ` before manual application. +Run `remote-compute-reconcile-mutation-preflight ` before any +human-approved mutation to prove the verified export still matches current +dirty repository state. +Generate `remote-compute-reconcile-approval-template ` before any dirty +protected repository is mutated; every repository must remain `approved: false` +until explicit human review changes that approval outside this read-only step. +Verify the human-filled approval file with +`remote-compute-reconcile-verify-approval ` before any +mutation; approval is invalid unless each repository row is explicitly approved +with reason, approver, and timestamp. +Generate `remote-compute-reconcile-mutation-packet ` after +approval verification and before mutation; the packet must remain read-only and +surface exact preservation branches, dirty heads, evidence paths, and +operator-visible commands. + +## Versionability + +These contract surfaces must be versionable and must not be hidden by +`.gitignore`: + +- `docs/compute-distribution.md` +- `docs/operator-tooling.md` +- `docs/remote-workspace.md` +- `docs/novaforge-ax102-stack.md` +- `scripts/check-compute-distribution.sh` +- `AGENTS.md` +- `.vscode/tasks.json` + +`remote-compute-audit` fails closed if any of these files exist only as ignored +local state. + +## NovaForge Stack + +This project docks into the AX102 stack documented in +`docs/novaforge-ax102-stack.md`. + +## Operator Tooling + +`docs/operator-tooling.md` defines the local tools that enforce this boundary. +`docs/remote-workspace.md` defines the Hetzner workspace and proof rules. + +## Local Guard + +Run: + +```bash +scripts/check-compute-distribution.sh "command or workload description" +``` + +The guard exits non-zero for known heavy local workloads. diff --git a/docs/novaforge-ax102-stack.md b/docs/novaforge-ax102-stack.md new file mode 100644 index 0000000..0580ae0 --- /dev/null +++ b/docs/novaforge-ax102-stack.md @@ -0,0 +1,84 @@ +# NovaForge AX102 Stack + +NovaForge is the operational expression of the compute-distribution boundary on +Hetzner AX102. + +It is not generic hosting and must not become a remote desktop replacement. Its +topology is: + +```text +persistent sovereign metabolic layer +``` + +## Role + +NovaForge carries sustained thermodynamic load for Namaka systems: + +- dependency installation +- Docker and devcontainer execution +- full tests, heavy builds, coverage, benchmarks, and release packaging +- persistent PostgreSQL, Redis, ChromaDB, queues, replay engines, and runtime services +- OCR, embeddings, vectorization, chunking, semantic indexing, and batch processing +- monitoring, backup, and long-running service stability + +The Mac Mini remains the sovereign control surface for UI, editing, git +metadata, local secrets, signing material, orchestration approval, lightweight +smoke checks, and local reasoning. + +## Base System + +The AX102 baseline is Ubuntu Server 24.04 LTS. + +Required service classes are: + +- Docker Compose +- remote devcontainers +- PostgreSQL +- Redis +- ChromaDB +- queue workers +- OCR workers +- embedding workers +- semantic indexing workers +- reverse proxy +- monitoring +- backup + +Implementation may use different package managers or deployment automation, but +the resulting system must expose these service classes as explicit, inspectable +infrastructure. Hidden installation state is invalid. + +## First Priority Migration + +Move these workloads first: + +1. NovaArchive OCR +2. NovaArchive embeddings +3. NovaArchive vectorization +4. NovaArchive chunking +5. NovaArchive semantic indexing +6. ChromaDB remote persistence +7. PostgreSQL remote persistence +8. Redis remote persistence +9. queue workers +10. replay engines + +These workloads are metabolic load, not control-surface activity. + +## Forbidden Topologies + +NovaForge must not become: + +- a remote desktop replacement +- generic hosting +- silent local heavy fallback + +If AX102 is unavailable, the system must surface the causal failure or route to +another explicit remote proof surface. It must not silently pull heavy execution +back to the Mac Mini. + +## Docking Boundary + +This document governs the broader AX102 stack that downstream systems can dock +into. Axiom Core may validate the topology, but it is not itself a long-running +service. diff --git a/docs/operator-tooling.md b/docs/operator-tooling.md new file mode 100644 index 0000000..2ad6407 --- /dev/null +++ b/docs/operator-tooling.md @@ -0,0 +1,150 @@ +# Operator Tooling Contract + +This repository uses local operator tools to enforce the Mac Mini / Hetzner +compute boundary. + +The tools may live outside this repository on the operator machine, but their +behavior is part of the compute-distribution contract. A repository is not +protected merely because files exist locally; tooling must prove the surfaces, +route heavy work away from the Mac Mini, and fail closed when proof would be +stale. + +## Required Tools + +- `remote-compute-adopt` +- `remote-compute-audit` +- `remote-compute-inventory` +- `remote-compute-inventory-summary` +- `remote-compute-inventory-action-plan` +- `remote-compute-inventory-decision-template` +- `remote-compute-provision` +- `remote-compute-run` +- `remote-compute-reconcile-report` +- `remote-compute-reconcile-plan` +- `remote-compute-reconcile-preservation-plan` +- `remote-compute-reconcile-export` +- `remote-compute-reconcile-verify-export` +- `remote-compute-reconcile-mutation-preflight` +- `remote-compute-reconcile-approval-template` +- `remote-compute-reconcile-verify-approval` +- `remote-compute-reconcile-mutation-packet` +- `remote-compute-doctor` +- `local-sovereignty-audit` + +## Required Behavior + +`remote-compute-adopt` installs the project contract surfaces and must not +silently overwrite dirty existing files. + +`remote-compute-audit` fails closed when a required contract surface is missing, +incomplete, non-executable where execution is required, or hidden by +`.gitignore`. + +`remote-compute-inventory` reports repository state without mutating it. Owned +dirty repositories with valid contracts must be classified as +`protected_dirty_local_only`, not as ready remote proof targets. + +`remote-compute-inventory-summary` summarizes inventory coverage without +mutating repositories. It must report protected, dirty-protected, external, +container/no-origin, and auto-adopt candidate counts in machine-readable form +so operators can see which repositories are safe to touch. + +`remote-compute-inventory-action-plan` converts inventory state into a +read-only per-repository action plan. It must classify each repository as +already protected, requiring verified reconcile approval, requiring fork or +ownership decision, requiring project identity decision, or requiring manual +classification. It must not mutate repositories. + +`remote-compute-inventory-decision-template` converts the action plan into a +read-only, human-fillable decision template. It must default every unresolved +decision to `selected_decision: null`, `mutation_allowed: false`, and must not +approve adoption, create branches, or write files. + +`remote-compute-provision` is the clean-bundle path for remote workspace +provisioning. It must refuse unclean local worktrees unless the workflow +explicitly preserves or packages the state being provisioned. + +When the local worktree is clean, the generated bundle is the authoritative +remote workspace state. `remote-compute-provision` must update the remote branch +and tracking ref from the bundle even if the Hetzner workspace is otherwise +clean. A clean but stale remote workspace is invalid proof. + +`remote-compute-run` executes commands on Hetzner, not locally. It must refuse +dirty local worktrees by default because the remote workspace may represent +stale code. `--allow-dirty-local` is allowed only as an explicit +human-approved non-proof override. + +`remote-compute-reconcile-report` reports dirty protected repositories before +any integration strategy is selected. It must be read-only and must surface the +branch, upstream delta, dirty count, local-only contract files, and changed +paths so the human can choose merge, stash, branch, or manual reconciliation +without losing local state. It must also expose a recommended next step and a +machine-readable JSON form so downstream operators can review the strategy +without parsing terminal prose. + +`remote-compute-reconcile-plan` converts the read-only report into an explicit +read-only sequence of strategy phases. It must not execute merge, stash, reset, +checkout, add, commit, or file writes; it only prepares the human-approved +reconcile path. + +`remote-compute-reconcile-preservation-plan` converts the read-only report into +explicit preservation preconditions before any dirty protected repository is +mutated. It must emit the dirty head, dirty count, preservation requirement, +suggested preservation branch, verified-export requirement, human-approval +requirement, and read-only flag without creating branches or writing files. + +`remote-compute-reconcile-export` writes reconcile evidence to an explicit +external artifact directory. It may export status, patches, upstream diffs, and +local contract-file copies, but it must not write inside source repositories or +execute merge, stash, reset, checkout, add, or commit. It must include +checksums for exported artifacts so the reconcile evidence can be verified +before manual application. + +`remote-compute-reconcile-verify-export` verifies an exported reconcile artifact +directory before any manual application. It must check required files, +manifest rows, JSON structure, read-only plan flags, and checksums. + +`remote-compute-reconcile-mutation-preflight` verifies that an exported +reconcile artifact still matches the current dirty repository state before any +human-approved mutation. It must fail closed when the dirty head, branch, dirty +count, preservation flags, or export checksums drift. + +`remote-compute-reconcile-approval-template` emits a read-only, machine-readable +approval template after export verification and mutation preflight pass. It must +default every repository to `approved: false` and must not create branches or +write files. + +`remote-compute-reconcile-verify-approval` verifies a human-filled approval file +against the exported reconcile artifact and current mutation preflight. It must +fail closed unless every repository row is approved with non-empty approval +reason, approver, and approval timestamp. It must not create branches or write +files. + +`remote-compute-reconcile-mutation-packet` emits the final read-only mutation +packet after approval verification succeeds. It may describe preservation branch +commands and evidence paths, but it must not create branches, write files, or +execute merge, stash, reset, checkout, add, or commit. + +`remote-compute-doctor` verifies local tooling, inventory, remote reachability, +and standard remote workspaces without turning a failure into local heavy +execution. + +`local-sovereignty-audit` verifies the full operator surface: + +- shell syntax of operator tools +- constitutional compute-distribution policy +- protected repository contracts +- heavy-workload guard refusal +- light git operation allowance +- VS Code remote-compute tasks +- remote workspace health +- dirty-worktree refusal in `remote-compute-run` + +## Proof Rule + +Heavy completion proof must come from GitHub Actions or Hetzner. Local operator +tool output is valid only for routing, contract inspection, bounded smoke +checks, and refusal proof. + +If a remote proof surface is unavailable, the correct result is a visible causal +failure. The tools must not silently execute heavy work on the Mac Mini. diff --git a/docs/remote-workspace.md b/docs/remote-workspace.md new file mode 100644 index 0000000..aad2d6b --- /dev/null +++ b/docs/remote-workspace.md @@ -0,0 +1,63 @@ +# Remote Workspace + +This repository's remote metabolic workspace is: + +```text +Host: hetzner-server +Workspace: /home/krille/workspaces/selectpilot +``` + +The Mac Mini may open the workspace through VS Code Remote SSH, but heavy +commands must execute on Hetzner or GitHub Actions. + +## Valid Heavy Proof + +Heavy proof is valid only when: + +- the remote workspace branch matches the explicit project state +- the remote workspace is clean +- the command output comes from Hetzner or GitHub Actions +- local dirty work has not been used as completion proof + +## Invalid Heavy Proof + +The following are invalid: + +- local Mac output for full tests, builds, benchmarks, OCR, vectorization, + indexing, Docker, devcontainers, or persistent services +- clean but stale Hetzner workspaces +- hidden fallback from remote execution to local execution +- proof generated from uncommitted local state unless explicitly packaged and + named as non-mainline proof + +## Standard Commands + +Inspect without mutation: + +```bash +remote-compute-run --dry-run -- git status --short --branch +``` + +Provision the remote workspace from a clean local checkout: + +```bash +remote-compute-provision +``` + +Run a remote command: + +```bash +remote-compute-run -- pnpm test +``` + +Audit the contract: + +```bash +remote-compute-audit . +``` + +Run the operator health check: + +```bash +remote-compute-doctor --quick . +``` diff --git a/scripts/check-compute-distribution.sh b/scripts/check-compute-distribution.sh new file mode 100755 index 0000000..9bdfcbb --- /dev/null +++ b/scripts/check-compute-distribution.sh @@ -0,0 +1,123 @@ +#!/bin/bash +set -euo pipefail + +description="${*:-}" + +if [[ -z "$description" ]]; then + cat >&2 <<'USAGE' +Usage: + scripts/check-compute-distribution.sh "command or workload description" + +The Mac Mini is a control surface. Heavy workloads must run on Hetzner or GitHub Actions. +USAGE + exit 64 +fi + +normalized="$(printf '%s' "$description" | tr '[:upper:]' '[:lower:]')" + +heavy_patterns=( + "pnpm install" + "pnpm i" + "pnpm test" + "pnpm -r test" + "pnpm build" + "pnpm validate" + "pnpm benchmark" + "pnpm harness" + "pnpm render" + "render:review" + "npm install" + "npm ci" + "npm test" + "npm run test" + "npm run build" + "npm run validate" + "corepack enable" + "yarn install" + "yarn test" + "yarn build" + "bun install" + "bun test" + "bun run build" + "uv sync" + "uv pip install" + "poetry install" + "swift build" + "swift test" + "xcodebuild" + "cargo build" + "cargo test" + "cargo install" + "go test ./..." + "python -m pip install" + "pip install" + "python -m compileall" + "pytest" + "unittest discover" + "pip-audit" + "security_audit" + "pre-commit run --all-files" + "docker build" + "docker compose" + "docker run" + "docker pull" + "docker system" + "docker image" + "docker volume" + "devcontainer" + "devcontainers" + "coverage" + "benchmark" + "ocr" + "tesseract" + "poppler" + "pdfplumber" + "pymupdf" + "embedding" + "sentence-transformers" + "transformers" + "torch" + "accelerate" + "vector" + "vectorization" + "indexing" + "chroma" + "chromadb" + "postgres" + "postgresql" + "redis" + "redis-server" + "celery" + "meilisearch" + "tantivy" + "release" + "package" + "backtest" + "simulation" + "prediction" + "replay" + "schema validation" + "full registry" + "organization-wide" + "generated registry" +) + +for pattern in "${heavy_patterns[@]}"; do + if [[ "$normalized" == *"$pattern"* ]]; then + cat >&2 <