diff --git a/README.md b/README.md index 966accd..8644c24 100644 --- a/README.md +++ b/README.md @@ -250,12 +250,8 @@ twenty-four short skills, one principle each. `poteto-mode` indexes them inline a few things `poteto-mode` references but doesn't bundle: -- `/deslop` and the `deslop` skill ship in the `cursor-team-kit` plugin. -- `control-cli` (for CLIs and TUIs) and `control-ui` (for browser, Electron, web) ship in `cursor-team-kit` too. - `/create-skill` is a cursor built-in. cursor also ships a built-in `/autopilot` that watches a pr. inside `poteto-mode`, pr-status requests go to the [babysit playbook](./skills/poteto-mode/playbooks/babysit.md) instead. -install `cursor-team-kit` alongside pstack if you want the full set. - ## why are there no planning skills? devin already has a great plan mode which works great with pstack. but personally, i don't believe in planning. the best spec is code. if you do want to make a plan, [`/pstack:poteto-mode`](./skills/poteto-mode/SKILL.md) covers it, but it's not a default. diff --git a/docs/guide/05-build-and-clean.md b/docs/guide/05-build-and-clean.md index 5ef1dda..b720d96 100644 --- a/docs/guide/05-build-and-clean.md +++ b/docs/guide/05-build-and-clean.md @@ -56,7 +56,7 @@ In context, that's enough. [`/pstack:tdd`](../../skills/tdd/SKILL.md) writes the ## Clean before you commit -The [Opening a PR playbook](../../skills/poteto-mode/playbooks/opening-a-pr.md) runs a slop-strip pass on the diff before each commit and applies [`/pstack:unslop`](../../skills/unslop/SKILL.md) to the PR description and commit bodies. `/deslop` ships in the `cursor-team-kit` plugin, not in pstack. If you don't have it, ask for the same outcome in plain words: remove narrating comments, unsupported guards, dead compatibility paths, and unrelated edits. +The [Opening a PR playbook](../../skills/poteto-mode/playbooks/opening-a-pr.md) runs a slop-strip pass on the diff before each commit and applies [`/pstack:unslop`](../../skills/unslop/SKILL.md) to the PR description and commit bodies. For prose, `/pstack:unslop` takes a target and any extra rules you have: diff --git a/skills/control-cli/SKILL.md b/skills/control-cli/SKILL.md new file mode 100644 index 0000000..69289ac --- /dev/null +++ b/skills/control-cli/SKILL.md @@ -0,0 +1,109 @@ +--- +name: control-cli +description: Build or adapt a local harness to drive, inspect, and profile an interactive CLI or TUI without external services. Use for CLI UX checks, startup regressions, memory leaks, hangs, prompt flows, or terminal demos. +--- + +# Control CLI + +Use a repeatable local harness to exercise an interactive CLI instead of poking at it manually. First reuse the repo's own test/demo harness if it exists; otherwise assemble a temporary harness from standard local tools. + +## What It Is Used For + +- Reproducing CLI/TUI bugs with deterministic input. +- Verifying keyboard flows, prompts, interrupts, resize behavior, and terminal layout. +- Capturing before/after transcripts for bug fixes. +- Profiling startup time, slow operations, hangs, or memory growth. +- Recording a short terminal demo when output is easier to show than explain. + +## Harness Loop + +1. Identify the command under test and the smallest reproducible workspace. +2. Discover existing local harnesses: package scripts, e2e tests, demo recorders, expect scripts, or PTY helpers. +3. If no harness exists, launch the CLI in an isolated terminal session with deterministic env vars. +4. Capture the current screen before interacting. +5. Send one action at a time: text, Enter, arrows, Escape, Ctrl-C, resize. +6. Wait for a concrete screen pattern or prompt before the next action. +7. Save the transcript and any profile artifacts. +8. Kill the session cleanly. + +## Harness Options + +- Repo-native harness: prefer checked-in scripts because they know the app's startup, env, and prompts. +- `tmux`: managed sessions, `capture-pane`, `send-keys`, attach/detach. +- PTY probe: use a short Python, Node, or Expect script when tmux is unavailable. +- Runtime inspector: use Node or Bun inspector for CPU profiles, heap snapshots, and live evaluation. +- Terminal recorder: use repo-local demo tools or asciinema-compatible tools when the user asks for a demo. + +## Minimal tmux Harness + +```bash +SESSION="cli-harness-$(date +%s)" +tmux new-session -d -s "$SESSION" -- +tmux capture-pane -pt "$SESSION" +tmux send-keys -t "$SESSION" "help" Enter +tmux capture-pane -pt "$SESSION" +tmux kill-session -t "$SESSION" +``` + +For Node CLIs: + +```bash +NODE_OPTIONS="--inspect=127.0.0.1:0" tmux new-session -d -s "$SESSION" -- +``` + +Read the terminal output to find the inspector URL, then use Chrome DevTools-compatible tooling if profiling is needed. + +## Minimal PTY Harness + +Use a PTY script when you need deterministic waits in a repo that does not have tmux or a demo harness. Keep it temporary unless the user asks to add a reusable test. + +```python +import os +import pty +import select +import subprocess +import time + +master_fd, slave_fd = pty.openpty() +proc = subprocess.Popen( + ["", ""], + stdin=slave_fd, + stdout=slave_fd, + stderr=slave_fd, + close_fds=True, +) +os.close(slave_fd) + +deadline = time.time() + 30 +buffer = b"" +while time.time() < deadline: + ready, _, _ = select.select([master_fd], [], [], 0.25) + if not ready: + continue + chunk = os.read(master_fd, 4096) + buffer += chunk + if b"" in buffer: + os.write(master_fd, b"help\n") + break + +print(buffer.decode(errors="replace")) +proc.terminate() +os.close(master_fd) +``` + +If the CLI needs richer terminal control, use `pty.fork()` or an existing PTY library. + +## Profiling Recipes + +- Startup regression: capture baseline and treatment startup timings under the same machine, env, and command. +- Slow operation: start a CPU profile, perform the operation, stop the profile, and compare top self-time functions. +- Memory leak: force GC if available, take a heap snapshot, perform the operation repeatedly, force GC again, and take another snapshot. +- Hang: capture the screen, active handles/resources, and a stack/CPU sample before interrupting. + +## Guardrails + +- Prefer deterministic waits over sleeps. If you must sleep, explain why. +- Do not send credentials or destructive commands into a controlled session. +- Keep the harness in `/tmp` unless the repo already has a testing/demo harness. +- Do not hard-code paths from another repository. Adapt commands to the current repo's scripts and runtime. +- Clean up tmux sessions, temp dirs, inspector processes, and demo artifacts unless the user asks to keep them. diff --git a/skills/control-ui/SKILL.md b/skills/control-ui/SKILL.md new file mode 100644 index 0000000..68484fd --- /dev/null +++ b/skills/control-ui/SKILL.md @@ -0,0 +1,109 @@ +--- +name: control-ui +description: Build or adapt a local browser/CDP harness to drive and inspect a web, IDE, or Electron UI. Use for local UI verification, screenshots, accessibility snapshots, perf profiles, visual diffs, or reproducing UI bugs. +--- + +# Control UI + +Use local browser automation to verify UI behavior with evidence. First reuse the repo's own Playwright, browser, or Electron harness if it exists; otherwise assemble a temporary local harness around the app's dev server or Chromium debug port. + +## What It Is Used For + +- Reproducing UI bugs that depend on real browser focus, keyboard input, scrolling, resizing, or rendering. +- Verifying visual or accessibility changes with screenshots and snapshots. +- Checking local web, IDE, or Electron behavior before shipping. +- Capturing console logs, network logs, CPU profiles, traces, or heap snapshots. +- Creating before/after evidence for `verify-this`. + +## Setup Pattern + +1. Start the app locally using the repo's documented dev command. +2. Discover existing local harnesses: Playwright tests, Cypress specs, Storybook, browser scripts, Electron launch scripts, or snapshot tools. +3. For a web app, connect to the local URL with the existing browser tooling. +4. For Electron/Chromium, enable a remote debugging port when supported. +5. Select the correct page by stable app markers, not by tab order alone. +6. Prefer accessibility roles, labels, and stable `data-*` selectors over coordinates. + +## Generic Web Harness + +Use the repo's installed browser tooling when possible. If the repo already has Playwright, a minimal one-off probe looks like: + +```javascript +import { chromium } from "playwright"; + +const browser = await chromium.launch(); +const page = await browser.newPage({ viewport: { width: 1280, height: 800 } }); +await page.goto("http://127.0.0.1:"); +await page.getByRole("button", { name: /submit/i }).click(); +await page.screenshot({ path: "/tmp/ui-harness-after.png", fullPage: true }); +await browser.close(); +``` + +Do not add Playwright as a project dependency just for this probe unless the user asks. Prefer existing dev dependencies or external browser tools already available in the environment. + +## Generic CDP Harness + +For Electron or a Chromium app launched with `--remote-debugging-port=`, connect over CDP: + +```javascript +import { chromium } from "playwright"; + +const browser = await chromium.connectOverCDP("http://127.0.0.1:"); +const pages = browser.contexts().flatMap((context) => context.pages()); +let page; +for (const candidate of pages) { + if (await candidate.locator("").count()) { + page = candidate; + break; + } +} + +if (!page) { + console.log(await Promise.all(pages.map(async (p) => ({ + title: await p.title(), + url: p.url(), + })))); + throw new Error("No matching app page found"); +} + +await page.screenshot({ path: "/tmp/ui-harness-cdp.png", fullPage: true }); +await browser.close(); +``` + +Replace `` with a stable marker from the current repo, such as a root app node, landmark, or product-specific `data-*` attribute. + +## Interaction Loop + +1. Capture a page snapshot or screenshot before acting. +2. Choose a target from the latest page structure. +3. Perform exactly one structural action: click, type, keypress, drag, scroll, navigate, or resize. +4. Capture a fresh snapshot/screenshot. +5. Verify the expected state change. +6. Save artifacts for before/after comparisons when the user asked for proof. + +## CDP Capabilities + +Use raw CDP only when higher-level browser APIs are insufficient: + +- Performance: CPU profiles, traces, paint flashing, FPS meter, layout shift inspection. +- Memory: heap snapshots and forced GC for leak investigations. +- Network: request blocking, throttling, cache disablement, request/response logs. +- Rendering: viewport changes, color scheme emulation, reduced motion, accessibility checks. +- Debugging: console streaming, exception capture, DOM snapshots. + +## Page Selection + +When multiple app windows/tabs share a debug port: + +- Prefer a positive marker for the surface under test, such as an app root selector. +- Use a negative marker to avoid the wrong surface when necessary. +- If no page matches, list available page titles and URLs instead of guessing. + +## Guardrails + +- Do not rely on stale element references after navigation or structural changes. +- Avoid coordinate clicks unless a fresh screenshot was captured immediately before the click. +- Keep test data local and disposable. +- Do not store screenshots or heap snapshots from privacy-sensitive workspaces unless the user explicitly agrees. +- Do not hard-code selectors, ports, or script paths from another repository. Discover the current repo's local app markers. +- Clean up dev servers, debug sessions, and temp profiles when done. diff --git a/skills/deslop/SKILL.md b/skills/deslop/SKILL.md new file mode 100644 index 0000000..1b3827c --- /dev/null +++ b/skills/deslop/SKILL.md @@ -0,0 +1,22 @@ +--- +name: deslop +description: Remove AI-generated code slop and clean up code style +--- + +# Remove AI code slop + +Check the diff against main and remove AI-generated slop introduced in the branch. + +## Focus Areas + +- Extra comments that are unnecessary or inconsistent with local style +- Defensive checks or try/catch blocks that are abnormal for trusted code paths +- Casts to `any` used only to bypass type issues +- Deeply nested code that should be simplified with early returns +- Other patterns inconsistent with the file and surrounding codebase + +## Guardrails + +- Keep behavior unchanged unless fixing a clear bug. +- Prefer minimal, focused edits over broad rewrites. +- Keep the final summary concise (1-3 sentences). diff --git a/skills/poteto-help/SKILL.md b/skills/poteto-help/SKILL.md index 893eae1..0755277 100644 --- a/skills/poteto-help/SKILL.md +++ b/skills/poteto-help/SKILL.md @@ -107,7 +107,6 @@ Close calls: Not in pstack: -- `/deslop`, `control-cli`, and `control-ui` ship in the `cursor-team-kit` plugin. - `/loop` is a Devin built-in. - pstack has no `/orchestrate` skill. Orchestrate is a `/pstack:poteto-mode` playbook. If the slash menu shows `/orchestrate`, another plugin provides it. diff --git a/skills/poteto-mode/SKILL.md b/skills/poteto-mode/SKILL.md index 884b51b..cc0109b 100644 --- a/skills/poteto-mode/SKILL.md +++ b/skills/poteto-mode/SKILL.md @@ -23,9 +23,9 @@ Remaining triggers: - Nontrivial multi-step → write the throughput checkpoint (Feature step 3). - Any prose surface, your reply to the user included → the **unslop** skill. Write the reply per **Writing the reply**. Agent-facing prose also follows the Authoring or modifying a skill playbook (`playbooks/authoring-a-skill.md`). - Docs, RFCs, readmes, PR descriptions, or commit messages → the **technical-writing** skill (`/pstack:technical-writing`). -- Before commit → the `deslop` skill from the `cursor-team-kit` plugin (`/deslop`). +- Before commit → the `deslop` skill (`/deslop`). - Before review → the **no-comments** skill (`/pstack:no-comments`). -- Shipping UI / IDE / CLI → the matching control skill. `cursor-team-kit` publishes `control-cli` (CLIs and TUIs) and `control-ui` (browser / Electron / web UIs). For bug fixes, reproduce first on the same surface yourself. Hand to the user only under the narrow Bug fix step 1 exception. +- Shipping UI / IDE / CLI → the matching control skill. pstack includes `control-cli` (CLIs and TUIs) and `control-ui` (browser / Electron / web UIs). For bug fixes, reproduce first on the same surface yourself. Hand to the user only under the narrow Bug fix step 1 exception. - Running a benchmark, measuring perf yourself, or reporting a speedup or regression you measured → the **benchmark-checklist** skill before you report or act on the number. - Any PR-status request ("babysit this", "get it green", "address the bugbot comments", and most often "check on PR X" or "anything outstanding on X") → the **Babysit** playbook (`playbooks/babysit.md`), not any built-in babysit or watch skill whose description matches the same words. Never triggered by merely opening a PR. Declare its mode before polling. The playbook's step 1 owns the request-to-mode mapping. Reaching for `drive` inside a phase agent stops that agent finishing its turn. - Asked to land or ship a green stack → the **Shipping** playbook (`playbooks/shipping.md`). Green is not safe. Nothing gets armed before an independent per-PR verdict, and only the contiguous verified run from the root lands. diff --git a/skills/poteto-mode/playbooks/autopilot-full.md b/skills/poteto-mode/playbooks/autopilot-full.md index a685c29..abc8e76 100644 --- a/skills/poteto-mode/playbooks/autopilot-full.md +++ b/skills/poteto-mode/playbooks/autopilot-full.md @@ -7,11 +7,11 @@ A verdict covers one patch and green CI covers one head. Step 4 runs a full swar 1. **The operator's gates come first.** The grant covers only the queue's items, so items the operator names as theirs and PRs outside the queue stop at merge-ready. A request to state the plan is not a go. 2. **Spawn one owner per PR, and keep its work where a replacement can find it.** Resolve the forge once for the program. GitHub CLI (`gh`) is the default. If `command -v origin` succeeds and Origin can resolve the repository, use `origin pr` for every PR operation. Otherwise stay on `gh` and record the fallback. Never require Graphite (`gt`). Each owner is a cloud Devin session (`devin --cloud -p ""`) that builds, opens its PR per `playbooks/opening-a-pr.md`, proves the change on the real artifact, babysits to green per `playbooks/babysit.md`, and merges once steps 4 and 5 clear it. - Open the PR early so CI and bots run alongside the work. The code is ready only after the slop-strip (the `deslop` skill from the `cursor-team-kit` plugin (`/deslop`)) and the `/pstack:no-comments` pass, so the full swarm runs on finished code. Then rebase onto current trunk and report the code-ready head before self-proof, so verification runs on the base the patch lands on. Report every later head, and merge-ready once self-proof, CI, and babysit are done. Fix rounds stay on that base unless trunk conflicts or breaks CI, because each rebase restarts CI. Run the repo's checks for the touched paths on the committed head before the code-ready push and before a later push that needs a verifier. + Open the PR early so CI and bots run alongside the work. The code is ready only after the slop-strip (the `deslop` skill (`/deslop`)) and the `/pstack:no-comments` pass, so the full swarm runs on finished code. Then rebase onto current trunk and report the code-ready head before self-proof, so verification runs on the base the patch lands on. Report every later head, and merge-ready once self-proof, CI, and babysit are done. Fix rounds stay on that base unless trunk conflicts or breaks CI, because each rebase restarts CI. Run the repo's checks for the touched paths on the committed head before the code-ready push and before a later push that needs a verifier. Assume the VM dies. Soon after starting, push and start a decision trail in the root agent's store (path in the system prompt) per the **show-me-your-work** skill, then push after every unit worth keeping. Whoever spawns a subagent records its id, state, and a stuck-after runtime from past runs of its kind in that store, so the root can probe it if the parent dies. Force-push only your own branch, with `--force-with-lease` pinned to the SHA you last pushed or took over, and on any push you did not make, stop and report to the root. 3. **Run owners in parallel off trunk, never stacked,** so each PR lands on its own. -4. **Swarm-verify once.** A full swarm runs once, at the code-ready head. Another full swarm runs only for new behavior, a redesign, or a large new diff. A rebase, a merge-conflict resolution, or a minor fix gets a single verifier at the new head. Fan out independent verifiers at the code-ready SHA per the **swarm** skill. They re-run the gates, prove the load-bearing behavior live on the real surface through its control skill (such as `control-ui` or `control-cli` from `cursor-team-kit`) or a named driver, and audit the diff. The verdict is not clean without the live lane, or before you audit the merge-ready report's receipts, because no lane trusts a claim it has not checked. +4. **Swarm-verify once.** A full swarm runs once, at the code-ready head. Another full swarm runs only for new behavior, a redesign, or a large new diff. A rebase, a merge-conflict resolution, or a minor fix gets a single verifier at the new head. Fan out independent verifiers at the code-ready SHA per the **swarm** skill. They re-run the gates, prove the load-bearing behavior live on the real surface through its control skill (such as `control-ui` or `control-cli`) or a named driver, and audit the diff. The verdict is not clean without the live lane, or before you audit the merge-ready report's receipts, because no lane trusts a claim it has not checked. Send every proven finding, whatever a lane labeled it, to the owner in one fix-forward, with a red test across every site with the same defect. A defect trunk shows without the PR is recorded against trunk and does not gate the PR, but one the PR copies or newly reaches is the PR's own. Never push a fix yourself, because each branch has one writer. Replace a stuck owner instead. 5. **The owner merges only what you verified, tested on the trunk it lands on.** Green CI alone never authorizes a merge. Once the swarm's lanes have started, merge prep rebases onto current trunk, reports the new head, and waits for green CI. diff --git a/skills/poteto-mode/playbooks/multi-phase-plan.md b/skills/poteto-mode/playbooks/multi-phase-plan.md index c4d7dd6..e97ba14 100644 --- a/skills/poteto-mode/playbooks/multi-phase-plan.md +++ b/skills/poteto-mode/playbooks/multi-phase-plan.md @@ -12,7 +12,7 @@ **Verification.** Tests alone are not sufficient verification. A PR is verified only when its unit, live, and perf boxes are all checked (the **prove-it-works** principle skill). That sentence is the verification rule. Every verification block opens with it. The live block is mandatory. Ten lanes at the PR head drive the real surface through its control skill, per the **swarm** skill, on the `swarm workers` model (default `swe-2-high`). Each lane is one box with a concrete scenario, the screenshot it saves, and its pass predicate. One lane is the **Regression lane against trunk.** It runs the same load-bearing scenario on trunk and head. If trunk does not have the feature, the lane records that fact and gates the behavior the diff adds plus the end state the user waits for instead of inventing a trunk result. The perf gate is dual-sided. Trunk and head must both produce the named metric. If trunk lacks the feature, also isolate the work the diff adds and set an absolute budget for that work plus the end-to-end state the user waits for. Do not claim a ratio between unlike scenarios. The perf block names the metric, the interleaved probe, the trunk baseline measured first, and the rule with the number that fails. A PR that changes an interaction is review-gated. The operator reviews it in chat with screenshots and a video before merge. A PR that changes no interaction writes `**Review gate.** None. is not review-gated.` and no boxes under it. -**Control skill.** Pick it by surface. Browser, Electron, and web UIs use `control-ui` from `cursor-team-kit`. CLIs and TUIs use `control-cli` from `cursor-team-kit`. Native mobile uses whatever simulator-driving skill the repo has. A PR that touches two surfaces gets lanes on both. A surface with no control skill is a risk in Appendix C, and its live block still names how each lane drives it. +**Control skill.** Pick it by surface. Browser, Electron, and web UIs use `control-ui`. CLIs and TUIs use `control-cli`. Native mobile uses whatever simulator-driving skill the repo has. A PR that touches two surfaces gets lanes on both. A surface with no control skill is a risk in Appendix C, and its live block still names how each lane drives it. ````markdown # plan @@ -68,7 +68,7 @@ Tests alone are not sufficient verification. A PR is verified only when its unit ### Boot recipe, for every live lane -Each live lane runs on its own cloud VM (a `devin --cloud -p` session) or worktree at the PR head. Drive through `control-ui` or `control-cli` from `cursor-team-kit`. +Each live lane runs on its own cloud VM (a `devin --cloud -p` session) or worktree at the PR head. Drive through `control-ui` or `control-cli`. - [ ] `git fetch origin && git checkout `. - [ ] diff --git a/skills/poteto-mode/playbooks/opening-a-pr.md b/skills/poteto-mode/playbooks/opening-a-pr.md index e5dbe3f..2079884 100644 --- a/skills/poteto-mode/playbooks/opening-a-pr.md +++ b/skills/poteto-mode/playbooks/opening-a-pr.md @@ -6,7 +6,7 @@ Invoked at the end of every other playbook. **Commits.** Commit liberally. Rebase into small, ordered commits before opening PRs. Each commit is a future PR: landable, ordered to tell the story. Amend when the fix belongs in a just-made commit. New commit when separable. Commit bodies don't restate the subject. -**PRs.** Run `/deslop` from `cursor-team-kit` over the diff before commit and `/pstack:no-comments` before review. Write every PR title, description, and commit body with `/pstack:technical-writing` (every layer except Diátaxis, and apply the STE vocabulary rules: one word per action, keep articles, a plain verb over `-ing` where one works), then apply `/pstack:unslop`. +**PRs.** Run `/deslop` over the diff before commit and `/pstack:no-comments` before review. Write every PR title, description, and commit body with `/pstack:technical-writing` (every layer except Diátaxis, and apply the STE vocabulary rules: one word per action, keep articles, a plain verb over `-ing` where one works), then apply `/pstack:unslop`. **Titles.** Conventional Commits `type(scope): subject`, no trailing period. Type such as `feat`, `fix`, `docs`, `refactor`, `test`, `chore`, or `perf`. Scope is the area, such as `pstack` or `poteto-mode`. Subject is short, imperative, and names a real symbol when one carries the change, for example `fix(pstack): retarget opening-a-pr babysit trigger`. diff --git a/skills/poteto-mode/playbooks/orchestrate.md b/skills/poteto-mode/playbooks/orchestrate.md index e27d775..13b1d09 100644 --- a/skills/poteto-mode/playbooks/orchestrate.md +++ b/skills/poteto-mode/playbooks/orchestrate.md @@ -14,7 +14,7 @@ Three rules carry the rest. - **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, chain rebases, 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 run_subagent. Pick each subagent's reasoning level and fast or standard speed for the job, per the Subagents section. State reads and writes go through `scripts/orch/orch.ts` at drain points, one command in and one line out. 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 `run_subagent` schema, gated by the profile's `max-nesting`). 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.** A cloud Devin session (`devin --cloud -p ""`) by default, unless the task needs this machine: `control-ui` or `control-cli` runtime verification (from `cursor-team-kit`), reading local session transcripts, simulators and local IDE state, auth that exists only here. Cloud sessions cannot read the local store, so their briefs inline what they need or point at repo paths. They also load plugin skills without plugin subagent profiles — a cloud worker cannot spawn `pstack-*` delegates, so any role that fans out (sub-coordinators, reviewers) stays local and cloud workers stay leaf-level. Prefer fewer, broader workers. One writer per worktree or branch (principle-separate-before-serializing-shared-state). Run a unit's verifier on a different model family from its worker. +- **Worker / verifier.** A cloud Devin session (`devin --cloud -p ""`) by default, unless the task needs this machine: `control-ui` or `control-cli` runtime verification, reading local session transcripts, simulators and local IDE state, auth that exists only here. Cloud sessions cannot read the local store, so their briefs inline what they need or point at repo paths. They also load plugin skills without plugin subagent profiles — a cloud worker cannot spawn `pstack-*` delegates, so any role that fans out (sub-coordinators, reviewers) stays local and cloud workers stay leaf-level. Prefer fewer, broader workers. One writer per worktree or branch (principle-separate-before-serializing-shared-state). Run a unit's verifier on a different model family from its worker. 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. diff --git a/skills/poteto-mode/playbooks/shipping.md b/skills/poteto-mode/playbooks/shipping.md index db46069..3e97417 100644 --- a/skills/poteto-mode/playbooks/shipping.md +++ b/skills/poteto-mode/playbooks/shipping.md @@ -2,7 +2,7 @@ **You own what lands. Verify each PR independently, land only the verified run from the root, then keep your hands off the stack.** -1. **Resolve the forge, then verify each PR independently before it lands.** GitHub CLI (`gh`) is the default. If `command -v origin` succeeds and Origin can resolve the repository, use `origin pr` for every PR operation. Otherwise stay on `gh` and record the fallback. Never require Graphite (`gt`). One verifier per PR, each a cloud Devin session (`devin --cloud -p ""`), runs the change the way a user would with the matching control skill (such as `control-ui` or `control-cli` from `cursor-team-kit`), parent against head, and posts `PASS`, `PASS+NOTES`, or `FAIL` on that PR. Only a verdict from an agent that did not write the code counts, because an author checks what it meant to build. Green CI and an approving bot review are not verdicts, because neither runs the change as a user would. +1. **Resolve the forge, then verify each PR independently before it lands.** GitHub CLI (`gh`) is the default. If `command -v origin` succeeds and Origin can resolve the repository, use `origin pr` for every PR operation. Otherwise stay on `gh` and record the fallback. Never require Graphite (`gt`). One verifier per PR, each a cloud Devin session (`devin --cloud -p ""`), runs the change the way a user would with the matching control skill (such as `control-ui` or `control-cli`), parent against head, and posts `PASS`, `PASS+NOTES`, or `FAIL` on that PR. Only a verdict from an agent that did not write the code counts, because an author checks what it meant to build. Green CI and an approving bot review are not verdicts, because neither runs the change as a user would. 2. **Land only the contiguous verified run rooted at the bottom.** Walk up from the lowest unmerged PR and stop at the first one without `PASS` or `PASS+NOTES`. The PRs below it are the run, and the top one is the ceiling. A verified PR above an unverified one waits, because it cannot land without the code below it. One whose branch neither holds nor needs that code can move onto trunk and land on its own. It needs a fresh verdict first, because its old one ran with that code beneath it and trunk does not have it. 3. **Re-check that the verdicts still describe the code.** A verdict covers a patch, and a chain rebase moves every PR above it to a new SHA without failing any check. Compare `git patch-id` at the verdict SHA with the current head before trusting an older verdict. When the patches differ only in tests, docs, or lint config, a lane's result stands if what it ran builds the same at both SHAs apart from noise. Noise is a difference that also shows up between two builds of the verdict SHA, or an embedded commit SHA. Report each kind of noise with its files, so a reader can check the call. The change itself still gets fresh checks and a review, because the old verdict never saw it. A lane with no build output, such as a dev server, cannot show this, so rerun it, and re-verify anything else that drifted. 4. **Land bottom-up, one PR at a time.** Always merge the run's lowest unmerged PR, with `origin pr merge ` or `gh pr merge --squash`. On Origin the plain command also merges every PR below the one you name, and on GitHub a PR whose base is still its parent's branch merges into that branch, not trunk. Read the PR back for the result (`origin pr view ` or `gh pr view --json state,mergedAt,baseRefName`), because a merge command can report success when a merge queue only queued the PR, and a requested auto-merge is not a merge. A landed PR reads merged with trunk as its base, not its parent's branch. Arm `--auto` (Origin merge-when-ready or GitHub auto-merge) only on a PR whose verdict covers its current head, because it lands whatever head is ready. After a merge lands, retarget the PR whose base was the merged branch to trunk (`origin pr edit --base ` or `gh pr edit --base `), move its patch onto the merge result, and push with `--force-with-lease`. The verdict covers the patch, not its commits, so step 3's patch-id rule decides whether the verdict survives. Merge it once its checks pass and its verdict survives.