Orchestrata Ultimate / Specs / 108-environment-installer

108-environment-installer: Environment Replication Installer

At a glance

Item Value
Spec directory specs/108-environment-installer/
Status line in the spec Complete
Requirement IDs defined 25
With a @traces citation in src/ 0 (0.0%)
With a @traces citation in tests/ 0 (0.0%)
Tracked files 2
RTM page 108-environment-installer

Reading this spec

This spec defines a tracked, tested installer suite that replicates the complete orchestrata-ultimate working environment on a fresh machine. The environment previously lived on one workstation only: the global ~/.claude tools and hooks, session state, custom test runners and a hand-built 13-node Incus fleet. Nothing outside the repository was reproducible, so a disk failure or a second machine meant rebuilding from memory.

The design is two idempotent bash installers plus tracked assets. claude-env/install.sh sets up the Claude Code global layer and delegates the config layer to deploy/install-claude-config.sh, the SPEC-107 FR-013 deployment of claude/. claude-env/install-infra.sh sets up the infrastructure fleet on either an Incus or a Docker backend, with Terraform as the infrastructure-as-code engine on the Incus path, using the infra/rehearsal/ harness, and infra/docker/infra-compose.yml for the Docker fleet. Four user stories cover a fresh workstation bootstrap, backend choice between Incus and Docker, a safe re-run on a machine with an existing environment, and a raw machine on another network without access to private images.

The 25 requirement IDs (REQ-108-NNN) state the behaviour. The config layer deploys from a pinned git ref and verifies every file byte for byte. A second identical run is a no-op, verified in a clean Ubuntu 24.04 container. --dry-run prints every planned action and changes nothing. The infrastructure installer detects both Incus and Docker and reports both states before choosing. The compose file brings up Redis, a primary Neo4j, three workers and Memgraph with health checks, and waits until all are healthy. Subnet, cloud image and ready-timeout overrides are available through ORCHESTRATA_SUBNET, ORCHESTRATA_CLOUD_IMAGE and ORCHESTRATA_READY_TIMEOUT. No Memgraph-Enterprise artifact appears in any public or tracked binary form, so the Docker path uses the community image and documents the divergence. A semantic-search test fails loudly on an empty semantic graph instead of passing vacuously. Per-service backend selection (mix and match) is declared as a follow-up.

No code module cites this spec, since the deliverables are shell scripts, compose and Terraform files. The requirements traceability matrix lists every ID. The spec's own status line reads Complete and it tracks 2 files. No src/ symbol cites any of the 25 requirements, so measured trace coverage is 0.0%, and in tests/, 0 requirements are cited by a test-side @traces. All 25 requirements have no citing symbol; untraced means no @traces names the ID, and the behaviour may still exist in code that was never annotated.

Requirements

Checkbox is the state recorded in the requirements checklist; Traced by is the count of src/ symbols whose @traces names the ID.

ID Done Requirement Traced by
REQ-108-001 yes install.sh delegates the config layer to deploy/install-claude-config.sh via --prefix, which deploys claude/ from a pinned git ref and verifies every file byte-for-byte. It no longer rsyncs a bundle of its own — claude-env/global/ is deleted none
REQ-108-002 yes settings.json is merged by claude/scripts/patch_settings.py — additive, idempotent, and it rewrites hook commands to the deployed venv's interpreter. Replaces the settings.json.new write-alongside none
REQ-108-003 yes Python deps go into ~/.claude/.venv, the deployment's own uv venv on python3.14t (platform convention 2), and the delegate verifies they import FROM that venv. The pip --user / --break-system-packages path is retired none
REQ-108-004 yes A second identical run is a no-op (verified on clean Ubuntu 24.04 container) none
REQ-108-005 yes Missing required tools (git rsync cmp uv python3) abort BEFORE any mutation, listing all of them with per-distro install hints none
REQ-108-006 yes The missing-uv path aborts with the astral.sh install hint, and a missing free-threaded python3.14t aborts naming scripts/build_ft_cpython.py — a build hint, since that is the one blocker no package manager fixes none
REQ-108-007 yes --dry-run prints every planned action and mutates nothing none
REQ-108-008 yes Every bundled Python file parses on Python 3.12 (17 PEP 758 parenthesis-free except sites parenthesized; verified in-container) none
REQ-108-009 yes tools/orchestrata -> session ships as a RELATIVE symlink so it survives any home layout none
REQ-108-010 yes install-infra.sh detects incus AND docker and reports both states before choosing none
REQ-108-011 yes --backend incus|docker + --yes is fully non-interactive; without flags an interactive prompt offers both none
REQ-108-012 yes Terraform installs from the hashicorp apt repo (Debian/Ubuntu) or pacman (Arch) when absent none
REQ-108-013 no Mix-and-match (per-service backend selection) — declared follow-up, enabled by per-service .env derivation none
REQ-108-014 yes The 8-node public tier builds from infra/rawmachine (terraform, images:debian/12/cloud, pinned IPs) with cloud-init provisioning — verified end-to-end in an ISOLATED VM (host fleet ACL-blocked and proven unreachable), incus installed in-VM, protocol-level checks green on every node none
REQ-108-015 yes All provisioned services are systemd-supervised, fleet-bound, and survive container restart; the app unit on prolog nodes is ConditionPathExists-guarded (inactive, never crash-looping) none
REQ-108-022 yes ORCHESTRATA_SUBNET / ORCHESTRATA_CLOUD_IMAGE / ORCHESTRATA_READY_TIMEOUT overrides work (image override exercised in verification — the images: remote stalls on constrained networks) none
REQ-108-023 yes Disk preflight: < 12GiB free aborts before any build (ORCHESTRATA_MIN_DISK_GB override) — a 10GiB root exhausted mid-provision in verification none
REQ-108-024 no installer + bootstrap_graphs.py --all + infra-subset suite green on the machine's own fleet — trigger: first raw-machine bring-up with the app venv (uv sync --dev + FT builds) installed none
REQ-108-016 yes infra-compose.yml brings up redis + neo4j primary + 3 workers + memgraph 3.11.0 with healthchecks; up -d --wait gates on ALL healthy (verified in clean Ubuntu 24.04 VM) none
REQ-108-017 yes Data-path smoke passes: redis PONG, cypher round-trip on primary AND a worker, memgraph bolt write+read none
REQ-108-018 yes .env.docker is emitted with the full localhost port map and the community-stand-in caveat in-file none
REQ-108-019 yes No Memgraph-Enterprise/orchgraph artifact appears in any public or tracked binary form; the docker path uses the community image with the divergence documented none
REQ-108-020 yes context.json/context.md/context.history.md are tracked in the repo none
REQ-108-021 yes session_cli.py init bootstraps a NEW project from cwd when no root exists (circular-error defect fixed); init → begin → log-work → status verified on the clean container none
REQ-108-025 yes test_semantic_search.py fails loudly on an empty semantic graph instead of passing vacuously (empty result list / "[]" / "No results." no longer satisfy the assertions); 12/12 observed on the populated fleet none

Code that traces this spec

No src/ symbol cites a requirement of this spec.

Checklists

checklists/requirements.md

The requirement list above comes from this file; 23 of 25 checkbox items are ticked.

Full spec text

Verbatim from specs/108-environment-installer/spec.md; headings are pushed down two levels.

SPEC-108: Environment Replication Installer

Metadata

Overview

Amended 2026-08-14 — claude-env/global/ is deleted. This spec originally made that directory a second, verbatim copy of the ~/.claude layer, rsynced into place by install.sh. SPEC-107 FR-013 then made claude/ the source of truth, deployed by deploy/install-claude-config.sh from a pinned git ref with a byte-exactness check that refuses success on any mismatch. Two installers were writing $HOME/.claude and only one verified its work; whichever ran last won.

Measured before removal: claude-env/global/ held zero files claude/ did not also have — every path unique to it was a .ruff_cache or .pytest_cache build artifact — and it had already drifted from claude/ on ~22 files within five hours of that tree existing. Its only distinct content was the drift.

Mohamed ruled claude/ canonical. FR-001 and SEC-001 below are amended accordingly; the fresh-machine entry point, the preflight and the infra half are unchanged, which is what this spec uniquely owns.

User Scenarios

US-108-001: Fresh workstation bootstrap
US-108-002: Backend choice (incus vs docker)
US-108-003: Safe re-run on a machine with an existing environment
US-108-004: Raw machine on another network, no private-image access

Data Models

{
  "env_docker": {
    "description": ".env.docker emitted by the docker backend",
    "type": "object",
    "required": ["REDIS_HOST", "REDIS_PORT", "KG_ROUTING_URI", "KG_DATABASE", "MEMGRAPH_URI"],
    "properties": {
      "REDIS_HOST": {"type": "string", "const": "127.0.0.1"},
      "REDIS_PORT": {"type": "string", "const": "6379"},
      "KG_ROUTING_URI": {"type": "string", "pattern": "^bolt://"},
      "KG_DATABASE": {"type": "string", "const": "orchkg"},
      "MEMGRAPH_URI": {"type": "string", "pattern": "^bolt://"},
      "PROLOG_NODES": {"type": "string", "const": "", "description": "empty: janus in-process"}
    }
  }
}

Functional Requirements

Error Conditions

ID Condition Handling
ERR-001 Required CLI tool missing (git rsync cmp uv python3) Exit 1 before any mutation; list all missing tools + per-distro install command
ERR-002 (amended 2026-08-14) uv absent Exit 1 with the astral.sh install hint. The pip path is gone: the deployment owns a uv venv (platform convention 2)
ERR-003 (amended 2026-08-14) Free-threaded python3.14t absent Exit 1 naming $FT_PYTHON and scripts/build_ft_cpython.py — a BUILD hint, not a package hint. The delegate still refuses success on a broken toolchain; it verifies importability from the deployed venv
ERR-004 (amended 2026-08-14) Existing settings.json differs patch_settings.py merges additively and idempotently, rewriting hook commands to the deployed venv. The settings.json.new write-alongside is retired
ERR-005 Unknown --backend value Exit 2 with usage
ERR-006 Neither backend chosen interactively (bad input) Exit 1 "invalid choice"
ERR-007 Nested/constrained network stalls the images: remote fetch Operator imports the image locally and points ORCHESTRATA_CLOUD_IMAGE at the alias (documented in the installer header)
ERR-008 terraform apply non-zero Exit 1; terraform's own error stream is the diagnosis
ERR-009 Node provisioning failure (any of the parallel provision_node.sh) Collect all PIDs, exit 1 if any failed
ERR-010 docker compose up --wait timeout (600s) Exit 1; containers left in place for inspection
ERR-011 Not root and no sudo Exit 1 "not root and no sudo available"
ERR-012 Unsupported distro (no apt/pacman) Exit 1 naming the requirement
ERR-013 Less than 12GiB free disk (ORCHESTRATA_MIN_DISK_GB override) Exit 1 BEFORE any build — a 10GiB root exhausted mid-provision in verification
ERR-014 Services not answering within ORCHESTRATA_READY_TIMEOUT Exit 1 with the per-node cloud-init status --long inspection command

API Contracts

claude-env/install.sh [--dry-run]                 # exit 0 success, 1 preflight/dep failure
claude-env/install-infra.sh
    [--backend incus|docker]                      # else interactive prompt
    [--yes|-y]                                    # non-interactive accept
    [-h|--help]
# env: CLAUDE_HOME (install.sh dest override),
#      ORCHESTRATA_SUBNET (incus fleet subnet, default 10.95.0),
#      ORCHESTRATA_CLOUD_IMAGE (base image override, default images:debian/12/cloud),
#      ORCHESTRATA_READY_TIMEOUT (service gate seconds, default 1800),
#      ORCHESTRATA_MIN_DISK_GB (disk preflight floor, default 12)

Security Requirements

Verification

The session-250 record previously here overclaimed: the docker run was container-level smoke only (fleet health + docker exec probes), with no app-level config wiring and no network isolation — the suite could have silently reached production infra. Retracted and replaced by the session-251 record below, which enforces isolation at the network layer.

Executed 2026-07-21 (sessions 250-251), all on fresh Ubuntu 24.04 images:

Layer Environment Result
install.sh preflight/dry-run/install/idempotency/settings-merge Incus container 12 scripted checks pass
Session CLI init → begin → log-work → status same container (Python 3.12) pass — after fixing 17 PEP 758 except sites + the init root-bootstrap defect
Isolation enforcement dedicated incus network + ACL 10.53.1.0/24 hard-dropped; proven unreachable from inside the VM before AND after the build, internet intact
incus raw-machine path, end-to-end isolated VM, incus installed IN-VM terraform applied the 8-node fleet from cloud-init; protocol-level checks pass on every node (authenticated cypher-shell RETURN 1 on all 4 neo4j, redis PONG, swipl 9.0.4 ×3); services survive container restart; canonical .env installed pointing at the VM's own 10.95.0.x fleet
Cloud-init first-boot cost same VM 2 iterations to green: 10GiB root exhausted mid-provision (→ ERR-013 preflight), 900s gate too tight for 4 parallel neo4j pulls (→ ORCHESTRATA_READY_TIMEOUT)
docker path VM (session 250) fleet healthy + data-path smoke (redis PONG, cypher on primary+worker, memgraph write/read) + canonical .env; infra-level only — the FR-012 suite-level acceptance is trigger-armed for both backends
Semantic-search false-green (seed-data audit) host fixed: empty-graph results now FAIL loudly instead of passing vacuously; 12/12 observed