Home / Projects / Orchestrata Ultimate / Decisions / ADR index / ADR-0067
ADR-0067: Developer daemons are deployed code; the checkout they serve is a runtime parameter
| field | value |
|---|---|
| Status | Accepted — Accepted (rulings R1/R2 of plans/ast-daemon-deployment-plan.md, Mohamed, 2026-10-05: "1. every deploy must follow the professioal deployment menthods and be seperate from code, 2. yes codemodd should be fiuxed too") |
| Date | 2026-10-05 |
| Register | factory (docs/adr, 4-digit ids) |
| Source | docs/adr/0067-dev-daemons-are-deployed-code-serving-checkouts-as-data.md — permalink at 7c7bfeea7 (unchanged on master since that commit) |
| Wiki register entry | ADR-0067 (wiki status: Accepted) |
The record
Status: Accepted (rulings R1/R2 of plans/ast-daemon-deployment-plan.md, Mohamed, 2026-10-05: "1. every deploy must follow the professioal deployment menthods and be seperate from code, 2. yes codemodd should be fiuxed too") · Date: 2026-10-05
Context
Two long-running daemons accelerate development on this host: the AST daemon
(scripts/ast_daemon.py, warm symbols/refs/source over a Unix socket)
and the codemod daemon (orchestrata_ultimate.refactor.codemod._daemon_entry,
the SPEC-110 code-intelligence-graph query server). Measured 2026-10-05:
- Both run as plain user units in
~/.config/systemd/user(orchestrata-ast-daemon.service,orchestrata-codemod-daemon.service) whoseExecStartandWorkingDirectoryname the~/workspace/orchestrata-ultimate-architecturecheckout and its.venv. That checkout is on brancharchitecture/domain-modelatd4b394279(2026-09-23), dirty, and is not the primary checkout. - Neither unit is in the repository. The repo ships only TEMPLATE units
(
deploy/systemd/orchestrata-{ast,codemod}-daemon@.service) whoseExecStartis/%I/.venv/bin/python …— the served checkout's own venv — started runtime-only byscripts/dev_daemons.sh. The "runtime-only, never~/.config" rule (labelled U-T2) exists only as a comment in the AST unit's header; ADR-0062's text does not contain it. - Nothing records which commit either daemon runs, nothing installs them from a pinned ref, and nothing refuses success when the running process is not the deployed one. Both survived the 2026-10-05 prod promote/rollback untouched; the AST daemon went inactive during it and nobody was told.
- Each Claude session's
start-ast-daemon.shhook additionally spawns an AST daemon from the session checkout's venv, detached withsetsid. - Footprint: AST daemon 546 MB RSS at 4 min (1.7 GB recorded 2026-08-30 in the unit header); codemod daemon 1.9 GB RSS at 5 h 40 min.
/opt/orchestrata-tools(deploy/install-tools.sh) already deploys the project-agnostic tools (ast_live_sync,observe_pytest,swarm_supervisor,ship) as copies underlib/with their ownpython3.14tvenv, aVERSIONfile recording the source commit,bin/entry shims, and a verifier that refuses workspace paths. Its venv holdsneo4jandwatchfiles; the daemons also needfastapi uvicorn pydantic(AST) andpsutil xxhash codemod_fast(codemod).
This is the platform's deploy-in-place defect (CLAUDE.md convention 4, RUL-027) in three forms at once: code executing from a working tree, no identity, and configuration carrying a checkout path.
Decision (Mohamed, rulings R1/R2)
-
A daemon that serves developer checkouts is deployed code. The AST daemon, the codemod daemon, and any future daemon of this kind are installed under
/opt/orchestrata-toolsbydeploy/install-tools.shfrom a pinned ref, into that deployment's own venv, at the commitVERSIONrecords. The checkout a daemon serves is a runtime parameter — the systemd instance name%I(an escaped path) and the daemon's--repo-root/repo_rootargument — never the location of the code it executes. -
No daemon process on this host executes from a workspace checkout. Not a plain unit, not a template instance whose
ExecStartpoints at/%I/.venv, not a hook-spawned process. When the tools deployment is absent, the SessionStart hook says so in one line and the AST client takes its existing slow path; it does not spawn a daemon from the checkout venv. The U-T2 "runtime-only" compromise existed because a checkout literal in config was the code location; with code under/opt, an enabled instance naming the served checkout is data, and is permitted for the primary checkout (~/workspace/orchestrata-ultimate). Worktree instances stay runtime-only, started by the session hook. -
Identity, not health. The AST daemon's
/healthand the codemod daemon's JSON-RPC status reportcode_rootanddeployed_commit. The installer's verify step starts each deployed daemon against a fixture checkout and assertscode_rootis under the deployment anddeployed_commitequals the shipped SHA; the session hook REPLACES a running daemon whosecode_rootis a working tree. -
The gate refuses their return.
scripts/check_prod_tree_separation.py(RUL-027) also inspects~/.config/systemd/user/*.service: a non-template unit whoseExecStartorWorkingDirectoryresolves under/home/*/workspace/is a violation.install-tools.shrefuses success whileorchestrata-ast-daemon.serviceororchestrata-codemod-daemon.service(plain) exists. -
The codemod daemon is in the same wave (R2), as the second half of each packet, after the AST daemon proves the shape.
Alternatives rejected
- Keep the plain units, add a drop-in pointing at the primary checkout. Still deploy-in-place; still no recorded commit; still nothing that refuses a wrong process. It would have made the symptom go away and the defect permanent.
- Deploy the daemons into
/opt/orchestrata(the prod tree). They serve developer checkouts and must not depend on prod promotion, which is gated on the prod fleet and on open operational decisions (ADR-0066 R16b). The prod tree is the product;/opt/orchestrata-toolsis the harness, and it already owns the sibling tools. - Keep the hook's checkout-venv fallback for hosts without the deployment. Rejected by R1: a fallback that runs code from the working tree is the pattern being removed. The client's slow path already keeps correctness.
- Runtime-only instances everywhere (no
enable). Nothing warm after a reboot until a session opens; the old plain unit's one virtue lost. The reason for runtime-only no longer applies once the instance name is data.
Consequences
install-tools.shgrows: venv depsfastapi uvicorn pydantic psutil xxhash(measured against a clean venv), thecodemod_fastnative module built with the pinned system toolchain,bin/ast-daemonandbin/codemod-daemonshims, installation of both template units into~/.config/systemd/user, and a live smoke test per daemon.deploy/systemd/orchestrata-{ast,codemod}-daemon@.service:ExecStartbegins with/opt/orchestrata-tools/bin/,WorkingDirectoryis the deployment,ExecStartPreasserts/%I/.git,MemoryMaxis set from measurement (provisional 3G AST, 4G codemod).scripts/dev_daemons.shkeeps working unchanged.scripts/ast_daemon.pygains--repo-rootand identity in/health;_daemon_entryalready takesrepo_rootand gains identity in status..claude/hooks/start-ast-daemon.sh(and its plugin mirror) becomes a two-branch hook: healthy deployed daemon → done; otherwisesystemctl --user --runtime start orchestrata-ast-daemon@<escaped>(after stopping a workspace-bound one); no deployment → one line, slow path.- The two plain units are disabled and removed as part of the P5 ship's verify, not by hand.
- Memory: N instances × (≤1.7 GB AST + ≤1.9 GB codemod). Mitigations:
MemoryMax, idle exit (AST), instances only for checkouts a session opens;fs.inotify.max_user_watchesmeasured against instance count before P6. - The plugin reference copies under
plugins/orchestrata/systemd/are regenerated bygen_plugin, never edited by hand.
Provenance
- Plan and packets:
plans/ast-daemon-deployment-plan.md(committed d6c8e487a, amended with these rulings in the following commit). - Rulings R1/R2: Mohamed, 2026-10-05, in the session that promoted prod and found the AST daemon inactive afterwards.
- Measurements:
systemctl --user show -p MainPID,/proc/<pid>/cmdline,/proc/<pid>/cwd,/proc/<pid>/statuson 2026-10-05;git -C ~/workspace/orchestrata-ultimate-architecture log -1 / status -sb;/opt/orchestrata-tools/.venv/bin/python -c 'importlib.util.find_spec'for the venv inventory. - Related: ADR-0062 (prod is a pinned checkout under
/opt/orchestrata), RUL-027 (prod/dev tree separation), ADR-0066 (secrets file; R16b).
Related ADRs
Rulings cited
- RUL-027: RUL-027 — Production runs its own checkout, never the development tree