# Agent instructions — overdeck

audience: AI coding agents (codex included — this file is your entry point). Claude Code auto-loads it via the repo-root `CLAUDE.md` symlink; edit THIS file, never the symlink.

Working under `modules/harness/**` → also read `modules/harness/CLAUDE.md` (factory layout, config, permissions, tracing, tests).

## Factory reliability — MANDATORY

ANY change to factory phase, retry, gate, permission or commit behavior changes the machinery that judges every other change. MUST run `python3 -m pytest modules/harness/factory/tests/ -q` and keep it green. NEVER weaken a gate to make a run pass.

## UI work — MANDATORY

ANY change under `apps/web/src/**` or `packages/deck-ui/src/**` → read
`.claude/skills/od-ui-dev/SKILL.md` FIRST and obey it. Non-negotiable core:

- NEW pages: generic primitives come from Astryx (`@astryxdesign/core`,
  `@astryxdesign/lab`) FIRST. `@platform-modules/ui-primitives` is RETIRED for overdeck —
  NEVER reach for it in a new page. Existing pages keep their current primitives until
  ported; port only when the task already touches that page.
- deck-ui = overdeck-specific composition only, built ON whichever primitive layer its
  page uses.
- Compose existing `@overdeck/deck-ui` exports (`packages/deck-ui/src/index.ts` = the
  registry). NO hand-rolled tables/chips/menus/tooltips in apps/web.
- NEVER create a new primitive without explicit user approval — stop and report instead.
- Tokens only, both themes. Honest data — never fabricate values.
- Every deck-ui component registered in the `/design-system` gallery; barrel⊆gallery test
  and slopgate stay green — never suppress/baseline your own violations.

## Worktree isolation — MANDATORY

NEVER work in `/home/user/Projects/overdeck` itself (the shared main checkout) —
other agent sessions have uncommitted work there; `git restore`, `checkout --`/
`checkout .`, `stash push|pop|drop|clear`, `clean -f*`, `reset --hard` there
destroys it. Claim a worktree first: `~/.claude/bin/od-worktree add <slug>`,
then `cd .worktrees/<slug>` and work only there.

Enforced fail-closed, not by convention:
- Claude Code: PreToolUse hooks deny Edit/Write into the main checkout and the
  destructive git verbs above run against it.
- codex (`cdx exec`, incl. via `/ask-codex`), cursor-agent, and anything else
  launched under the agent shim chain: a `git` PATH shim blocks the same
  destructive verbs against the main checkout.

A refusal names the fix (`od-worktree add <slug>`) — run it, never retry raw.

Idle worktrees are auto-salvaged to `origin` `wip/*` + local vault
(`~/.local/state/overdeck/worktree-vault`). Recover with `od-wip list` /
`od-wip restore <ref>` — never dig manually.
Loose main-checkout WIP is parked on `wip/*`; the checkout stays ff-synced to `origin/main`.

## Delivery — MANDATORY

**Slice ends in owner-obtainable evidence: page, before/after number, or command output. Name that evidence FIRST, before writing code.**
**Infra inside the slice, never before it.** Thinnest vertical line reaching a surface.
**Enabling-only slice:** state what it unlocks and prove the capability exists. NEVER two consecutive.
**Slice N deploys before N+1 starts.** Done = owner can see/feel/use it.
**Ugly first.** Real data plain > styled fake.
**Incomplete work lands dark** — inert, flipped separately.
**Report what you did NOT verify. NEVER fabricate** — missing data renders as unknown.
**Owner-visible surfaces get owner language.** No jargon, internal stage names, or IDs on a card face, chip, or status line.
**Prefer the smallest slice that removes a whole failure class** over one that speeds a path up.

## Landing discipline — MANDATORY

**NEVER hand-type merge/push** — use the project lander (see Landing below).
**Same failure twice = loop: STOP and report.** Landed code with a named gap > unlanded perfect proof.
**Proof path broken ⇒ land, name the unverified step.** NEVER chase evidence through a seam another lane is repairing.
**Guards are facts, instructions are requests.** Rule broken repeatedly → make the wrong path fail. NEVER block the hand path before the automated one works.

## Delegation — MANDATORY

**Owner directives outrank stored records.** Conflict → follow the directive, flag the record. NEVER silently substitute a default; repeat owner-given model names VERBATIM.
**Lanes own disjoint files. Cap ~5.** Check the plan index for overlap BEFORE dispatching.
**Pin the exact command line in a brief.** Skill-doc references do not resolve for subagents.
**Ask for verbatim evidence when a report surprises you.** A fabricated finding retracts in one round-trip; an unchallenged one becomes doctrine.

## Machine — MANDATORY

**Agent compute runs on buildboxes** via wrappers. A dispatch failure is REPORTED, never absorbed locally.
**NEVER `git gc --prune=now` on a shared repo** — races conducting lands, destroys refs. Use `--prune=1.hour.ago`. For space: check `garbage:` in `git count-objects -vH`, sweep `.git/objects/pack/tmp_pack_*` older than 90 min (time-gate mandatory — a live `index-pack` owns recent ones).
**Share only content-keyed caches** (cargo target-dir, turbo, tsbuildinfo). NEVER share build outputs (`dist`, `build`, `.next`) — two branches colliding is a correctness bug.

## Tool discovery — MANDATORY

Overdeck-specific tools every agent must know, by trigger phrase (`intent → command`). Full detail: `deck-tools <query>` or `deck-tools <id>` (module-local tools live in that module's own `CLAUDE.md`).

- land this branch / push to main → `land`
- run the gate / check this passes before I ship → `local-gate --key <key> --mode full -- <command>`
- apply systemd units / manage fleet hosts → `deckctl fleet <verb>`
- run playwright tests / screenshot the dev server / visual-diff the UI → `e2e-remote --server "<cmd>" --wait-port <port> -- <driver-cmd>`
- make a worktree / claim a workspace for this task → `od-worktree add <name>`
- run this as root / I need sudo → `deck-sudo <command>`
- what claude sessions are running / kill a zombie session → `list-sessions`
- find where a symbol is defined / map an unfamiliar directory → `ft sym <Name>` / `ft map [dir]`
- build this feature end to end / run the factory on this → `factory <adw> <prompt-or-path>`
- write a probe/smoke/canary that calls a model → `model-test-fixture --purpose verification --backend <opencode|codex|north> ...`
- what agent processes are running / clean up orphaned sessions → `agent-sessions`
- find my lost worktree changes / recover deleted WIP → `od-wip list` / `od-wip restore <ref>`
- is the buildbox up / check build host health → `bb-status`
- delegate this to codex / review this diff with codex → `cdx exec -m <model> "<prompt>"`
- start ccr / bring up the router daemon → `bash ~/.claude/workflows/lib/ccr-up.sh <slug>`
- ask north / use the north model → `~/.claude/skills/north-orchestrator/na.sh --workspace <dir> --trust "<prompt>" --task-slug <slug>`
- run a container → `deck-podman <podman-args...>`
- reinstall the headless browser guard after a version bump → `install-headless-guard`

## Verification

Before planning, running, fixing, optimizing, or reporting tests/checks/gates, invoke `/od-testing` and follow it. Detailed test-order, temp-root, remote-sharding, timing, fake-clock, cache, and exact-revision receipt doctrine lives there; NEVER duplicate or bypass it here.

`pnpm --filter @overdeck/deck-ui test|typecheck`, `pnpm --filter web build|typecheck`,
collector: `bun test` in `collector/`. Playwright probes: SSE stream ⇒ `networkidle`
never fires — use `domcontentloaded` + `waitForSelector`.

## Runtime before Git — MANDATORY

Owner-facing Overdeck failure, live incident, blocked work, or laptop load fire → invoke `/od-emergency` FIRST and follow it through installed owner-visible proof. Runtime restoration MUST precede full gates, Git, queues, and review. Applies to product/UI/collector and local infra. Normal feature work with no active incident keeps branch→gate→land→deploy order.

Never cut safety floor: isolated candidate, smallest seam check, atomic rollback, exact-service scope, real installed-entrypoint proof. NEVER mutate served web output in place.

## Landing

DEFAULT: work on a branch; SUBMIT it via `.claude/scripts/ship.sh` (guarded trunk) and stop —
the standing conductor gates, lands, deploys, and cleans up on its own. NEVER hand-type the
merge/push cascade. NEVER wait or poll for the landing result — a brief's delivery duty ends at
"submitted"; the board (`/requests`) carries proof from there.

Missing `.claude/scripts/ship.sh` is executable setup, NEVER an external blocker. Follow
`modules/workstation/claude/skills/finishing-a-development-branch/SKILL.md`:

```bash
bash ~/.claude/workflows/lib/ship-init.sh <PROJECT_ROOT>                 # Phase A: inspect proposal + evidence; writes nothing
bash ~/.claude/workflows/lib/ship-init.sh <PROJECT_ROOT> --mode pr|merge-to-main [--testcmd "…"]   # Phase B: freeze mode from project facts
bash <PROJECT_ROOT>/.claude/scripts/ship.sh submit <branch> <worktree>
```

Inspect Phase A evidence internally. Choose Phase B mode from project facts. NEVER ask owner or hand-type publication cascade.

`ship.sh land <branch> <worktree>` (blocking: gate→land→cleanup in your own process) still exists
but is LEGACY — do not use it for new work; it is being phased out in favor of `submit` and will
start refusing with a pointer to `submit` once the daemon-only flag is live.

DIRECT LAND — owner-authorized escape hatch for runtime-first work above, or when the land queue is the bottleneck (queue
depth stalls landing for hours). NEVER a way to skip a red gate: you own the
verification the queue would have run.

```bash
/usr/bin/git -C <worktree> -c core.hooksPath=<empty-dir> push origin HEAD:refs/heads/main
# MANDATORY — landing without deploying ships nothing. Use the deploy clone's copy: it
# re-pins to origin/main every run, while the shared main checkout's copy can be stale.
bash ~/.local/share/overdeck/deploy/packaging/deploy-local.sh --now
```

`packaging/deploy-local.sh` without `--now` only ENQUEUES a request for the standing
consumer (`overdeck-deploy.service`) to drain — it does not deploy. `--now` is this
escape hatch's own emergency/bootstrap override that runs the deploy in this process
immediately; only use it when you actually need synchronous proof, not as a habit.

`/usr/bin/git` by absolute path: plain `git` is a PATH shim that reroutes `push`
into the land queue. Re-fetch and merge `origin/main` immediately before pushing —
main moves fast. A direct land skips the gate, so you own verification: run the
touched module's tests yourself and report what you did NOT verify.
