diff --git a/skills/poteto-mode/playbooks/opening-a-pr.md b/skills/poteto-mode/playbooks/opening-a-pr.md index e96e15c..ebfd4b5 100644 --- a/skills/poteto-mode/playbooks/opening-a-pr.md +++ b/skills/poteto-mode/playbooks/opening-a-pr.md @@ -16,13 +16,13 @@ Invoked at the end of every other playbook. - `## Scope`. State facts from the diff. Name real symbols and paths. Name both sides of a rename or retarget. State what is in and out when the boundary matters. - `## Tradeoffs`. State real choices only. Skip this section when there are none. - `## Blast Radius`. State who and what the change touches. Explain why the change is safe or risky. If main is red without the fix, name the continuing cost. -- `## Verification`. State how you ran each check and its rigor. Name the real path, such as `control-cli`, `control-ui`, or the targeted tests. State the outcome of each check, not only the command name. +- `## Verification`. State how you ran each check and its rigor. Name the real path, such as `npm run verify:deterministic`, `npm run verify:browser`, Playwright, or the targeted tests. State the outcome of each check, not only the command name. After these sections, attach videos or screenshots when they prove a claim. Do not use `## Summary` or `## Test plan` boilerplate. A commit body does not restate its subject. **Size and stacks.** Prefer narrow PRs to one large PR. Use the configured delivery adapter, with `gh stack` as the default and Graphite as an explicit option. Keep the ordered stack visible to reviewers. Branch from main only for independent work. Rebase on `main` before substantial stack work. -**Readiness.** Open every PR ready, never as a draft. Cloud-agent PR tools default to draft, so set `draft: false` on every PR creation call. If a PR still opens as a draft, run the host's ready command, such as `gh pr ready `. Run `gh pr view ` before you refer to PR status. +**Readiness.** Open every PR ready, never as a draft. Set `draft: false` on every PR creation call. If a PR still opens as a draft, run the host's ready command, such as `gh pr ready `. Run `gh pr view ` before you refer to PR status. **Babysit.** Opening a PR does not start a babysit. Post the URL and keep building. Finish the phase or stack first. Run a separate babysit pass only when the user asks for one after the whole stack exists. A babysit for each new PR stalls the build and spends checks on commits that later waves restart. Push back when feedback drifts from intent. diff --git a/skills/poteto-mode/playbooks/orchestrate.md b/skills/poteto-mode/playbooks/orchestrate.md index cfaba02..e98ba1b 100644 --- a/skills/poteto-mode/playbooks/orchestrate.md +++ b/skills/poteto-mode/playbooks/orchestrate.md @@ -15,7 +15,7 @@ Open a todolist with the steps below copied in verbatim. A step you skip stays l #### Roles and placement - **Coordinator (this chat).** Local. Frames, authors briefs, drains the inbox, owns the human report, makes judgment calls. It never authors or edits code: conflicted merges, restacks, and code changes are always tasks. Mechanically landing a verified unit (fast-forward or clean cherry-pick of a worker's commit, then push) is bookkeeping the coordinator may do itself on repos where local git is cheap; queueing finished work behind an idle stacker is how a deadline harvests nothing. The loop is agentic end to end. Agents are spawned, resumed, and drained only through the subagent tool. State reads and writes go through `scripts/orch/orch.ts` at drain points, one command in and one line out, to conserve context. The CLI never spawns, waits, or wakes anything. -- **Sub-coordinator.** Always local, durable, one per track, and only when the program exceeds what one coordinator's drains can manage. A track the coordinator can drain itself needs no middle layer: each nested layer re-pays a full orientation preamble, and a blocking sub-coordinator hides its children while the parent idles. Owns its track's units and boards, authors its workers' briefs, spawns its own workers and verifiers (nesting works to depth 3, and a nested spawn has the full subagent schema including `environment`). Rolls up aggregates at wave boundaries; never forwards raw child reports. Cap in-flight children at what one drain can process, roughly ten, as a rolling window; never as blocking batches, which cost the slowest child of every batch. +- **Sub-coordinator.** Always local, durable, one per track, and only when the program exceeds what one coordinator's drains can manage. A track the coordinator can drain itself needs no middle layer. Each nested layer re-pays a full orientation preamble, and a blocking sub-coordinator hides its children while the parent idles. Owns its track's units and boards, authors its workers' briefs, spawns its own workers and verifiers (nesting works to depth 3, and a nested spawn uses `agent`, `task`, and `worktree`, plus optional `model`, `role`, and `readOnly`). Rolls up aggregates at wave boundaries; never forwards raw child reports. Cap in-flight children at what one drain can process, roughly ten, as a rolling window; never as blocking batches, which cost the slowest child of every batch. - **Worker / verifier.** Use `worktree: true` unless the task needs this machine for the project verification skill, the active session transcript named by `$PI_SESSION_FILE`, simulators, local IDE state, or local-only authentication. Briefs inline what an isolated child cannot read. Prefer fewer, broader workers; one writer per worktree or branch. Run a unit's verifier on a different model family when an available model profile makes that possible. Depth stays at coordinator, track, worker. Author the track decomposition per project (build, landing, and verification are common cuts, not a required shape); hard-coded swarm trees were tried and parked as too rigid. @@ -43,7 +43,7 @@ SCOPE paths this unit may write; paths it may not; its exclusive worktree CONTEXT pointers to files and PRs; upstream reports pasted in full when this unit depends on them, because workers cannot see siblings ACCEPTANCE checkable criteria, one per line -VERIFY exact commands or the control-skill path, plus known gotchas +VERIFY exact commands such as `npm run verify:deterministic` or the project verify scripts, plus known gotchas TIMEBOX rough cap on runtime; on expiry, return partial findings and stop rather than run on FORBIDDEN no gt, no rebase, no force-push, no fixes outside scope, plus unit-specific bans REPORT status, branch, head SHA, PRs, verdict, what you actually ran, deviations, @@ -51,9 +51,9 @@ REPORT status, branch, head SHA, PRs, verdict, what you actually ran, devi STANDING ``` -Size the brief to the unit. A one-command unit gets the template collapsed to a paragraph that still names goal, scope, the verify command, and the report shape; a 4KB scaffold around a two-line edit costs more to write and obey than the edit. Local spawns may reference the standing-orders file by store path; verbatim paste is for cloud spawns and every resume. +Size the brief to the unit. A one-command unit gets the template collapsed to a paragraph that still names goal, scope, the verify command, and the report shape; a 4KB scaffold around a two-line edit costs more to write and obey than the edit. Local spawns may reference the standing-orders file by store path. Verbatim paste is for isolated `worktree` children and every resume. -A sub-coordinator brief adds its track boundary and unit list, its spawn budget with the cloud default and the local exception list, the drain protocol, and the rollup format (per child: name, status, PR, head SHA, verdict, one line; plus track status and frontier delta). +A sub-coordinator brief adds its track boundary and unit list, its spawn budget with the `worktree: true` default and the local exception list, the drain protocol, and the rollup format (per child: name, status, PR, head SHA, verdict, one line; plus track status and frontier delta). A dependency is a context relay, not just ordering: undeclared upstream context makes the worker guess. Missing fields are a refuse-to-spawn condition. Audit one sampled worker brief per sub-coordinator per wave, concurrently with the wave it samples, never as a gate in front of it; a failing brief stops that track and fixes the sub-coordinator's instructions, not just the worker, because brief quality decays late in a run. Never resume-chain a brief; respawn fresh with consolidated scope. @@ -70,7 +70,7 @@ A dependency is a context relay, not just ordering: undeclared upstream context #### Queue and drain - On a completion notification, run `orch inbox push [--report PATH]` and return to what you were doing. Never deep-review inline; a completion that needs review becomes a verifier unit. Never review a diff inside a drain. -- Drain in batches at four points: the end of a critical section, a track rollup, a frontier watcher wake (arm it via the loop skill, with a long heartbeat fallback), and before a human report. Begin each batch with `orch inbox drain`. Arrivals during a drain wait for the next one. +- Drain in batches at four points: the end of a critical section, a track rollup, a frontier watcher wake (arm it with `subagent_wait` or a Pi schedule, with a long heartbeat fallback), and before a human report. Begin each batch with `orch inbox drain`. Arrivals during a drain wait for the next one. - Critical sections you finish first: authoring a brief, a stack operation, a conflict decision, writing a gate, updating ledger or frontier. - Each drain classifies every pointer (landed, needs-verify, failed, zombie, noise), writes the resulting rows through `orch unit add`, `orch unit set`, and `orch ledger record`, runs `orch status`, then spawns the next wave in one message. - Account for every spawned child at its track's rollup: arrived, respawned, or its scope explicitly absorbed. Silently redoing a missing child's work hides both the wasted spend and the coverage gap its result existed to close. @@ -109,7 +109,7 @@ A unit is not done until its output is externalized the moment it lands, never b - A zombie that returns hours late reconciles against the current frontier and ledger before anything is accepted; the world moved while it slept. Salvage unique findings through a fresh unit, never a blind merge. - When continued spawning would produce garbage tree-wide (bad upstream output, broken acceptance, dead infra), write a stop line at the top of the standing orders, let in-flight work finish, fix the cause, clear it. - Bound your own infra retries the same way you bound a child's. After a few consecutive tool aborts, stop retrying: write a terminal handoff to durable state (what is done, where it lives, the exact command to resume) and end the run. Hours of retry loops against a dead executor produce nothing a handoff would not. -- After a Pi restart: local agents are dead, cloud work is not. Re-read the standing orders and `units.tsv`, recompute the frontier, reattach cloud work by PR and branch rather than agent id, respawn one sub-coordinator per track from its stored brief plus current state, drain, resume. The dead session's store lock clears itself on the next write; `orch` replaces a lock whose holder pid is gone. +- After a Pi restart, local agents are dead. Re-read the standing orders and `units.tsv`, recompute the frontier, reattach by PR and branch rather than agent id, respawn one sub-coordinator per track from its stored brief plus current state, drain, resume. The dead session's store lock clears itself on the next write; `orch` replaces a lock whose holder pid is gone. #### Escalation diff --git a/test/resources/resources.test.mjs b/test/resources/resources.test.mjs index 64277ea..ff8640f 100644 --- a/test/resources/resources.test.mjs +++ b/test/resources/resources.test.mjs @@ -124,6 +124,11 @@ test("active resources use Pi runtime contracts", async () => { ["doubled subagent", /subagent subagent/], ["create-skill", /create-skill/], ["workspace-boundary leftover", /crosses workspace boundaries/], + ["control-ui", /control-ui/], + ["control-cli", /control-cli/], + ["cloud spawns", /cloud spawns/], + ["cloud work leftover", /cloud work is not/], + ["loop skill leftover", /the loop skill/], ]) { assert.doesNotMatch(corpus, pattern, `${token} remains in active resources`); }