Orchestrata Ultimate › Plans › dogfood-build-to-promotion

Plan: orchestrata builds, deploys and promotes — by itself

Source: plans/dogfood-build-to-promotion.md at 8a2cb42ad · last changed 2026-08-07 · first committed 2026-08-07 · 134 lines.

Prose pending.

Plan text

Plan: orchestrata builds, deploys and promotes — by itself

Written: 2026-08-08, end of session 260, for a NEW session after a Claude Code restart. Self-contained on purpose: assume none of session 260's context survives.

Goal, in one sentence: everything I did BY HAND this session — write code, run the gate battery, run the suite, commit, merge, deploy, promote — is done instead by orchestrata's own kernel/orchestrator/volks, with a human approving rather than driving.


1. What already exists (verified in session 260, do not re-derive)

capability state
Kernel (runtime_main, cxpt on CXP_GRPC_PORT) running in prod, probes green
Gateway (WS 8765 + HTTP 8766) running in prod, ping→pong
PipelineRunner, IntentBroker, 11 volks built and tested
Governance (PolicyEvaluator, constitutional.pl) wired, fail-closed
SPEC-033 factory (DoR, red-first, conformance, merge queue, worktrees) built, CLIs under scripts/factory_*.py
scripts/e2e_run.py dogfood runner "with full real-time observability"
scripts/promote_env.py validate / test / promote, ledger-gated
Self-hosted CI (GitLab Runner + Incus custom executor) registered, online, jobs passing
Prometheus @ 10.92.53.40 scraping the gateway

Prod runs from this working tree (WorkingDirectory=/home/mohamed/workspace/ orchestrata-ultimate-architecture, ORCHESTRATA_ENV_PROFILE=prod). There is no separate prod artifact — a restart is the deployment. This is load-bearing for everything below, and is also the biggest single risk (see §5).


2. The measurement to take FIRST

Do not plan around guesses about where the loop breaks. Run it and watch:

uv run python scripts/e2e_run.py            # observed, background, per RUL-009

Record exactly which stage it reaches and what stops it. Everything in §3 is predicted from reading the code, not from having run it end to end — treat §3 as hypotheses to confirm or discard, not as a task list to execute blindly.


3. Predicted gaps, in dependency order

G1 — no volk can deploy or promote

ToolRegistry has 17 tools (read/write file, list_dir, search_code, run_shell, ast_query, check_coverage, validate_mermaid, check_doc_links, message_volk, pub/sub, get_volk_status, web_search, web_fetch, design_patterns). None of them can run the gate battery as a first-class action, and none can promote or deploy. run_shell could technically do both, which is exactly the problem: an ungoverned shell escape is not a deploy capability, it is a hole.

Needs: run_gates, run_suite, promote_env tools with real governance predicates (who may promote, to which env, under what evidence). Design first (RUL-022) — this is a privilege boundary, not a wrapper.

G2 — SPEC-110 observability has no producer

Five observers, an 8-member event enum, and zero CodemodEvent(...) constructions anywhere. Design is already written and needs no new mechanism: plans/codemod-observability-wiring-design.md. Without it a factory run is unobservable exactly when observability matters most.

G3 — the promotion gate reads a ledger, not evidence

promote --to prod passes if ledger[test][test].result == PASS, regardless of whether that PASS describes the code being promoted. In session 260 the record was 6 hours stale and would have gated a promotion of code it never saw. It happened to be equivalent (proven with git diff), but the gate did not know that. It should bind the recorded PASS to a commit sha and refuse when the sha does not match HEAD.

G4 — no rollback path

promote records PROMOTED. Nothing records what the previous good sha was, and nothing can go back to it. Autonomous promotion without rollback is not something to switch on.


4. Staging — each stage ends with a human-visible artifact

Pick the S4 deliverable from the existing backlog rather than inventing one. Candidates already logged: the 8 spec-mismatch traces, EnterWorktreeTool's 36-requirement shotgun, the AST toolkit rename dropping Load references.


5. Standing risks — carry these into the new session

  1. Prod runs from the dev tree. CLOSED 2026-08-08 by RUL-027. Production now runs from ~/prod/orchestrata-ultimate — its own clone, its own .venv, no PYTHONPATH into this tree. Verified from /proc: all four prod processes have cwd=~/prod/orchestrata-ultimate and zero mapped files from the development tree. Enforced by the prod-separation gate (scripts/check_prod_tree_separation.py). Deployment is now an explicit git checkout <promoted sha> in that tree plus a restart — editing files here no longer changes production.
  2. The suite is 283–286s against a 240s target. The tail is test_workspace_load::test_memory_guard at 78s, spec-mandated (REQ-110-004) and not reducible by tuning. Any further gain is placement or anti-affinity, not another knob. Do not let an agent "fix" this by deselecting tests.
  3. CI is self-hosted and single-host. Runner 54962152, custom Incus executor under deploy/gitlab-runner/. concurrent = 2 is shared with the dr-hannah runner in the same config.toml and the same process.
  4. Root vs user credentials. The incus daemon runs skopeo as root. A private-registry login as the desktop user is invisible to it — that cost a CI round-trip. If image pulls start returning 403, re-run sudo skopeo login registry.gitlab.com.

6. First commands in the new session

session status                       # where things stand
git log --oneline -12                # session 260's tail
uv run python scripts/promote_env.py status
uv run python scripts/e2e_run.py     # S0 — observed, background