Skip to content
Skillv1.0.0

port-daddy-internal-dev

Contributor manual for agents working ON the Port Daddy codebase itself — the daemon, MCP server, FleetBar / Fleet Control Center, website, CLI surface, distribution mirrors, internal recovery ledger,

by curiositech(0) 0 installs
Free
Sign in to install

Free account. Installing gives you the manifest plus copy-paste snippets.

See reviews

About

Imported from curiositech/port-daddy (skills/port-daddy-internal-dev/SKILL.md). Install upstream with npx skills add curiositech/port-daddy --skill port-daddy-internal-dev. Copyright stays with the author (FSL-1.1-MIT).

Port Daddy — Internal Contributor Manual

You are editing the Port Daddy codebase itself: the daemon, MCP server, FleetBar, Fleet Control Center, website, CLI, SDKs, distribution surfaces, the recovery ledger, and the internal actor inboxes. This skill is private to the port-daddy repo because most of what's here would be noise on a project that just uses Port Daddy.

For the public skill — how any agent on any project should drive Port Daddy — see the sibling port-daddy-agent-skill.

NOT For

  • Agents on other projects driving Port Daddy as a coordination tool — that's port-daddy-agent-skill.
  • General coding without a Port Daddy surface change.
  • Distribution to public skill catalogs.
  • Replacing the live daemon, recovery ledger, or actor inboxes as sources of truth — those still come first.

Operator vs Agent — the product rule

When designing or changing a Port Daddy surface, the test is "would the operator have to drop to a terminal to do this routinely?" If yes, the design is wrong. The operator's surface is FleetBar + the dashboard. pd CLI exists for agents and emergencies. Every routine operator action (configure credentials, restart daemon, see open feedback, harvest a roadmap entry, ack a salvage item) must have a FleetBar button or dashboard panel as its primary surface — CLI is the secondary path for agents and scripts.

Contributor implication: when you add a new actuator or data source, ship the FleetBar/dashboard affordance in the same slice when reasonable, or file a high-severity FleetBar feedback entry so cartographer promotes it to the roadmap before the CLI-only path ships to operators. Examples in flight: fleetbar-secret-management-with-provider-deeplinks, fleetbar-console-must-support-zoom-and-text-scaling.

How to work a slice (operating expectations)

The full posture lives in AGENTS.md § Agent Operating Expectations. The repo-specific mechanics:

  • Coordinate + pay rent. Clean linked worktree off origin/main, pd begin … --lifecycle durable, pd session files add before editing, a pd note per commit (the Coordination Guard enforces it), pd done at the end. When inheriting stale work, prefer pd takeover <old-session-id> [reason] (or pd session takeover <old-session-id> [reason]) over deleting or silently reusing the old session; notes and claim history are append-only evidence.
  • Supplant, don't migrate. No users yet (operator directive, 2026-08-22): a new mechanism that overlaps an old one replaces it exhaustively in the same slice — delete the legacy path, fix every caller, no compat shims, no "legacy mode" flags, no downgrade fallbacks, no deprecation windows. Backwards compatibility only when the operator explicitly asks, per surface.
  • Assume broken; verify both ends. After any write, read it back from the surface that should serve it, and prove cold start (daemon down → elegant operator instruction, never a stack trace), worktrees, a second user, and the GitHub round-trip. A green exit code is not evidence.
  • Keep daemon actuation singular. On canonical macOS, launchd alone starts, stops, replaces, and resurrects the daemon. The daemon publishes readiness; Bosun detects a dead/stale generation and asks launchd for replacement; Doctor/status/native UIs observe the same snapshot. Never add a detached fallback to pd start or pd restart, never silently walk the canonical port, and do not call runtime health green unless launchd PID, /health, PID/port files, heartbeat, listener, and binary hash converge.
  • Confirm the telemetry trail. Calls must show up in pd usage AND in the transcript saves (lib/transcripts.ts), and durable state must ride the Cloudflare fabric (lib/relay-client.ts) so posterity is cheap and survives the container — verify the read-back, don't assume it.
  • Dogfood novelly + capture wins. Exercise a CLI/MCP/SDK surface you haven't before each slice; when a hard-won gambit lands, write it into this skill (or the public port-daddy-agent-skill if it generalizes).
  • Generalize. Features must work for non-tsx/non-Rust repos, remote harbors, other machines, and shared GitHub teams — not just this checkout.
  • Whitepaper check. Reconcile coordination/kernel work against the seven whitepapers registered in website-v2/src/data/whitePapers.ts (Legible Swarm, Single-Writer Kernel, Spawn to Person, Harbor Economy, Anchor Protocol, Bonded Commons, Federated Harbor); note drift in the PR.
  • Skill matching. If you're missing a matching skill, pause and run pd jury-rig query. It uses Port Daddy's native hybrid catalog and guarded reference loader; no external skill runtime is required.
  • Launch work through PD spawn (pd spawn, SDK spawn(), or MCP spawn), never a raw side-channel — so the work is registered, sandboxed, budgeted, salvageable.
  • Managers orchestrate; workers author PRs. A manager lane delegates implementation edits, PR body drafting, and PR authoring to worker sessions. The manager reads returned artifacts, checks evidence, steel-mans the strongest case against shipping, retunes roles by round, and decides whether work advances.
  • Target: durable roles keep ledgers. Notes are immutable evidence; role ledgers are curated projections for future briefings. Do not claim this as a fully shipped runtime unless the branch/live daemon proves it. Ledger entries that summarize operator preferences or cross-repo tactics must carry provenance, redaction/sync posture, account/team authority, and staleness.
  • Keep README.md current in the same PR when a slice changes a documented surface.
  • A daemon/CLI-surface change ships atomically with its release. If your slice alters the shipped pd — a new/renamed/removed verb, what the single binary registers, anything an operator sees after brew upgrade — the version bump, the embedded-version sync, and the Homebrew formula roll are part of the SAME change, not a follow-up. A landed binary that disagrees with the formula is the drift version-drift-guard and tests/unit/embedded-version-sync.test.js are there to catch; do not let them be what discovers it. Full rule and the "did the surface actually change?" test: AGENTS.md § Release.
  • Prove Squid from release cargo. Adding a hook to source is not enough. Declare every required tentacle/identity/steering asset in release-artifacts.json, stage it in release.yml, then run scripts/smoke-squid-release.mjs against the compiled binary outside the source tree. The proof must cover Claude/Gemini project config, Codex/agy user config, exact-root gating, statusline, Pilot SessionStart, /squid, and machine-readable READY/LIVE state. A source-suite pass cannot substitute for this artifact-boundary proof.
  • Prove native dependencies again after macOS signing. Hardened runtime can change dynamic-loader behavior after an unsigned build smoke has passed. Run the native import through the exact signed dist/pd release pair, with DYLD_* absent, before soak or archive sealing. Package dylibs behind a verified executable-relative Mach-O rpath and keep com.apple.security.cs.allow-dyld-environment-variables out of the release entitlements; do not trade a packaging defect for an injection surface. FleetBar release packaging must also sign every nested Mach-O under the bundled payload inside-out; Bun JIT entitlements belong on the Bun executable only, never on ordinary .dylib runtime libraries.
  • Keep coordination content bounded; the SITREP is the visible value surface. Coordination content (alerts/pheromones) stays invisible and bounded: with the SITREP dial off, a healthy no-op turn emits zero bytes and no status message, never starts the daemon or shells through the full pd CLI, and filters file traces to the exact project root before rendering them. Keep that coordination block to one heading plus at most two facts, clamp its context budget, and keep harness deadlines at one second. The regression proof must include thousands of irrelevant matrix entries while still surfacing one fresh exact-root fact. Installer tests must also prove atomic, idempotent config writes and migration of duplicate legacy Codex registrations without disturbing user hooks. The end-of-turn SITREP compulsion is the deliberate exception (operator doctrine reversal, 2026-08-22): governed by the per-repo sitrep.endOfTurn dial (off|suggest|enforce, default enforce; PD_SITREP env override wins, then agent.config.json.portdaddy/sitrep.json.portdaddy/project.json), the pd-hook-prompt tentacle and the SessionStart Pilot inject the end-of-turn SITREP table contract — a constant-size standing block that rides outside the coordination byte cap. Do not re-bound or silently strip it; repos that want quiet turns dial it off explicitly.

Core Decision Tree

flowchart TD
    start[Edit lands on port-daddy] --> what{What changed?}
    what -->|CLI surface| cli[Update CLI help → references → website /docs/cli → MCP tools → skill bundle. Send Lookout drift report when scope > 2 surfaces.]
    what -->|Daemon API| api[Update lib + routes + OpenAPI + SDK ref. Run pd integration ready signals. Audit pd guard for new contracts.]
    what -->|MCP tool| mcp[Update mcp/server.ts + handshake test + skill catalog. Re-validate all 10 tool schemas.]
    what -->|FleetBar / Console| ui[Update Mac app + screenshots in references/fleetbar-and-console.md. Test from a clean install root. For updates, pin the exact release and prove checksum + Developer ID + notarization + rollback + relaunch.]
    what -->|Distribution mirrors| dist[Update brew formula sha256. Bump version in 4 places. Rerun install.sh end-to-end. Lookout review.]
    what -->|Internal actor| actor[Update routes/+ lib/ owning module + actor-roster.md + decisions/who-do-i-message.md. Backfill inbox tests.]
    what -->|Recovery ledger| ledger[Edit docs/recovery/CURRENT-WORK.md only via Cartographer/Navigator. Don't bypass the actors.]
    cli & api & mcp & ui & dist & actor & ledger --> ship[Reconcile + guard + tag + push]

Internal Actor Embodiments

The five actor roles in the public skill are concepts. In this repo, each one has a concrete embodiment: a route, a lib module, a fleet persona, and a status surface. When you edit any one of these, you are editing a piece of the actor's body, and the corresponding inboxes, contracts, and operator surfaces must stay coherent.

Actor Route Lib module Fleet persona Status surface
Coxswain routes/claims.ts, routes/locks.ts lib/claims/, lib/locks/, lib/symbol-index/ agents/coxswain.yaml (when present) claim density + lock health in pd briefing
Navigator routes/sessions.ts, routes/recovery.ts lib/sessions/, lib/salvage.ts agents/navigator.yaml docs/recovery/CURRENT-WORK.md
Cartographer routes/cartographer.ts lib/roadmap-progress.ts, lib/feedback.ts agents/cartographer.yaml (also lives at .claude/agents/cartographer/) .cartographer/status.md, IDEAS-TROVE.md, DOGFOOD-FEEDBACK.md
Lookout routes/lookout.ts release-surface scanners under lib/ fleet/documentarian.sh (current shell-script form) drift reports posted to lookout inbox
Quartermaster routes/spawn.ts, routes/fleet.ts lib/spawner.ts, lib/cost-tracker.ts, lib/backend-readiness.ts, lib/resource-governance.ts agents/quartermaster.yaml spawn budget + readiness in FleetBar

Shipwright is a sixth, internal-only role: it owns skill-bundle ingestion, archetype classification, and survey aggregation across the fleet. Lives at lib/shipwright/{archetypes.ts, skill-index.ts, survey.ts} and routes/shipwright.ts. Tests under tests/unit/shipwright-*.test.js. Don't expose Shipwright in the public skill — it's a port-daddy-internal abstraction.

Recently Shipped Surfaces — contributor module map

These landed on main in the last few weeks. When you touch one, you own its full mirror set (Release-Surface Drift, below). Each is a release surface: CLI help, manifest, MCP catalog, and skill docs must move with the code. The public-facing summary lives in skills/port-daddy-agent-skill/SKILL.md § Recently Shipped Surfaces — keep the two in sync.

Surface ADR Edit these together
Relay — cross-machine pub/sub docs/adr/0049-relay-architecture.md Worker apps/relay/ (D1 schema apps/relay/schema.sql, wrangler.toml) · daemon routes routes/relay.ts · outbound SSE lib/relay-client.ts · CLI cli/commands/relay.ts · MCP relay_status in mcp/server.ts
Cloud coordination peer — offline-first CRDT federation docs/adr/0092-suggestibility-ladder-and-cloud-coordination-federation.md §4 shared wire/fold lib/coordination-ledger.ts · local SQLite outbox/importer lib/coordination-peer.ts · relay DO/auth/routes apps/relay/src/coordination-room.ts, apps/relay/src/coordination-auth.ts, apps/relay/src/coordination.ts · real sandbox daemon apps/fleet-executor/src/sandbox-runner.ts · compiled acceptance smoke scripts/smoke-coordination-peer.sh
Dispatch — autonomous feature-dev queue ADR-0035 cli/commands/dispatch.ts (+ deprecated alias cli/commands/nightshift.ts) · lib/dispatch/{runner,spawn-adapter,queue,state-machine}.ts · routes/dispatches.ts · pd review · docs/proposals/pd-nightshift.md
Coast Guard — sandbox + compulsion rent docs/adr/0050-coast-guard.md lib/coast-guard.ts (buildSeatbeltProfile, wrapWithSandbox) · lib/coast-guard/{compulsion,compulsion-facts,egress-meter}.ts · default in lib/spawner.ts · read path cli/commands/coast-guard.ts (operator_coast_guard feature) · requireNotePerCommit wiring in the Coordination Guard (cli/commands/guard.ts)
Attest — honest self-report ADR-0045 cli/commands/attest.ts · lib/attest.ts · lib/attest-invariants.ts · GET /attest · the attest manifest feature
Tube — conversational pipe cli/commands/tube.ts · message-channel store · pd_discover listing

Contributor gotchas specific to these:

  • Dispatch is dry-run by default. pd dispatch run <id> prints the plan; only --really-run spawns. The worktree root is ~/coding/tmp/port-daddy-dispatch-<id> (never os.tmpdir() / /tmp). If you change the spawn path, keep it under the scratch root — the Coast Guard reclaim gate (isReclaimableSandbox) assumes disposable sandboxes live there and the operator's main checkout does not.
  • No artifact means no reap. A review launch may finish with useful dirty files while push/PR publication returns no URL. The Conductor adapter must route that outcome to salvage and preserve the worktree plus transcript. settled is disposable only when resultArtifact proves the work is durable.
  • pd nightshift must keep delegating. The alias rewrites legacy flags (--auto-queue--auto-claim, --status--state) before calling handleDispatch. If you add a dispatch flag, check the alias still maps it.
  • Coast Guard is opt-out and never advertised. It is the default for every subprocess backend in lib/spawner.ts; the agent-facing refusal must never name the opt-out (same rule as the guard bypass — guardrails do not advertise their bypass).
  • pd attest is a loud-fail gate. Adding an invariant means it can flip CI/boot gates red. New CRITICAL invariants go in lib/attest-invariants.ts with a test; mark non-blocking checks as such so a green exit keeps meaning "every CRITICAL invariant holds."
  • Manifest bijection. features.manifest.json is the parity source of truth (npm run parity). The dispatch/relay/attest/operator_coast_guard feature rows carry _note fields explaining intentionally-omitted routes (e.g. generic-typed Fastify handlers the route-parser cannot extract) — keep those notes accurate when you add or remove a route.
  • A coordination Durable Object is a peer, not the commit point for local work. Never put a network await on the local claim/note/session/lease write path. Persist a local outbox first, acknowledge an operation only after the DO alarm flush made it durable, require contiguous pull cursors, and keep the sender retrying anything merely buffered. The DO hot path must not call storage.put per operation; model it on HarborChannel/HarborQuota and prove zero request-path writes plus one alarm-batch write.
  • Remote-daemon selection forbids local substitution. An explicit URL or profile that refuses a connection must not enter direct-DB mode and must not auto-start a local daemon. Squid's generated hook gate uses bounded remote health for that explicit peer; only the implicit local daemon uses local ready/PID/heartbeat files. Preserve both sides in tests.

Rust surfaces — the kernel IS landed; ADR-0120 is the boundary rule

The kernel lives in-tree at core/kernel/ (pd-anchor / pd-mesh / pd-eventlog / pd-runtime / pd-core / pd-compat / pd-tui / pd-rs). ADR-0120 is the once-and-for-all answer to "what is Rust for" — read it before any console/Rust/crypto work. The three-plane rule, compressed:

  1. Security kernel (Rust, canonical, small): core/kernel/pd-anchor (Ed25519 cards, macaroon discharge gate, keystore), core/pd-broker (ADR-0087 separate-UID TCB), core/harbor-card-rs (FFI constant-time compare + caps-subset). Every security primitive is implemented ONCE, here. Native TS reaches it via FFI (lib/arbiter.ts, lib/macaroon-ffi.ts).
  2. Product planes (TypeScript, on purpose): daemon control plane, fleet, CLI, website, and BOTH Cloudflare Workers. Outside the TCB, so Rust buys no security there (ADR-0087) — and Workers physically cannot call native code. Where a Worker must duplicate kernel logic, it lands a shared test-vector fixture in tests/fixtures/*-parity-vectors.json generated from the canonical Rust impl, asserted by both suites, in the same PR. No fixture, no second implementation. Never a third.
  3. Console (Rust because GPU, not crypto): core/pd-console renders; it never signs/verifies. Not precedent for "write X in Rust."

Fixture regeneration is a security-relevant diff — review it like a change to the verifier itself. Do not scaffold new Rust crates for non-kernel, non-GPU work; keep prod/latest/dev pd-console lanes distinct when building or reviewing the console.

Building / installing / running pd-console (full detail in AGENTS.md § Building, installing & running pd-console)

Two binaries from one crate on crates.io gpui 0.2.2 (not the Zed git pin): pd-console (GPU window, --features gpui, macOS) and pd-console-repl (headless TUI, CI gate). Build: cargo build --release --bin pd-console --features gpui (from core/pd-console). Install BOTH launch surfaces or you demo a stale build: the PATH binary ~/.port-daddy/bin/pd-console and the double-clickable ~/Applications/pd-console.app (embeds its own binary — does NOT read PATH). After replacing the .app binary, codesign --force --deep --sign - ~/Applications/pd-console.app or macOS rejects it. Launch normally against the canonical published daemon port; use PORT_DADDY_URL only to target one explicit development berth. Startup must never read ~/.port-daddy/console-daemon.url: that stale selector previously pinned future launches to dead berths. PD_CONSOLE_THEME=light|dark / Ctrl-A g controls the theme. The Work screen submits one WorkIntent and stays attached to the daemon's exact launch/agent/transcript receipt; never jump to “newest agent” or spawn directly from the view. gpui 0.2.2 has no transform: glow/lift = shadow(BoxShadow) + hover color; timelines = with_animation; inside .hover(|s|…) pass bare rgb(x) (NOT .into() — ambiguous). Console branch: feat/console-tmux-multiplexer.

Release-Surface Drift (the contributor's prime directive)

When Port Daddy itself ships, the cost of inconsistency lands on every project on the user's machine. Every change to a public surface MUST update every mirror in the same coherent slice.

For the actual release ceremony (tagging, GitHub Release, release.yml, archive provenance, and the tap's credential-independent self-promotion), follow docs/RELEASING.md. For semver policy and the canonical list of version surfaces that must all bump in lockstep, see docs/VERSIONING.md.

The list below is the broader surface area a contributor touches before the release ceremony fires — the docs, examples, manifests, and CLI help that lie about behavior if not updated alongside the code.

Public surfaces, in approximate update order:

  1. Source code (lib/, routes/, mcp/, apps/FleetBar/).
  2. CLI help text (bin/port-daddy-cli.ts and any --help strings touched).
  3. The skill bundle (this repo's skills/port-daddy-agent-skill/SKILL.md, references, templates, examples).
  4. The website (apps/website-v2//docs/cli, /docs/api, /docs/mcp, command detail routes, screenshots).
  5. The OpenAPI spec, SDK reference, MCP tool catalog.
  6. README + the version surfaces in docs/VERSIONING.md. The changelog is NOT hand-edited: add changelog.d/<pr>-<slug>.md (see changelog.d/README.md) and let node scripts/assemble-changelog.mjs --release <version> stamp CHANGELOG.md — the release train runs it for you.
  7. Any plugin/extension manifests (Codex .codex/skills/, Gemini .gemini/extensions/port-daddy/, Claude .claude/skills/).
  8. Binary smoke-test (per docs/RELEASING.md §3, "local feature dev") for any change in lib/, routes/, server.ts, or mcp/. Source-mode tsx server.ts lies about what users actually run.

The Homebrew formula is no longer a per-PR concern. The curiositech/homebrew-tap workflow discovers stable latest.json on a serialized schedule, independently peels the release tag, verifies both Batten imprints and archive digests, and requires GitHub provenance for v3.30.3+. Source release.yml waits for the exact formula version but never writes across repositories. See docs/RELEASING.md §1 step J.

If you cannot land all of these in one commit, leave a pd actor lookout message naming the gaps and link the follow-up issue. Lookout is the role that watches for release-surface drift; making the drift visible is your job, fixing it is theirs (or future-yours).

PR Finish Line Discipline

For Port Daddy repo PRs, local validation is not the finish line. Before calling a branch ready, inspect and close the full PR surface:

  • Inline bot comments from Copilot, Claude review, Cloudflare Pages, CodeQL, package/release jobs, or deploy previews count as review findings. Reply to each actionable thread with fixed / deferred / contested-because.
  • A neutral adversarial reviewer runs in CI on every PR (the claude-adversarial-review workflow — assumes laziness/slop/lies/corner-cutting, ends with a SHIP / SHIP-AFTER-FIX / DO-NOT-SHIP verdict). Also run your own skeptical reviewer agent for non-trivial changes. Fix high-confidence findings as named fixup commits on the branch.
  • The PR description is gated. .github/PULL_REQUEST_TEMPLATE.md is the form, and scripts/check-pr-requirements.mjs (CI job pr-requirements-guard) fails the merge queue on an empty/boilerplate Summary or Test Plan, or a visual diff with no artifacts. Draft-check locally: npm run check:pr-requirements -- --body-file <draft.md>.
  • Treat GitHub CI, external deploy checks, release-package jobs, and Cloudflare Pages as one CI/CD surface. If one is red, inspect the linked logs. Only call it external after proving the branch is not the cause, and record that proof in both the PR and a pd note.
  • Do not leave a PR with "CI green except..." as an unresolved aside. Either make it green, file/assign the external blocker with evidence, or hand off the exact next action to an active Port Daddy session.
  • UI diffs ship visual artifacts — forever (now [M]). A PR touching a GPUI surface (core/pd-console window), the console (any pane/renderer), or the website/dashboard (website-v2/, fleet-config-ui/, public/fleet-ui/, public/, dashboard/, apps/FleetBar/) is incomplete without screenshots + a GIF + a short screen recording of the real change in its Test Plan, and pr-requirements-guard now fails the PR without at least a screenshot + a motion artifact. Green CI proves compilation, not rendering. TUI panes → vhs (tape under core/pd-console/docs/artifacts/); GPUI window → cargo build --release --features gpui then core/pd-console/scripts/capture-gpui.sh (needs macOS Screen Recording permission — a headless host is TCC-denied); website/dashboard → headless Playwright dark+light pairs. See AGENTS.md § "Visual artifacts for UI diffs". Operator rule, 2026-06-11.

PR Lifecycle (Create / Update / Land)

The Finish Line Discipline above is the review contract; this is the mechanical contract. AGENTS.md (## Pull Request Operating Procedure) carries the canonical copy — this is the contributor-repo mirror.

Create. Linked worktree off origin/main under ~/coding/tmp/wt-<slug> (never the main checkout — it carries the operator's WIP) → pd begin "<purpose>" --identity port-daddy:contrib:<slug> --lifecycle durable → full pd plan set → scope pd note → smallest claims before editing → edit and test → pd guard check --staged → frequent coherent checkpoints with verified agent author/committer attribution → ready, non-draft App/Fleetbot PR through the authorized publication path. A checkpoint is not delivery; do not run pd done at PR creation. Retain ownership through actual merge.

GitHub writes (push, PR, comment, review and queue mutations) use that scoped App path, never ambient personal gh/API credentials. Read-only inspection is distinct from publication and may use tools permitted by repository/operator policy; where all GitHub access is broker-routed, honor that policy for reads too. A planned ActionReceipt API or an ad-hoc helper is not a shipped surface. If the required publisher is missing, preserve the exact commits and body, record the missing capability and arrange an accepting handoff; do not invent a command, switch identities or replay an uncertain write.

Update (review + CI). Read live comments, replies and checks through the permitted inspection path. Respond graciously, incorporating actionable feedback unless clearly wrong or harmful; explain disagreements with evidence. Add regression tests and land high-confidence findings as named fixup commits. Get npx tsc --noEmit, jest, npm run parity, and the build green. Rebase onto latest origin/main, resolve conflicts with affected owners, validate and update the same App PR. Read-only reviewers must not push or merge; preserve role scope.

Land. Merge in dependency order: base before dependent, and rebase the dependent after each merge — mergeability can flip MERGEABLE → CONFLICTING the moment the base lands. Use the authorized App protected merge/queue path and let branch protection choose the merge strategy. Keep required checks and review gates intact; neutral/skipped Fleet is not a clean required verdict. Queue admission is not merge: verify the actual merged-head receipt, merge commit and timestamp, then update the full plan and typed roadmap PR receipt before ordinary pd done. Do not add --admin as routine agent flow. A human maintainer may make an explicit, documented emergency bypass; an agent does not admin-skip a real required gate. Cloudflare Pages may be external/advisory, but prove that from branch protection and record the evidence before treating it as non-blocking.

The ordinary completion Git gate verifies clean, origin-bound publication or advertised-default-branch ancestry, not the reviewed protected merge required above. lib/git-origin-check.ts returns the exact proof kind and commit/ref observation; missing local tracking metadata must not be labeled never-pushed. Keep tests for absent and deleted upstreams, dirty/untracked work, non-origin refs, missing objects and read-time movement. Reads have a ten-second total budget, bounded output and no interactive prompts; they do not fetch, rewrite refs/config, infer squash/rebase delivery, or promote the installed runtime. The separate ledger-only --no-pr verifier remains unchanged.

Cleanup. Delete a worktree only when its branch is merged AND git -C <wt> status --porcelain is clean. Never delete a worktree with uncommitted work; never reset or clobber the main checkout.

Shell gotchas (real and recurring)

  • git add -A is refused by the pd-shim. Stage explicit paths. If the refusal is wrong, repair the session/claim input and publish the inconsistency; do not disable the guard.
  • The ~/.port-daddy/bin/git shim sets core.pager=deltabat. If bat is absent, git log / git show / git commit emit command not found: bat and can swallow output. Use git -c core.pager=cat … or GIT_PAGER=cat.
  • Inline node -e and heredocs get mangled by zsh. Write a .cjs under the repo's .scratch/ (gitignored, resolves node_modules) and run it.
  • Secrets go through pd secret set (hidden stdin prompt) — never as an argv argument.

Test + session gotchas (dev-loop shibboleths)

The friction below costs every fresh session real time. Internalize it.

  • Tests are Jest, not vitest. tests/unit/*.test.js import from @jest/globals; run them with npm test (which is node --experimental-vm-modules node_modules/jest/bin/jest.js). Invoking vitest fails at import with "Do not import @jest/globals outside of the Jest test environment" — that's a wrong-runner error, not a broken test.
  • A fresh linked worktree has no node_modules. git worktree add copies tracked files only, so npm test / jest / tsc all fail with MODULE_NOT_FOUND until you install. Either npm ci in the worktree, or run the parent checkout's binary directly against the worktree: node --experimental-vm-modules /Users/erichowens/coding/port-daddy/node_modules/jest/bin/jest.js --rootDir . <path/to/test>. A bare node_modules symlink to the parent does not work — Node resolves the symlink target and looks for node_modules beside it, not inside it.
  • Headless pd begin needs an explicit lifecycle and closed stdin. With no TTY, pd begin blocks waiting for interactive input, and even with a purpose it errors without --lifecycle. Use pd begin "<purpose>" --lifecycle durable < /dev/null (or --lifecycle ephemeral for heartbeat-bound process sessions). Sessions launched via the Bash background-job wrapper never register — run pd begin in the foreground.
  • pd learn purity is a whole-command contract, not only a handler test. pd learn is canonical and pd tutorial is an exact alias. The orientation handler changes no work resources; headless mode makes no handler daemon request, while an actual controlling terminal may make one 750 ms, retry:false GET /health independent of color settings. Both aliases must skip daemon freshness and version-staleness probing, including update-cache reads and writes. The outer CLI envelope deliberately retains exactly one best-effort append-only POST /usage/trace attempt. A handler-only unit test cannot prove this boundary: keep a full-command subprocess test with a fake daemon that asserts the one telemetry event, no other request, and no update-check.json creation for both aliases. Run that ESM suite through npm test, not a bare Jest invocation.
  • Coordination-Guard claims are per-file, not per-directory. pd session files add skills/foo/ does not cover skills/foo/SKILL.md; the guard rejects the commit file-by-file. Claim exactly what you staged: pd session files add $(git diff --cached --name-only) right before pd guard check --staged.
  • A git add -A / reset --hard / rebase refused with "coordination guard … could not be verified" (not the routine advisory refusal) means the daemon-side guard could not confirm your session. Inspect the selected daemon, exact session, owner, physical worktree/root and retained claim history. Do not rerun pd begin to hide the disagreement. Use supported authorized recovery, read back its actual successor/claim disposition, or record the bounded defect and continue authorized disjoint work. Missing projections and released history are not permission to borrow claims or credentials.
  • Inherited selectors are not a recovery shortcut. Only at launch of a genuinely new child with its own context slot may the launcher remove inherited parent selectors before fresh admission. Never clear an existing CONTEXT_CONFLICT, broaden selectors, or copy a credential to bypass a proven contradiction. Retain the exact caller for notes, claims and completion; inspect runtime support before any recovery mutation and read back the result.
  • Binary drift in integration tests on dev machine: Ephemeral test daemons started by the integration test framework will verify binary hashes. If there's a global Homebrew or PATH-installed pd binary, it may cause false positive "binary drift" checks. Fix this by overriding the comparable on-disk path by setting PORT_DADDY_BIN_OVERRIDE: process.execPath inside the test environment for both the CLI runs and the ephemeral daemon spawns (now configured automatically in tests/helpers/integration-setup.js and tests/helpers/ephemeral-daemon.js).
  • Roadmap authority during Oracle cutover: Core coordination paths may still trigger the legacy Coordination Guard check for a local roadmap receipt. Do not satisfy that check by minting or touching a local roadmap row: local roadmap stores and files are transitional projections, not new authority. Use an attributable, fresh, signed remote Oracle work receipt once that writer is deployed and a remote read-back succeeds. Until then, fail closed and record the exact violation plus the operator-authorized, narrowly scoped commit exception or handoff for the slice; do not weaken Guard globally or claim a canonical remote receipt.
  • Guard receipt lookups must not infer absence from a capped list. Linked sessions read only their exact roadmapLink in the same intended harbor selected by pd roadmap writes; wrong-harbor and unrelated-item receipts cannot satisfy them. Keep freshness and agent attribution checks. Unlinked sessions use one scoped bounded page, reporting incomplete or unavailable evidence separately from missing receipts. These are local projection checks, not canonical remote authority.
  • Heartbeat liveness is not durable work authority. Automatic expiry preserves durable sessions and claims; only verified active durable bindings retain an inactive, not-ready directory row. Harvest and report only the ephemeral IDs actually abandoned. Existing replacement capsules stay held with holdReason: durable_session_active, never reopened by heartbeat or ordinary salvage callbacks. A previously admitted attempt is not canceled by a hold. Queue-hold clearance is not implemented; existing explicit session end, abandon, and takeover do not clear the saved hold. Source tests prove this preservation boundary, not an installed daemon upgrade or completed recovery UI.
  • Rich Docstring Mandate (TypeScript and Rust): Every library function and method in the codebase must carry rich, informative documentation. This is enforced by the npm run check:rich-docs (under scripts/check-rich-docs.mjs) validation loop. TypeScript functions/methods must use /** ... */ JSDoc blocks including @param and @returns tags (when parameters/return values are present) and discuss design, motivation, or philosophical rationale (e.g., matching keywords: motivation, purpose, philosophy, why, design, intent). Rust functions must use /// doc comments discussing the same motivation/philosophy keywords and parameter/return usage. You can run npm run check:rich-docs -- --staged to fast-audit only your changed/staged files.
  • Hook fan-out is host-visible work, not free middleware: Codex schedules a command hook once per matching nested tool call and renders concurrent batches as concurrent hook jobs. Never register an observational synchronous PostToolUse command, and never match an edit gate against broad Bash / exec_command / shell surfaces when the gate cannot derive a canonical target. The shipped topology is one turn briefing plus a synchronous gate only for direct edit tools; claims and notes are the cumulative outcome record. A six-tool read-only batch must schedule zero Port Daddy tool hooks. The raw debug/headless pd-hook-post-tool asset remains staged, but the stable interactive wrapper is an immediate zero-work tombstone so a running provider with cached config cannot resurrect it; never “repair” that wrapper by copying the raw tentacle over it. Its absence from provider config is intentional and must still diagnose as LIVE.
  • Hook config paths are a durable interface, not a package location: resolve versioned release assets only while staging; every Claude/Codex/Gemini/agy lifecycle config must call ~/.port-daddy/bin/pd-hook-*. Release smoke must reject /Cellar/ paths, and uninstall/repair must sweep legacy project-local Codex TOML without touching user hooks. The generated wrapper owns a CLOSED/OPEN/HALF_OPEN circuit breaker (3 consecutive failures or >250 ms, 5-minute cooldown, one probe, zero hook retries). Measure latency through external /usr/bin/time -p -o; shell-reserved time leaks outside redirections under dash. A missing timer must fail open, trip the same breaker, and request FleetBar Repair. Test unexpected exit, missing executable, missing timer, slow execution, exit-2 enforcement, concurrent accounting, one-shot FleetBar remediation, repair reset, minimal tooling, macOS/Linux shell behavior, and compiled artifact wiring as separate V&V seams.
  • Harness introspection is a bounded interface: pd squid status and pd squid debug status must read one sanitized timeline source and emit valid JSON regardless of retained history size. Cap recent steps and matrix values, expose total/returned/truncated metadata, and keep descriptions beside actual/expected timestamps. When capture is off, routine status must omit retained session identifiers and absolute workspace/event paths; only explicit debug status may reveal that diagnostic window. The portable shell compactor must strip BSD/macOS wc -c whitespace before its numeric guard and remove the first partial line after tail -c, or the nominal byte ceiling silently stops working and the retained TSV begins with a corrupt record. Test a multi-thousand-record fixture, macOS-padded byte counts, complete record boundaries, and a response-size ceiling; a JSON EOF is an interface failure even when the underlying daemon route returned 200.
  • Arrival and sitrep are on the critical path: optional pd begin peer guidance is semantic-only, capped to three, fail-open, and budgeted at 75 ms total — disable reconnect retries, abort the active request, and test a transport that never settles. Sitrep must project and cap every top-level collection, nested salvage notes, and text field; preserve exact note totals separately from the DB-bounded preview. --quiet must request a summary-only route rather than fetching a full payload and discarding it locally. A fast database query that serializes 200 KB of histories is still a failed launcher interface.
  • Durable history needs admission, not lifetime erasure: ordinary durable note appends have no lifetime count ceiling; SQLite atomically checks 60 writes/60s per session with the append, preserving originals and returning a precise retry time. Bound content to 10 KiB UTF-8 and type metadata to 128 bytes at the library boundary. Only an actual active-to-terminal transition gets one bounded handoff outside burst admission; repeated end calls are no-ops and a caller-selected handoff type is ordinary admission. Ephemeral 500 remains. Typed/since reads must apply the requested 1–1000 limit in SQL, and write authorization must not materialize notes/claims/counts; full-history detail remains explicit existing behavior. Test 601+ actual appends, normal plan/check/done, exact persisted totals, two-connection contention, Unicode, SQLITE_FULL/rollback, auth refusal and post-commit projection failure. Do not claim installed runtime proof, a hostwide quota, or cursor/UI pagination. Replicated history is not fresh authoring: use the internal project-bound synchronous page transaction, preserve original content/time and existing encryption, and commit notes/cursor/bindings atomically. Populate the key cache and emit projections only after commit; projection failures are separate from storage success. Never add a public rate-bypass flag; count only ordinary-origin rows for ordinary bursts. Incoming room pages allow 1000 operations and need their own finite byte/deadline bound, not the smaller outgoing envelope budget.
  • A preferred port is not endpoint evidence: startup may seed 9876, but SDK/CLI connection resolvers must use an explicit URL, a real socket, or a strictly parsed published port. Keep forgiving seed helpers separate from strict connection helpers, including public display fields and socket-to-TCP fallback. Reject a protocol the returned connection target cannot carry: the current Node target is HTTP-only, so accepting https: and then calling node:http is a plaintext-to-TLS-port defect, not compatibility. Fixture-test absent, malformed, unreadable, environment-published, file-published, unsupported-protocol, and constructor-URL-over-socket cases without consulting the developer's live daemon. The compiled smoke must use AF_UNIX-safe paths under ~/coding/tmp and prove Unix plus TCP health on both boots.
  • Provider CLI policy flags are versioned interfaces: dogfood the exact packaged spawn argv against the installed provider CLI, not only a mocked child process. Current Codex defines --approve-for-me as automatic review inside workspace-write; combining it with --sandbox workspace-write is a hard parse error before an agent starts. Direct spawn and Tube builders must share this compatibility invariant, and a reviewer that cannot launch is a product red, not a reason to waive review.
  • A Cloudflare Queue delivery is not a logical Fleet run: persist an ingress intent before queue.send(), idempotently key it by webhook delivery id, and assign a monotonic generation per repo + PR. Only supersede older active generations after the newer queue send succeeds; otherwise a transient admission failure can erase the last valid review. The executor must compare-and-swap that intent before spend so duplicate deliveries, retries, and stale heads acknowledge without re-running ships. Project activity from the intent ledger plus fleet_runs; label D1-known queue depth and expected timestamps as estimates, never Cloudflare-internal position. Keep active rows out of retention deletion, delete intent-only receipts through the same operator contract, and test the webhook, executor race, rollback-without-table path, signed-in receipt, and terminal retention seams independently.
  • Generated relay migration ledgers land through a PR, never a direct main push: deploy-relay.yml first proves the staging D1 apply and deploys relay-latest, then updates the deterministic automation/relay-staging-ledger branch and arms auto-merge on its generated PR. Use release-workflow-state.mjs select-live-token to live-probe the dedicated PAT fallbacks and expose only the source name. Do not use GITHUB_TOKEN for this mutation (GitHub leaves its generated PR runs human-approval-gated; use a dedicated App/PAT for automatic runs), do not add github-actions[bot] to the ruleset bypass, and do not make staging availability depend on whether the generated ledger PR has merged. The production gate stays closed until that PR lands.

Show-Me Runbook (operator demos)

When the operator asks to see a pd-console / FleetBar / daemon feature, the deliverable is a running, seeded, correctly-registered triple — not a build log. Every step below encodes an actual failure from a live demo (2026-07-12).

  1. Build the TRIPLE from the feature branch with scripts/dev-triple.sh <label>. The daemon must launch with the berth env vars from shared/daemon-berths.ts (BERTH_ENV): PD_DAEMON_TIER=dev PD_DAEMON_LABEL=<label> PD_DAEMON_COLOR=<hex> PD_DAEMON_SOURCE_DIR=<worktree> so it self-registers into ~/.port-daddy/dev-daemons.json. dev-triple.sh exports these itself; any other launch path must export them by hand. Unregistered berth = daemon invisible in FleetBar's Daemons list = furious operator.
  2. Seed live state before the operator looks. An empty daemon renders empty panes — it can't render what it has no backend for. For claim/conflict surfaces: two sessions with overlapping POST /sessions/:id/files claims (agentId is required in the body).
  3. Multi-PR feature → combined local preview branch. Merge the PR branches locally (never push the merge branch) so the operator reviews the sum. Demoing one slice invites rage-bugs about everything the other slice already fixed.
  4. pd-console-repl / terminal-face artifacts are machine-gate evidence only — never operator review material. Operator review = the GPUI app, running, seeded.
  5. Emoji sweeps grep BOTH literal emoji AND unicode escapes (\u{2693}, \u{1F...}). Escaped emoji still render as emoji; the no-emoji-as-icons rule judges pixels, not grep hits.
  6. Never create virtual displays or modify display settings. On-primary-screen window openings only with explicit operator consent, per action.

Distribution Mirror Sync

The skill bundle is mirrored to several locations. Inside this repo the canonical copy is skills/port-daddy-agent-skill/. The metadata.mirrors block in its frontmatter declares targets:

Target Purpose Sync trigger
.codex/skills/ Codex CLI agents on this repo install.sh + brew post_install
.claude/skills/ Claude Code agents on this repo install.sh + brew post_install
.agents/skills/ Generic AGENTS.md-aware tools install.sh
.gemini/extensions/port-daddy/skills/ Gemini CLI extension surface install.sh
external-skill-catalog (out of repo) Public catalog distribution manual cp -r from this repo to ~/coding/external-skill-catalog/skills/

The standalone scripts/install-pilot-agents.ts accepts --source-dir before Homebrew discovery; an invalid explicit source never falls back. Preview with --dry-run, then bind an apply using both --expect-agent-sha256 and --expect-config-sha256 from the captured source receipt. Those digests describe the exact prompt/config bytes rendered into all five formats, not trusted-source attestation, atomic target replacement or proof of an installed runtime. Without a source override, package-first defaults remain and no setup/MCP flags are added; the shared target executor now governs replacement, cleanup and uninstall.

Target ownership requires a verified prior output record, never an ID substring or equality with newly rendered bytes. Preserve historical unmanaged targets. --expect-target-sha256 binds an explicitly reviewed target preview; without that pin, apply validates an immediate snapshot, not a separately reviewed or signed plan. Source validation precedes target, backup and receipt writes; preview writes nothing. --uninstall and explicit --recover <run-id> require both source and base directories. Partial recovery must preserve later edits and report unresolved evidence. There is no force/adopt option, automatic recovery, actor grant, same-UID sandbox or all-five-file transaction. Source tests do not authorize a real-home installation; machine actuation needs its own exact preview and execution evidence.

port-daddy-internal-dev (this skill) is intentionally absent from the mirrors-list above. Do not propose distributing it. Its presence on a non-port-daddy machine would be confusing noise.

Recovery Ledger Discipline

docs/recovery/CURRENT-WORK.md is owned by Navigator + Cartographer. Do not edit it directly. Send messages to those actors:

pd actor navigator --message "ROADMAP: <slice> completed at <commit>. Reconcile live work events and projections; suggest promoting next: <item>."
pd actor cartographer --message "DOGFOOD: <synthesis>. Publish attributable evidence; suggest roadmap entry: <name>."

Mailbox delivery is durable but not synchronous. After messaging an actor, work from live daemon events, notes, sessions, and checked-in release evidence. docs/recovery/CURRENT-WORK.md, Cartographer files, plans, binders, DAGs, hypertrees, and snapshots are evidence or projections; none is a database or a rival authority. The target authority is the configured remote append-only work-event Oracle after a write has a remote read-back receipt. Until the cutover is proven live, preserve unique local source material, label projections honestly, and never create another "authoritative" file.

If docs/recovery/CURRENT-WORK.md contradicts the live fleet, that is a Navigator projection-drift issue. File it; do not silently overwrite it or let it outrank live evidence.

Git Discipline (inherited; see ADR 0001)

The five rules from port-daddy-agent-skill apply here too — and harder, because this repo has the highest agent density on the user's machine.

  1. Worktree mandatory for any background contributor work — even small ones. The repo has 70+ existing worktrees and dozens of WIP branches; sweeping up someone's WIP is a near-certainty without isolation.
  2. No git add -A ever. No exceptions. The repo has too many drafts in flight.
  3. Pre-commit git status --porcelain check. Abort on foreign files. The pre-commit hook from pd guard install --mode enforce should be on at all times in this repo.
  4. Lock the staging area if you must work in the main checkout: pd lock port-daddy:git:write (or pd with-lock port-daddy:git:write -- <command>). MCP-aware clients can call acquire_lock with the same name.
  5. Push only what you tagged. Never git push --follow-tags from a contributor agent.

See references/git-discipline-internal.md for port-daddy-specific extensions (release-tag immutability, the v-prefix convention, the brew formula update protocol).

Fleet Model Tiers (never choose from memory)

Every Workers AI model decision — a ship's tier, a purser step model, a new admission — is made against references/cloudflare-model-roster.md (the verified catalog + pricing snapshot, the admission contract, and the standing decision record) and the live scoreboard (node scripts/fleet-ship-stats.mjs --days 14, which reads the relay D1's per-ship × per-model spend and broken/repair health). Two standing rules: an id is honored only after existence + rate + context are verified (phantom ids return silent blanks — #654), and a model-change PR carries its before-window stats and gets judged on its after-window. The gpt-oss-20b author tier (#8870: 75% repair failure, half the fleet's verdicts washed out) is the tombstone for choosing a tier off a price note without a scoreboard.

Catalog-First Reflex (Jury-rig, internal edition)

Port Daddy contributors are not exempt from the local catalog. Project, user, and explicitly configured skill roots cover most patterns you'll hit while editing this codebase: rate limiting, caching, websocket protocols, distributed transactions, pre-mortems, evaluation harnesses, design systems for the website, and more.

pd jury-rig query "<the thing you're about to do>"
pd jury-rig reference <skill-id> <path-within-skill>

Before every contributor slice, one search. Examples that have paid off:

  • Editing the daemon's lock-acquire path? pd jury-rig query "distributed lock semantics" surfaces the closest local guidance.
  • Adding a new MCP tool description? pd jury-rig query "MCP tool description writing" surfaces mcp-creator when installed.
  • Touching the website? pd jury-rig query "responsive layout master" finds the available design-system skills.
  • Writing pre-release tests? pd jury-rig query "adversarial QA" finds installed QA and web-app testing guidance.

If the catalog is wrong or stale for our domain, that's a Cartographer issue: pd actor cartographer --message "Catalog gap: <what skill should exist>. Use case: <internal slice>."

Maintain These Skills (port-daddy-internal-dev edition)

This skill is alive. It improves when contributors update it. When you finish a slice — any slice on this repo — ask: did I just learn something that this skill or port-daddy-agent-skill should have warned me about?

Contributors are the only agents who write to both surfaces. As an internal agent you own a continuous maintenance duty for both:

  • Public (skills/port-daddy-agent-skill/SKILL.md) — anything that helps an agent on any project using Port Daddy. New verb, deprecated flag, decision row, anti-pattern, clarification, brevity win.
  • Internal (this skill) — anything specific to editing this repo: release ceremony, internal actor embodiments, drift protocol, worked contributor examples.

Drive-by edits are explicitly welcome on both. No issue required, no permission required. Same-slice fixes — landing the skill update alongside the code change that revealed the problem — are the default; that is what keeps the documentation from going stale between releases. Retrospective edits (the lesson surfaced days later) are still owed; open a tiny PR.

Concrete triggers:

  • You hit a release-surface gap the protocol didn't cover. Update references/release-surface-drift-protocol.md.
  • An internal actor's body moved (new route, lib reshuffle). Update the Internal Actor Embodiments table.
  • A worked example would have saved an hour for a recurring slice. Add it to examples/.
  • A new useful internal-only tool (audit script, fleet persona, debugger) was written. Cross-link from this skill.

Update mechanics:

git worktree add ../port-daddy-internal-skill-$(date +%s) origin/main
cd ../port-daddy-internal-skill-*
pd begin "Update port-daddy-internal-dev: <what>" --identity port-daddy:contrib:internal-skill-update
$EDITOR skills/port-daddy-internal-dev/SKILL.md   # or references/<file>.md
git add skills/port-daddy-internal-dev/<paths>
git status --porcelain                             # must be clean of foreign files
git commit -m "skill: port-daddy-internal-dev — <change>"

If the wisdom is public (any agent on any project would benefit), put it in port-daddy-agent-skill instead. The split-decision rule: would this help an agent on a non-port-daddy repo? Yes → public. No → internal. Both? → public, with a port-daddy-specific extension page in this skill.

After landing, send Cartographer: pd actor cartographer --message "port-daddy-internal-dev updated: <section>. Reason: <session/incident>."

Advance (the invocable "move it along" call)

When the operator invokes this skill with advance (or any phrasing like "move things along", "go on", "keep going", "you know what to do"), run the standing autonomous sweep. Do not ask permission at any step — review is the gate, not the operator. These are the operator's recorded expectations; re-asking them is the failure mode this section exists to kill.

  1. Recon. pd status / pd briefing / pd sessions --all-worktrees, then env -u GITHUB_HOST gh pr list --author @me --state open (plus any PRs this fleet opened under other identities). Snapshot main's CI: gh run list --branch main --limit 5.
  2. Classify each open PR: green-and-mergeable → land it now; stale base → rebase; red required check → root-cause it; superseded by a landed PR → close it with a comment naming the superseding PR (never merge a semantically obsolete diff — see the #353 incident); draft → leave unless its gate condition is met. Compare the head's actual invariant and tree to current origin/main; an old green check and a non-empty commit list do not prove work is still missing. Carry forward the smallest valid invariant, and leave broad adjacent programs open instead of relabeling them as part of a cleanup sweep.
  3. Red required check = STOP and fix the root cause, even when the debt is inherited from main. Never --admin over a real red. Cloudflare Pages may be external/advisory, but prove that from branch protection before treating it as non-blocking. A Fleet receipt that says concluded while GitHub's required check remains in_progress is the same class of stop: inspect both sides of the delivery interface. The executor must propagate an exhausted completeCheckRun result into queue retry/DLQ before acknowledging the message. Keep ship checkpoints durable and post non-idempotent aggregate reviews only after the required check PATCH succeeds, so retries neither re-spend nor duplicate. The logical-run deadline must also fit the configured roster: budget at least one default AI-call window per ship plus explicit queue/checkpoint overhead. A ceiling equal to ship count x call deadline has zero room for continuations and will deterministically terminate healthy checkpointed reviews before their final blocking ship. Prove the slow-success boundary with a focused test whenever either deadline or roster size changes.
  4. Answer every review thread. Copilot and claude-review inline comments are first-class reviews: fix-and-reply, or dismiss-with-reason against origin/main. A PR with unanswered threads is not "ready".
  5. Land in dependency order, base before dependent, rebasing the dependent after each merge. Use the authorized App protected merge/queue path; required checks and review gates stay binding. Queue admission is not merge. Verify the actual merged-head receipt before advancing dependents.
  6. Clean up: delete only worktrees whose branch is merged AND whose git status --porcelain is clean. Never touch the main checkout.
  7. Close the ledger: pd note "Result: ... Validation: ... Remaining: ...", the complete plan and typed roadmap PR receipt, then pd done and pd feedback only after actual merge or an accepting, attributable handoff. Preserve unfinished work in the plan; PR creation is not completion. If the sweep taught this skill something, land the skill edit in the same sweep.

Built b

Truncated - read the full file at https://github.com/curiositech/port-daddy/blob/439c8886bc157a0ae315c1b8c316b9363669deac/skills/port-daddy-internal-dev/SKILL.md.

Use it

Copy one of these into your project. Installing also returns the manifest and these snippets.

yaml
targets:
  - https://api.opensmartroute.ai/api/v1/registry/curiositech-port-daddy-port-daddy-internal-dev/manifest   # or paste the manifest below

Manifest

An Open Capability Manifest: the router reads it to know what this does, what it costs and when to pick it.

curiositech-port-daddy-port-daddy-internal-dev.ocm.jsonjson
{
  "ocm": "1",
  "id": "curiositech-port-daddy-port-daddy-internal-dev",
  "kind": "skill",
  "name": "port-daddy-internal-dev",
  "description": "Contributor manual for agents working ON the Port Daddy codebase itself — the daemon, MCP server, FleetBar / Fleet Control Center, website, CLI surface, distribution mirrors, internal recovery ledger, and the named internal actors (Coxswain / Navigator / Cartographer / Lookout / Quartermaster + Shipwright). Use when editing the port-daddy repo. NOT for agents using Port Daddy on other projects (use port-daddy-agent-skill for that), and NOT distributed to public skill catalogs — this skill is private to the port-daddy repo.",
  "publisher": "curiositech",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "general"
    ],
    "tags": [
      "skill-md",
      "port-daddy",
      "internal",
      "contributor",
      "daemon",
      "fleetbar",
      "mcp",
      "distribution",
      "release-surface",
      "shipwright"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "Contributor manual for agents working ON the Port Daddy codebase itself — the daemon, MCP server, FleetBar / Fleet Control Center, website, CLI surface, distribution mirrors, internal recovery ledger, and the named internal actors (Coxswain / Navigator / Cartographer / Lookout / Quartermaster + Shipwright). Use when editing the port-daddy repo. NOT for agents using Port Daddy on other projects (use port-daddy-agent-skill for that), and NOT distributed to public skill catalogs — this skill is private to the port-daddy repo."
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "github",
      "repository": "https://github.com/curiositech/port-daddy",
      "path": "skills/port-daddy-internal-dev/SKILL.md",
      "ref": "439c8886bc157a0ae315c1b8c316b9363669deac",
      "url": "https://github.com/curiositech/port-daddy/blob/439c8886bc157a0ae315c1b8c316b9363669deac/skills/port-daddy-internal-dev/SKILL.md",
      "key": "curiositech/port-daddy/skills/port-daddy-internal-dev/SKILL.md"
    },
    "allowed_tools": [
      "Read,Bash,Grep,Glob,Edit,Write"
    ],
    "license": "FSL-1.1-MIT"
  },
  "instructions": "# Port Daddy — Internal Contributor Manual\n\nYou are editing the Port Daddy codebase itself: the daemon, MCP server,\nFleetBar, Fleet Control Center, website, CLI, SDKs, distribution surfaces,\nthe recovery ledger, and the internal actor inboxes. This skill is private\nto the port-daddy repo because most of what's here would be noise on a\nproject that just *uses* Port Daddy.\n\nFor the public skill — how any agent on any project should drive Port\nDaddy — see the sibling `port-daddy-agent-skill`.\n\n## NOT For\n\n- Agents on other projects driving Port Daddy as a coordination tool — that's `port-daddy-ag",
  "cost": {
    "context_tokens": 19924
  }
}

Fetch it by URL: GET /api/v1/registry/curiositech-port-daddy-port-daddy-internal-dev/manifest?version=1.0.0

Reviews

Star ratings from people who tried it. One review per account; edit yours any time.

No reviews yet. Install it, try it, and be the first to rate it.