worktree-unit-route-config
Config delivery for routes that name their own systemd unit (discussion #114)
Spec: docs/superpowers/specs/2026-09-07-named-unit-config-delivery-design.md (approved by Paul 2026-09-07, three codex rounds; rulings in §8, dispositions §9–§11). Plan: docs/superpowers/plans/2026-09-07-named-unit-config-delivery.md.
What lands:
- A route stamped with a named unit (
carlos route --unit, the #110 column) is the ROOT pass's:appconfig.SyncUnitsrenders/etc/carlos/apps/<host>.env, writes a marker-owned drop-in/etc/systemd/system/<unit>.d/zz-carlos-env.confthat resets the unit'sEnvironmentFile=list to that file, records intent incarlos-env.pendingbefore mutating, runs onedaemon-reload, verifies the effective list is exactly carlos's file, andsystemctl restarts the unit. All of it behind a flock, behind a rail (shape, name, hostname, one route per unit, alias/load-state probe, symlink-safe directories), with every failure printed and the marker kept so nothing restarts on a guess. - The exec sweep leaves stamped routes alone; an old
/data/<host>.config.envstays (existing ruling) and is warned about every pass. env set/secrets setnow say when a write reached nothing (Undelivered) and when a stamp is blocked (Blocked), over both wire types, additive.- The doors (
carlos route --unit,--hibernate,carlos add) validate the row that would result: an addr upstream, no socket, no hibernation. - Docs: cli.md and AGENTS.md.
Before merge: copy-review of the new member-facing strings (restartCopyUndelivered, restartCopyBlocked, the refusal reasons in internal/appconfig/stamped.go and cli.go, the stamped secrets notice in syncexec.go).
After the roll: the first root pass restarts each stamped, configured route once (spec §4), and the reset means a hand-built unit's own EnvironmentFile= lines stop applying. Check systemctl cat on console.service and the Woodstar units before rolling (spec §7 step 2). Woodstar's route is already stamped; no box step is needed.
Twelve tasks, each with tests; four controller rulings against plan text and the parked residuals are in the branch's SDD ledger. Full gate green: build, vet, all 42 test packages, gofmt, darwin/windows/linux-arm64.
🤖 Generated with Claude Code
Discussions
- No discussions on this branch yet.
Tasks
- No tasks yet.
Activity
- paul@keymail.dev pushed 4690a5b72 spec: the lock paragraph no longer says a queued pass stepped aside
- paul@keymail.dev pushed 171f1faab final-fix wave: validate the row Upsert stores, secrets notice for a stamped route, lock wording, dead code, deferred minors
- paul@keymail.dev pushed 2e5b50f96 docs: a stamped route gets its config from the root pass; the notice's two new lines
- paul@keymail.dev pushed aa5a2e9c1 cli: add --unit validates the row that would result, not the raw flags
- paul@keymail.dev pushed db5d67041 cli: route --unit, --hibernate and add validate the row that would result
- paul@keymail.dev pushed 72eb63a8e notice: undelivered and blocked over both wire types, rendered by the CLI (copy pending copy-review)
- paul@keymail.dev pushed 467c30282 appconfig: narrow BlockedStamps to the written environment
- paul@keymail.dev pushed efbfb1d78 appconfig: the notice says when a write reached nothing or a stamp is blocked
- paul@keymail.dev pushed 974803588 appconfig: pin that SyncExec leaves a stamped route's old file alone
- paul@keymail.dev pushed e8fab7000 host: real unit ops for the config pass (batched show, daemon-reload, restart, flock)
- paul@keymail.dev pushed 4ce1b888d appconfig: reap drop-ins for units no route names, recording the reload owed first
- paul@keymail.dev pushed f1d93b5d9 appconfig: a drop-in read error keeps the pending marker, not clears it
- paul@keymail.dev pushed 04051c4c5 appconfig: reload, verify exactly one env file, restart marked units, report drift
- paul@keymail.dev pushed 382e38631 appconfig: fix round 1 — gate SyncUnits loops on syncable||Stamped, not unitDelivered
- paul@keymail.dev pushed df285e895 appconfig: SyncUnits prepares stamped routes behind a lock and the root-write rail
- paul@keymail.dev pushed b9baaad35 appconfig: the marker-owned drop-in and pending marker as pure file operations
- paul@keymail.dev pushed 8afa6e571 appconfig: split syncHost into prepare and commit with a three-state outcome
- paul@keymail.dev pushed d5a8fa1c2 appconfig: a stamped route is the root pass's; shared shape and name rails (#114)
- paul@keymail.dev pushed 3d8a7864e plan: console conversion extracted as restartWire for a pure test
- paul@keymail.dev pushed 5a4f100f5 plan: named-unit config delivery, twelve tasks from the approved spec
- paul@keymail.dev pushed fcd941af7 spec: named-unit config delivery, revised after codex round 3; approved
- paul@keymail.dev pushed 1729f812e spec: named-unit config delivery, revised after codex round 2
- paul@keymail.dev pushed f62f1a039 spec: named-unit config delivery, revised after codex round 1
- paul@keymail.dev pushed 012b682a4 spec: config delivery for routes that name their own unit (#114)