Home / Projects / Orchestrata Ultimate / Decisions / ADR index / ADR-0071

ADR-0071: REQ-110-135 amended: codemod daemon lifecycle is delegated to systemd user units

field value
Status Proposed
Date 2026-10-06
Register factory (docs/adr, 4-digit ids)
Source docs/adr/0071-req-110-135-amended-codemod-daemon-lifecycle-is-delegated-to-systemd-user-units.md — permalink at ffadad98c (unchanged on master since that commit)
Wiki register entry ADR-0071 (wiki status: Proposed)

← ADR-0070 · ADR-0072 →

The record

Status: Proposed · Date: 2026-10-06

Context

SPEC-110 REQ-110-135 (specs/110-codemod-engine/spec.md:2003) reads verbatim:

REQ-110-135: The daemon SHALL support lifecycle management via codemod daemon start|stop|status|restart subcommands. The start command SHALL fork to background, parse the workspace, create the Unix socket, and start an inotify watcher thread. The stop command SHALL send SIGTERM, wait 5s for graceful shutdown, and force kill if necessary.

ADR-0067 (Accepted) rules that every development daemon, the codemod daemon included (Decision item 5, wave R2), is deployed code under /opt/orchestrata-tools run as a systemd user unit, and that no process is spawned from a checkout. Packet P4 of plans/ast-daemon-deployment-plan.md executed that ruling in src/orchestrata_ultimate/refactor/codemod/daemon.py:

The P4 reviewer (round 3, 2026-10-06) found the result correct against ADR-0067 and contradictory to REQ-110-135 as written: "fork to background" is false (the unit forks nothing; systemd owns the process), and "send SIGTERM, wait 5s, force kill" is now the exception path, not the rule. Both decorated methods cite REQ-110-135, so RUL-013 (scripts/check_spec_authority.py) keeps pointing tests at a clause the code deliberately does not satisfy.

ADR-0067's Decision text does not name REQ-110-135. Changing a requirement's words is a spec amendment, and ADR-0068 set the mechanism for that: a Proposed ADR carrying the new text, edited into spec.md only once Accepted. Editing the clause under the ADR-0067 waiver would be a self-issued ruling.

Decision (proposed)

Amend REQ-110-135 to read:

REQ-110-135: The daemon SHALL support lifecycle management via codemod daemon start|stop|status|restart subcommands that delegate to the systemd user unit instance named by the repository root (ADR-0067). start SHALL refuse when that instance is already active, SHALL refuse when the deployed launcher under /opt/orchestrata-tools is missing (spawning nothing), SHALL start the instance with systemctl --user start, and SHALL record the instance's MainPID in .codemod_daemon/pid; the deployed launcher parses the workspace, creates the Unix socket, and starts the inotify watcher thread. stop on a loaded instance SHALL run systemctl --user stop and SHALL signal no pid. Only when no instance is loaded for the repository SHALL stop send SIGTERM to the pid-file pid, wait 5s for graceful shutdown, and force kill if necessary, and only after verifying that pid's argv is the codemod daemon entry module; any other pid is left untouched and the stale file removed.

REQ-110-134 is unchanged: the daemon still writes its pid to .codemod_daemon/pid (via the manager recording MainPID), creates the socket at .codemod_daemon/socket, and holds .codemod_daemon/lock. REQ-110-133, REQ-110-136 and REQ-110-137 are unchanged.

Alternatives rejected

Consequences

Provenance

Rulings cited

Specs cited