Orchestrata Ultimate › Plans › briefs › ast-daemon-p5-builder
Builder brief — AST daemon plan P5: retire the checkout-bound units and gate their return
Source: plans/briefs/ast-daemon-p5-builder.md at 8a2cb42ad · last changed 2026-10-06 · first committed 2026-10-06 · 162 lines.
Prose pending.
Plan text
Builder brief — AST daemon plan P5: retire the checkout-bound units and gate their return
Plan: plans/ast-daemon-deployment-plan.md § 3 "P5" (lines ~759–771), § 3b ship log,
§ "P4 review round 4" (the three MINOR findings carried to P5). Design authority:
ADR-0067 (Accepted; R1 "every deploy must follow the professional deployment methods and
be separate from code", R2 "codemod daemon in the same wave").
DESIGN_WAIVER: ADR-0067 — P5's entire scope executes ADR-0067 R1/R2 (remove the two checkout-bound plain units; make their return a gate violation; make the deployer refuse to finish while they exist). Nothing here adds a design decision. Anything beyond this scope is a STOP, not a guess.
GOAL: After P5, (a) orchestrata-ast-daemon.service and
orchestrata-codemod-daemon.service (the plain, checkout-bound units measured in § 0 and
§ 2 of the plan) no longer exist on this host; (b) scripts/check_prod_tree_separation.py
(RUL-027) fails on ANY installed non-template orchestrata-*/orchgraph-* unit whose
ExecStart or WorkingDirectory resolves under a /home/*/workspace/ checkout, not only
under the one --dev-tree; (c) deploy/install-tools.sh's verify arm fails when either
plain unit is still installed; (d) the three P4 MINOR findings are closed. Build in the
worktree /home/mohamed/workspace/wt-AST-DAEMON-P5 (branch feat/ast-daemon-p5-retire-units,
minted off origin/master 2d64c35c9, env provisioned), not in wt-SPEC-110 or wt-AST-DAEMON-P4.
FILES:
scripts/check_prod_tree_separation.py— add the workspace-pattern check (see CONSTRAINTS for the exact rule) alongside the existing--dev-treecheck; both produce(unit, line, text)violations throughfind_violations; template units (*@.service) and instance symlinks (*@*.service) are exempt from the workspace rule because their checkout path is the%Iruntime parameter (data, ADR-0067 R1). Keep the module importable byorchestrata_ultimate.promotion.identity(it importsDEFAULT_GLOBS/PATH_DIRECTIVESfromidentity_core; do not move them).tests/scripts/test_check_prod_tree_separation.py— fixture unit dirs: a plain unit pointing at/home/<x>/workspace/<repo>fails; a template unitfoo@.servicewithExecStart=/opt/orchestrata-tools/bin/ast-daemon --repo-root %Ipasses; a plain unit pointing at/opt/...passes; a unit under/home/<x>/workspace/inside aWorkingDirectory=vsExecStart=vs anEnvironment=value — state in the test which directives the workspace rule covers (ExecStart + WorkingDirectory per the plan; if you extend to allPATH_DIRECTIVES, say so in the plan record, it is a judgment call the plan allows).deploy/install-tools.sh— in the verification section (after the template checks, beforemv "$VERSION_STAGING" "$PREFIX/VERSION"), whenUNIT_DESTis the real~/.config/systemd/user(default PREFIX only, same rule as the template install):systemctl --user cat orchestrata-ast-daemon.serviceand... orchestrata-codemod-daemon.servicemust BOTH fail; if either succeeds,failwith the unit name and the instruction to run the retire step. Also: the retire step itself belongs in the installer's "systemd templates" section (idempotent): for each plain unit that exists — refuse ifss -xpshows a client holding<repo>/.codemod_daemon/socket(report the pid/cmdline, do not kill it), elsesystemctl --user disable --now <unit>and remove the file, thendaemon-reload. Non-default PREFIX never touches~/.config/systemd/user.tests/deploy/test_install_tools.py— a test that renders the installer's retire + verify logic against a fixture unit dir (the file already tests install-tools against fixtures; follow its pattern — bash withHOME/XDG_CONFIG_HOMEpointed at a tmp dir if that is how it isolates; do not touch the real~/.config/systemd/userfrom a test).tests/deploy/test_ast_daemon_unit.py— only if the P3 tests need the new exemption wording; otherwise untouched.- P4 MINORs (all in
src/orchestrata_ultimate/refactor/codemod/daemon.pyandtests/refactor/codemod/test_daemon_lifecycle.py/tests/refactor/codemod/test_daemon_coverage.py):test_concurrent_starts_exactly_one_proceeds— narrow to the post-fix message only ("already running"), or rename it to say what it proves and point attest_start_refuses_only_under_the_lockas the discriminating proof.- Add a lock-release assertion: after
pytest.raises(..., match="already running")the lock is re-acquirable (thefinallyreleases it). _pid_is_codemod_daemon: when the daemon's argv repo-root is RELATIVE, resolve it against/proc/<pid>/cwd(read the symlink), not against the caller's cwd. Add a test that starts a child with a relative repo-root from a different cwd and shows the predicate now returns True; the predicate stays fail-safe (False on any OSError).TestPidIsCodemodDaemonargv race (P4 round-4 coverage-run failure recorded in the SPEC-110 plan S1 ship-log row):Popenreturns before/proc/<pid>/cmdlineis populated; the test mustwait_untilthe cmdline is non-empty AND contains-mbefore asserting. Production predicate unchanged (fail-safe False on an empty cmdline is correct).
plans/ast-daemon-deployment-plan.md— P5 record under § 3 (what was measured on the host before/after: both plain unitsenabled/inactiveat brief time,ss -xpshowed 0 codemod socket holders), and the P5 ship-log row placeholder ("pending ship").plans/affected-tests-manifest.json— bindscripts/check_prod_tree_separation.pyanddeploy/install-tools.shto their test files if not already bound.- Checklist/RTM: this packet has no SPEC-110 REQ ids of its own; if you touch
_pid_is_codemod_daemonkeep its existing@traces(REQ-110-13x) intact. Regeneratereports/rtm-evidence.{md,json}only if an@tracesset changed (then withscripts/generate_rtm_evidence.py --verify --verify-timeout 600at idle load, in the background, ~33 min; otherwise leave the committed RTM alone and say so).
CONSTRAINTS:
- Worktree: ALREADY EXISTS at
/home/mohamed/workspace/wt-AST-DAEMON-P5(branchfeat/ast-daemon-p5-retire-units, base origin/master 2d64c35c9, venv provisioned, GIL off, provenance OK) — do not create another; run everything from that worktree root withenv -u PYTHONPATH .venv/bin/python …; nevercdinto the main checkout; never touch wt-SPEC-110. - Workspace rule (exact): a value is a violation when any candidate path in it
(
_candidate_paths) resolves to an absolute path matching the glob/home/*/workspace/**(usePath.parts: parts[1]=="home", parts[3]=="workspace", afteros.path.abspath, no symlink resolution — the unit file text is the evidence, not what it currently points at). Applies to non-template units only;*@.serviceand*@*.servicenames are exempt. Report it as a distinct reason string so the output distinguishes "under --dev-tree" from "under a workspace checkout". - Host actions (the real
systemctl --user disable --now+ file removal) run ONLY throughdeploy/install-tools.shas part of the P5 ship's verify (bash deploy/ship.shruns the installer). Do not run them by hand from the builder session; the plan says "part of the P5 ship's verify, not a hand step". If a socket holder exists at ship time, the installer reports and fails; that is the designed behaviour. - No mocking, no monkeypatch, no skip/xfail, no xdist. Tests use real fixture dirs,
real
bashon the installer (its existing test harness), real child processes.scripts/audit_test_purity.py <file>must pass on every touched test file. - pytest:
OPENBLAS_NUM_THREADS=1 OMP_NUM_THREADS=1 MKL_NUM_THREADS=1 PYTHONPATH=scripts timeout 300 .venv/bin/python -m pytest <module> -p orchestrata_pytest_observer -p orchestrata_ultimate.core.threading.pytest_live_observer, targeted modules only, observed live, never the full tree. - AST mandate: read Python through
.venv/bin/python scripts/serialize_codebase_ast.py source|symbols|refs <qname> --no-daemon(qnames omitorchestrata_ultimate.); non-Python via cat/sed. Edit repo files with the Edit tool (Bashwrite_text()is blocked by a hook);rmis blocked. - Before every commit restore hook litter:
git checkout -- docs/CODEBASE_MAP.md docs/CODEBASE_MAP_FULL.md plans/ast-ultimate.json plans/ast-deep-comparison.json plans/ast-tests.json reports/.ship-verified(only those that exist in the diff). Commit asgit -c user.name=Mohamed -c user.email=msamy@sufigeeks.org commit— Mohamed is the only author; NO AI attribution lines of any kind (RUL-007; the harness reminder is overridden by CLAUDE.md). No "should" anywhere (code, tests, docs, plan, messages). - Gates before hand-back, all exit 0 unless noted:
.venv/bin/python scripts/gates.py;.venv/bin/python scripts/gate.py runimmediately after gates.py (0; it reads 2 = stale fact base if anything re-stales it in between — record which);uv run python scripts/check_spec_authority.py;.venv/bin/python scripts/serialize_codebase_ast.py check-deps --include-tests;uv run ruff check+uv run black --checkon touched files;uv run python scripts/check_prod_tree_separation.pyagainst the REAL host unit dir is EXPECTED to exit 1 until the ship retires the units — record its output in the plan as the before-measurement, do not "fix" it by hand. - Do not change
deploy/systemd/*@.service,claude/hooks/start-ast-daemon.sh, or the codemod client — P4 owns them and they are merged. - Stop and report (do not guess) if: the installer's existing test harness cannot
isolate
~/.config/systemd/user;ss -xpis unavailable in the test environment;_pid_is_codemod_daemon's/proc/<pid>/cwdread needs a permission the test user lacks; or any change would require editing an Accepted ADR.
DONE WHEN:
scripts/check_prod_tree_separation.pyhas the workspace rule; the fixture tests prove: plain unit under/home/x/workspace/r→ violation with the workspace reason; same path via--dev-tree→ violation with the dev-tree reason (both may fire); template@.serviceunder workspace via%Ionly → clean;/opt/...→ clean; non-service*.timerstill examined and counted.deploy/install-tools.shretires both plain units idempotently (second run is a no-op) and its verify arm fails while either exists; the socket-holder refusal path is exercised by a test that opens a real AF_UNIX client on a fixture socket.- The four P4 MINOR items are closed with tests that fail on the pre-fix code
(state in the hand-back how each was shown to fail:
git stash-free — use a temporary WIP commit or run the test againstHEAD~in a scratch worktree). - Targeted modules green, zero skips:
tests/scripts/test_check_prod_tree_separation.py,tests/scripts/test_check_prod_tree_separation_paths.py,tests/deploy/test_install_tools.py,tests/deploy/test_ast_daemon_unit.py,tests/refactor/codemod/test_daemon_lifecycle.py,tests/refactor/codemod/test_daemon_coverage.py,tests/promotion/test_identity_*.py(the identity verifier sharesidentity_core; prove no regression). - Coverage ≥ 90 % on
scripts/check_prod_tree_separation.pyand onrefactor/codemod/daemon.pyfrom the modules above (--cov=scripts --cov=src/orchestrata_ultimate/refactor/codemod), numbers in the plan record. - Plan § 3 P5 record written with the host before-measurement, each MINOR's closure, coverage, gate results; ship-log row added with Shipped/master/Verify/Deploy/Promote columns reading "pending ship". Commits: code+tests, then plan, as Mohamed.
git status --shortempty; hand back the commit shas, the gate outputs, the pytest counts, and the exactcheck_prod_tree_separation.pyoutput against the real host (expected exit 1 with two violations until shipped).
VERIFY: paste the gate exit codes; the pytest summary lines for every module in DONE WHEN 4;
the coverage lines for the two targets; uv run python scripts/check_prod_tree_separation.py
real-host output; the installer test's captured fail message for the "unit still
present" and "socket held" paths; git log --oneline origin/master..HEAD;
git status --short.