Files
Frank 8af40c402b chore(agent): commit the machine tier and the doctrine text the checkout was already running
Landing blocker for #61 and #63: the deployment checkout is 12 commits behind and
`merge --ff-only` refuses while tracked paths are dirty. Discard is not available here
(workspace policy: no `checkout`/`stash` on shared state), so the dirt is committed.

- `agent/APPEND_SYSTEM.md`: the point-of-use / one-work-log / PR-link doctrine, already
  byte-identical to `origin/main` (`cmp` against the trunk blob: no difference). No new
  prose — the commit exists so the trunk merge can proceed.
- `agent/config.yml` and `agent/managed-skills/**`: the machine-live tier the heartbeat
  owns (AGENTS.md § Live-sync tiers).

`ALLOW_SECRETS=1` was used, deliberately and after auditing the staged diff by hand: the
only credential-shaped strings in it are two copies of `AKIA0000000000000EXAMPLE` — the
inert all-zero AWS example id — and they appear inside the two skill pages that teach
that exact placeholder shape. This checkout is still running the pre-#61 hook; the merged
gate (value-scoped placeholder filter, `71601f7`) exempts this value, so the refusal
dies with this landing. No `--no-verify` was used: the gate ran and its verdict is
recorded here.

Refs #61
2026-10-21 01:44:51 -07:00

2.5 KiB

name, description
name description
new-fleet-service-checklist Add a new deployable service to serverAppConfigs: the four registration touch-points (two allowlists, planner, router) whose drift breaks the first-ever deploy.

Adding a new service to the serverAppConfigs deployer

A new --service <name> target must be registered in four files or the first deploy fails at a gate. Two fleet services (cadvisor, gpu-exporter) shipped with the client gate missed within a day of each other; the failure mode is Service 'X' is not deployed on <target> from deploy.sh, exit 2 — before SSH.

The four touch-points (per target host)

  1. scripts/deploy.sh → valid_service() case: add <target>:<svc>. Client gate — the one people forget.
  2. scripts/deploy-remote.sh → service_is_allowed() case: add <target>:<svc>, and the dispatcher case branch <svc>) deploy_<svc> ;;.
  3. scripts/deploy-plan.py: the name in the target's service set (DANKCLAW_SERVICES / DANKSERVER_SERVICES) + SERVICE_ORDER, plus a path map so edits to the service's own files select it (for scripts/<svc>.* host processes, map the exact filenames like the signal-relay/gpu-exporter maps do).
  4. scripts/test-changed.sh: route the service's files to its seam, else focused test runs skip it (full tests/run.sh still covers).

Sanctioned exception: dankclaw:searxng-network is client-only (network unit, no remote handler) — the drift test exempts it.

Enforcement + local verification

tests/deployment_flow.bats test "the client and remote allowlists agree per target" diffs the two extracted lists. Verify before pushing:

grep -oE 'dank(claw|server):[a-z0-9-]+' <(sed -n '/^valid_service()/,/^}/p' scripts/deploy.sh) \
  | grep -v dankclaw:searxng-network | sort -u > /tmp/cli
grep -oE 'dank(claw|server):[a-z0-9-]+' <(sed -n '/^service_is_allowed()/,/^}/p' scripts/deploy-remote.sh) \
  | sort -u > /tmp/rem
diff /tmp/cli /tmp/rem   # must be empty

Also: a # comment after a trailing \ inside a bash case pattern list breaks line continuation (syntax error) — annotate on its own line above.

Gotchas

  • Merge ≠ deploy: deploy.sh <host> --service <svc> must still be run per host; a merged service is dead code until then (GPU stats "not showing" was exactly this).
  • deploy.sh refuses to run anywhere but a clean main checkout: the canonical dev checkout is /home/blank/Projects/serverAppConfig (not the session ~/.omp/wt/... worktree, not the build worktree).