Status: procedure and history reference. The surface-agnostic contract lives in AGENTS.md §17 and stays always-on. This file holds the guard implementations, the BI trail, and the full §7 decision text. Single source of truth for the decisions themselves remains the unified-delivery-surfaces spec. Relocated from §17 by BI-0020D511 Phase 1; no rule was dropped.
→ Spec (single source of truth): docs/superpowers/specs/2026-06-05-unified-delivery-surfaces-execution-alignment-design.md. This section is the operational pointer; the §7 decisions are WWMD-ratified and final.
- Four peer surfaces, one process. DPF delivers through Claude Code, Codex CLI, Grok, and the embedded Build Studio — peers, not a hierarchy. None is privileged; work never depends on any one being healthy. All four advance the one common evidence-gated lifecycle (
ideate → plan → build → review → ship), right-sized by(type × size); each transition runs the gate check and nothing is rubber-stamped. (Grok joined as a first-class external coding surface per2026-05-31-grok-first-class-support-design.md; the three external CLIs — Claude Code, Codex, Grok — are the host-worktree surfaces, Build Studio is the embedded surface.) → kernel principle - No surface is mandatory — choose by fit; “Build Studio for all development” is retired. Any earlier guidance that all development must go through the embedded Build Studio (it predated this section) is retired by founder directive (2026-06-26). The peer principle above is operational, not aspirational: pick the surface that fits the work and the available tooling. An external Claude Code / Codex / Grok build — implement in a host-worktree, claim a workroom, record evidence, ship the PR — is fully equal to an embedded Build Studio build and must never be force-routed through the embedded pipeline. Embedded BS is the right tool when its in-portal codegen/review fits; it is not a gate every change must pass, and delivery must never block on it being healthy (e.g. when the embedded pipeline is degraded or its reviewer is the bottleneck, do the work as an external build). → kernel principle
- Large/complex work may run externally even when centrally tracked. The desire for central tracking is satisfied by the MCP/capsule/evidence plane, not by forcing work into the embedded BS executor. Build Studio is intentionally narrower than the host CLI surfaces today; when a task is too large, subtle, cross-cutting, tool-sensitive, or long-running for BS to handle well, choose an external host-worktree surface and keep it centrally visible through a Workroom, backlog links, evidence records, and PR health. Do not tell the operator “this must go to Build Studio” merely because it is feature work.
- MCP is the coordination plane. Work tracking, claims, and gate evidence live in the DPF MCP substrate (backlog/
FeatureBuild/WorkCapsule, workroom + lease claims, evidence tools), regardless of Build Studio. If it isn’t in the MCP plane, it didn’t happen — a surface that works without claiming a workroom and recording evidence is invisible to coordination and cannot advance a gate. → kernel principle - Claim a workroom before you work — every surface, including the external CLIs. Because the MCP plane is the coordination substrate, an external agent (Claude Code, Codex, Grok) opens a Workroom at the start of an effort —
create_work_capsulefor new work, oradopt_worktreeto attach an existing branch/worktree — then records evidence at phase boundaries (record_external_development_evidence,record_capsule_evidence) and releases on exit, so the work shows up in the same progress/evidence/document tracking as an in-portal build. Build Studio auto-attaches its workroom; external surfaces must claim theirs. As of 2026-08-28 that claim is automatic and enforced. both worktree-creation paths claim before they hand the tree over — the Claude Code hook (worktree-create.mjs) and the shell script the rest of this runbook uses (scripts/new-dev-worktree.sh, viascripts/bind-worktree-cli.mjs) — so a worktree is born bound whichever way it was made, andpackages/dpf-skill-pack/hooks/workroom-claim-guard.mjsrefuses an edit or a commit on a feature branch that no live claim covers (DPF_WORKROOM_CLAIM_ENFORCE=0downgrades it to advisory for an install where binding genuinely cannot run;DPF_ALLOW_UNCLAIMED_WORK=1is the recorded per-command bypass). Until then the rule was prose and behaved like it: 31 of 91 live branches carried no binding at all, a 35% miss rate unchanged since the rule was written. Runnode scripts/reconcile-workroom-bindings.mjs(dry run;--applyto bind) to reconcile branches created before this, or after any period where MCP was unreachable — bind-at-birth only ever governs the future. Both paths are named deliberately: binding shipped on the hook path alone first, and coverage measured 95% right after reconciliation then fell back to 82% within a day as new branches arrived through the shell path. Automating one of two entry points relocates the leak rather than closing it. Ifadopt_worktreerefuses withbranch_occupiedagainst a complete capsule, that branch’s work is finished and the worktree is a leftover: reap it or start a new branch rather than reopening closed work. Degrade gracefully: if the MCP plane is unreachable, do the work and reconcile the workroom afterward — never block local editing on workroom availability (work never depends on any one surface being healthy). Resuming another agent’s in-flight effort — start-by-one/finish-by-another — is the workroom-handoff path being built under EP-UNIFIED-TRACKING (BI-51787ECD); until it lands,adopt_worktreethe in-flight branch and continue from the workroom’s recorded evidence. → spec2026-06-19-unified-build-studio-tracking-all-surfaces-design.md - Central WIP via the workroom plane — the unit of WIP is the Workroom, not the Build Studio build (founder-directed 2026-06-26). Sandboxes and shared singleton leases are finite, so the platform must see total WIP across all four surfaces. Every surface registers its workroom centrally (Build Studio auto-attaches; the external CLIs
create_work_capsule/adopt_worktree), and the WIP count and any capacity limit derive from active workrooms across all surfaces, gated by the real scarce resources — the shared Build Studio sandbox and the shared:3001/singleton leases — not a Build-Studio-only build count. The BS cap (apps/web/lib/build/wip-cap.ts) gates only BS-sandbox contention; external Claude Code / Codex / Grok work runs in its own host worktree, is never blocked by the BS cap, yet its active workrooms still COUNT in the unified WIP (apps/web/lib/build/unified-wip.ts). Funneling work through Build Studio to gain central tracking is retired and futile — external code work is first-class, made visible by workroom registration, not by funneling. → kernel principle - Governance approves evidence, not provenance — the keystone. A gate reads only its required evidence fields and never branches on which surface produced them; that is exactly what makes the surfaces interchangeable. → kernel principle
- Thin adapters behind a stable contract. Claude Code, Codex, and Grok ship updates frequently; the surfaces are swappable adapters behind the gate/evidence + MCP + lease/worktree/sidecar contract. No surface-version-specific mechanics in the doctrine — if a rule would break when Claude, Codex, or Grok bumps next week, it belongs in a thin adapter, not the contract.
- Hide complexity from layman users. The coordination plane is backstage. Non-technical users see work + status + outcomes (progressive disclosure via the AI Coworker panel, §7 Q3), never worktree names, container ids, evidence JSON, or gate predicates; operator-grade plumbing stays admin-only.
§7 decisions — hard rules (WWMD-ratified 2026-06-05):
- Worktree canonical location = dedicated sibling
D:/DPF-worktrees/<topic>⟦runtime: install-local path — Windows shape; §4 gives the macOS/Linux equivalent⟧ for all three host CLI surfaces (Claude Code, Codex, Grok). The tool-native.claude/worktrees/<name>nesting inside the root clone is not the convention — treat it as a hard error to migrate. Every worktree is born governed (topic branch offorigin/main, MCP + toolchain seeded,COMPOSE_PROJECT_NAMEisolated, workroom claimed) and is reaped whenidle/done(janitor BI-DBF3F426). → kernel principle - Tooling-upgrade = operator-triggered quiesce-reap-upgrade. Session = claimed workroom; session end reaps its sidecars (
app-server,node_repl, npx MCP children). Upgrading Claude Code / Codex (incl. the WindowsApps Store package) runs a first-class operator-triggered quiesce → reap → upgrade → resume routine; orphaned sidecars must never pin a tool against update. → kernel principle :3001and every shared singleton are lease-gated. Runtime-bound gates run only throughclaim_nonprod_environment_lease(environmentKey="local-integration-ci"); the:3001Contributor preview folds into that lease (§7 Q5). ⟦runtime: install-local port — the lease rule is doctrine, the number is not⟧ No per-branch CI images, no silent re-bind of a held shared singleton, no ad-hocdocker run/compose upfrom a surface, and never reachable from outside the host — no tunnel, public URL, or non-loopback bind, because the preview writes to the live database and holding the lease permits use, never exposure. Deterministic preview claim keys preserve FIFO while active or queued; released, cancelled, or expired history advances through bounded monotonic attempt keys without changing the owning session or target-worktree branch identity. → kernel principle- Admission reserves the work the claimant declares. Exact gates request the canonical slot-manifest capability and therefore reserve the builder and host-stage envelopes before admission. Contributor previews request no runner slot, so they remain in the same FIFO/provider-exclusion pool but use the ordinary host-safety floor; reserving an unused build stage can deadlock the preview that owns stale-runtime cleanup.
- Contributor preview authority is live, not ceremonial.
scripts/dev-portal-lease.sh refreshsamples host pressure through the samelocal-ci-host-pressureprimitive as the gate before admission, then remains in the foreground as the preview’s lease keeper. Keep that process running for the whole UX exercise. It renews below the registry heartbeat cap; a renewal/admission failure or process stop shuts downdev-portalbefore releasing its lease. A detached container with no keeper is not a governed preview, even if an earlier command printed a lease id. - Enforced, not just documented. A
PreToolUseguard (lease-guard.mjs, in the pluginhooks/hooks.json) refuses ungoverned dev-server launches (pnpm/npm/yarn dev,next dev,turbo dev,dev-portal-start). Governed path:claim_nonprod_environment_lease→ run on the leased runtime, heartbeat withrenew_nonprod_environment_lease, release on exit (theSessionEndreaper also releases). Emergency bypass: prefixDPF_ALLOW_UNGATED_SERVER=1. Codex and Grok inherit the same guard (BI-CA0ED781); functional confirmation there is pending, so comply by construction (claim before you launch). Leases are TTL-capped (MAX_LEASE_TTL_MS) and reaped if heartbeating stops. - Root-clone protection — enforced. A
PreToolUseBash guard (root-clone-guard.mjs) refuses a recursive-force delete (rm -rf,Remove-Item -Recurse,git clean -fdx) that would follow a junction into — or target — the shared root clone, and raw root-clone git state movement (git switch/checkout/reset/pull/merge/rebase) that strands new sessions on a dirty tree. Junction-safe removals stay allowed (non-recursivermdir,git worktree removewithout--force).git worktree remove --forceis NOT junction-safe on Windows — it follows anode_modulesjunction into the root (see below, BI-F6AC1A56). Emergency bypass: prefixDPF_ALLOW_ROOT_CLONE_MUTATION=1. Structural fix: the canonical sibling baseD:/DPF-worktrees/<topic>via aWorktreeCreatehook (BI-6B02FEE5) + the worktree janitor (BI-DBF3F426). - Root-project data-volume protection — enforced. A
PreToolUseBash guard (compose-guard.mjs) refuses a rawdocker compose up/create/restart/runthat would (re)create PostgreSQL on the rootdpfproject, plusdown --volumeson it — the path that once silently swapped the live DB onto a stale volume. Governed update path:/ops/self-upgrade;scripts/redeploy-portal.*andpromote.shuse--no-deps portaland stay allowed, as do any isolated project (COMPOSE_PROJECT_NAME=dpf-<topic>/-p),build, and plaindown.scripts/lib/compose-safety.mjscarries the same rule for harness callers. Bypass:DPF_ALLOW_ROOT_COMPOSE_UP=1orDPF_ALLOW_DESTRUCTIVE_COMPOSE=1. Backstop: a boot-time DB-continuity check (apps/web/lib/operate/db-continuity.ts) fails loud on a reverted volume. - Auto-worktree placement — enforced for Claude Code (BI-6B02FEE5). A
WorktreeCreatehook (packages/dpf-skill-pack/hooks/worktree-create.mjs, same pluginhooks/hooks.json) replaces Claude Code’s defaultgit worktree addso an auto-created worktree (the--worktreeflag / subagentisolation: "worktree") lands at the canonical sibling base<dirname(root)>/<basename(root)>-worktrees/<name>(e.g.D:/DPF-worktrees/<name>,~/dpf-worktrees/<name>) offorigin/main— never nested inside the root clone at.claude/worktrees/. This is the full-enforcement, auto-create form of the contractscripts/new-dev-worktree.shalready applies to the MANUAL path. It fails safe: on any error it falls back to the default nested location (still protected by the root-clone guard above), so worktree creation is never broken. Codex/Grok have noWorktreeCreateevent — they get the canonical base viascripts/new-dev-worktree.sh(adpf worktreeCLI wrapper is the follow-up). Live-tested on this host; functional confirmation of Claude’s consumption of the hook output is pending, like the lease-guard. - Worktree removal is junction-safe (BI-F6AC1A56). ⟦runtime: Windows-only hazard — junction-follow does not occur on macOS/Linux; still route removals through the janitor⟧ Never
git worktree remove --forceby hand on Windows (junctions follow into the root clone). Route removals throughscripts/lib/junction-safe-worktree-remove.mjs/ the janitor. The helper unlinks every link under the worktree’snode_modulesdirectories without following it, including scoped@dpf/*junctions inside a realnode_modulesdirectory; git cannot delete those on Windows and would leave a half-deleted tree (BI-995E17AB). Hygiene: session reaper is primary; fleet soak is flag-gated; dry-run free; live Tier-A only with operator go — skilldpf-worktree-hygiene(BI-413FD81C).
- The live install advances only via the self-upgrade pipeline, and a built image carries the identity of its bytes — stamp == built HEAD == target, asserted pre-swap,
DEPLOYED_SHApopulated, fail loud on divergence (BI-5B6C1C35). No surface hand-advances the root clone HEAD or rebuilds the portal to “update”; never trust a version label over the bytes. → kernel principle - A Workroom for delivery work is born owned, with its exact source (BI-36FC2981).
claim_backlog_item_for_workandadopt_worktreewith abacklogItemIdmake the person the work is for the room’s Process Overseer and admit the assistant acting for them as a contributor, in the same transaction as the claim. An existing owner and an earlier removal always stand. PassbaseShaandheadSha(full 40-character SHAs): without both no reviewer can be routed to the room’s source, so an adoption missing them returnsdata.identityRepair, a packet you can replay as given with the missing SHAs added. The claim’s readback refuses a room that does not end with exactly one owner, or whose recorded head differs from the one requested. Rooms created before this rule get their owner from the workroom drive (delivery-room-ownership.ts): the requester, lease holder or creator who is a person, otherwise the user who first recorded on the room. The drive also runs a room’s tasks for its requester, not its creating assistant. - A replacement assistant takes over its person’s room with one approved call (BI-821EEB18). When a session ends, the person’s next assistant is a different agent that has never been in the room. Every call naming the room then returns
workroom_assistant_not_admitted, not a dead-end “ask its owner”, with the exactreassign_workroom_executorcall indata.handover. That call is let through only if the person owns the room (an active Process Overseer or accountable participant, or the creator, requester or holder of a room nobody oversees) and nobody has admitted, narrowed or removed that assistant. Case policy and clearance still apply. The tool changes authority, so the person approves the handover and the approval carries it out; an assistant an operator has graduated for authority changes is not asked (seen live 2026-09-24 forexternal-claude-code). The executor change and the assistant’s admission as a contributor to that one room are written in one transaction, and the room records acoworker-joinedactivity with sourcehandover. From then onget_workroomgives the assistant the recovery packet and next action, with no chat history needed. Another person’s assistant, and one removed from the room, are still refused. - A Workroom for a backlog item must be BOUND to it, not merely anchored at it.
Workroom.backlogItemIdis the column every subject lookup keys on — reviewer recovery ingoverned-work-claim.ts, andsubjectWhereinbacklog/initiative-readiness/repository-artifact.ts, which sits behind plan coverage and canonical-design resolution. AnoutcomeAnchornaming the item is invisible to all of them.create_workroom,adopt_worktreeandclaim_backlog_item_for_workall resolve a suppliedbacklogItemId— or abacklog-itemoutcome anchor — onto that column, refuse an id that does not resolve rather than creating an unbound room, and verify the stored row carries the binding before reporting success (a report of the request is not a report of the result). Historic rooms created before this may be anchor-only and therefore unreachable from the completion gate’s “no live Workroom is bound to this item” recovery;node scripts/reconcile-workroom-bindings.mjsis the reconciliation path. Fixed for adoption and for the argument name in earlier passes (see the comments inadopt-backlog-binding.ts), and for creation in a later pass.
Task-specific operating rules
- Four peer surfaces, one process. Claude Code, Codex CLI, Grok and the embedded Build Studio are peers running the same process — no surface is mandatory, choose by fit. “Build Studio for all development” is retired. → kernel principle
- MCP is the coordination plane. Work tracking, claims and gate evidence live in the DPF MCP substrate — not in a surface’s local state. Large/complex work may run externally and still be centrally tracked. → kernel principle
- Claim a workroom before you work — every surface, including the external CLIs. The unit of WIP is the Workroom (founder-directed 2026-06-26, renamed 2026-08-15), not the Build Studio build. → kernel principle
- Governance must earn its cost. Reuse relevant evidence and authorization; a phase change alone needs no fresh consent. Gates serve a decision or protection, not ceremony or client identity. See evidence doctrine.
- One resilient pipeline, enforced by gates not client rigor. Compile-ready worktree, fast local gate, evidence contract at workroom transition, cloud heavy-build safety net, liveness reaping — every surface applies it because each stage is a platform gate. → process spec · EP-056D2A5E
- Thin adapters behind a stable contract. The CLIs ship updates frequently; keep surface-specific code at the adapter edge so an upstream release never reaches the process.
- Hide complexity from layman users. The coordination plane is backstage; non-technical users see work, status and outcomes.
- Worktree canonical location = the dedicated sibling base ⟦runtime: install-local path — Windows shape; §3 gives the macOS/Linux equivalent⟧ for all three CLI surfaces, not the tool-native nesting. Every worktree is born governed and reaped when idle. → kernel principle
- Tooling upgrade = operator-triggered quiesce → reap → upgrade → resume. Orphaned sidecars must never pin a tool against update. → kernel principle
:3001and every shared singleton are lease-gated ⟦runtime: install-local port — the lease rule is doctrine, the number is not⟧ viaclaim_nonprod_environment_lease. No per-branch CI images, no silent re-bind, no ad-hocdocker run/compose upfrom a surface. Hook-refused, so §1’s refusal rule governs what to do when one fires.- A built image carries the identity of its bytes — stamp == built HEAD == target, asserted pre-swap.
Contributor preview binding and cleanup
Preview startup resolves the canonical install settings and overlays, then binds
/workspace to the clean admitted worktree. The controller generates development
password/signing material in memory, validates Compose config before runtime
mutation, and uses explicit preview services with --no-deps. Initialization must
succeed before dev-portal starts. Docker mount/commit labels and the served health
identity must agree. No hand-built live image is an acceptable substitute.
A queued claim stops its shell caller: the returned durable TaskRun resumes the
wait. A terminal claim stops too; never scan historical :rerun-N keys. A new
explicitly wanted attempt may supply a new DPF_DEV_PORTAL_CLAIM_KEY. Durable
resume supplies its original lease and task through DPF_DEV_PORTAL_RESUME_LEASE_ID
and DPF_DEV_PORTAL_TASK_RUN_ID.
WWMD DI-E1203C00715D supports ordinary cleanup only for a verified principal and its exact owning session. Current leases lack principal provenance, so their release remains an authority action requiring approval. Report the exact lease and owning session and the returned approval link; never suppress the request. The existing Concierge envelope-expiry sweep settles lapsed proposed/approved requests using the envelope state machine. It does not silently approve or replay them. Restricted connections never receive grants from the client.
Preview browser authentication uses issue_ux_verification_sign_in with the
admitted preview lease and active verification Workroom session. The source
Workroom may remain paused under its original session: WWMD DI-FBEC4720D1DA
requires the same authenticated principal and repository for both rooms, an
active verifier lease, and the source room’s exact recorded SHA. The platform
checks those identities again before returning the session and issues in the
preview database with its
own signing key. The sweep consumes that one-time link and saves its own browser
storage state. Production cookies and operator passwords are not preview inputs.
For shared-header changes, record the complete touched-route inventory first.
Use desktop (1280×900), mobile (390×844), normal and Simple (worker) navigation,
light/dark themes and representative persona/account states. The local 40-route
feedback cap is not coverage: --exhaustive --fixture-map <file> selects all
touched static and dynamic routes. A fixture map must name the admitted source
SHA, lease, base URL and every dynamic concrete route. Missing fixture paths,
redirects, failed routes or incomplete accounting block the sweep.