Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion PORTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Upstream is the source of truth for the workflows themselves. This file records
- `worktree-audit.sh` and the [Worktree cleanup playbook](skills/poteto-mode/playbooks/worktree-cleanup.md) guard kept files, a port fix for #167 from 2026-10 that can be offered upstream. Steps 4 and 5 own the output contract and removal guard. On sync, preserve the script's NUL-delimited status parsing and explicit `--ignored=matching`, `--untracked-files=normal`, and `--ignore-submodules=none` flags. Preserve the nested `.git` scan, which reports a checkout even under an ignored build cache and skips one under an already reported kept directory. Preserve the `git ls-files -v` count of present skip-worktree and assume-unchanged files as `wip`, the case-insensitive fixed-string `rg -F -i` transcript match, and the `unreadable` result with bucket `hold-kept` when status, `ls-files`, or the scan fails. Preserve the porcelain worktree-path parsing with `sed -n 's/^worktree //p'` for paths with spaces. Keep the regression coverage in `tools/test_worktree_audit.py` and `WorktreeAuditPromises` in `evals/promises/test_scripts.py` when upstream rewrites either file, and keep the `ripgrep` install in the `lint.yml` skills job, without which most of `tools/test_worktree_audit.py` skips. Do not restore upstream's disposable `scratch:N` classification.

- **documentation-impact** (`skills/documentation-impact/`) is a port addition for authoring and independently reviewing documentation affected by a change. Preserve its auto-invocable metadata, `tools/skill-trigger-cases.json` entry, README and guide entries, central Poteto completion trigger, and Babysit and Shipping readiness hooks during sync. Preserve its canonical author result rules. The pass covers local work without a PR and binds any required independent review verdict to the examined artifact and documentation context. Visual tools remain optional. Keep model selection and lifecycle orchestration in the calling workflow.
- **pr-recap** (`skills/pr-recap/`) is a port addition that posts one reviewer recap comment per pull request: a two-sentence story, one hand-drawn sketch rendered by the bundled Bun tool in `scripts/sketch` and attached with `gh`, a "Not covered" line, and a collapsed details block. `skills/pr-recap/CREDITS.md` carries the MIT notices for the six skills its rules adapt and the OFL notice for the vendored Excalifont subset. On sync, keep the skill, its trigger row, the **Recap** paragraph in Opening a PR, the sketch tests in `tests/skills/pr-recap/`, and their `lint.yml`, `tools/gate-check.sh`, and Dependabot entries. Its refresh trigger in `skills/poteto-mode/references/task-triggers.md` is also a port addition, so keep that line when a sync rewrites the trigger list.
- **pr-recap** (`skills/pr-recap/`) is a port addition that posts one reviewer recap comment per pull request: a two-sentence story, one hand-drawn sketch rendered by the bundled Bun tool in `scripts/sketch` and attached with `gh`, a "Not covered" line, and a collapsed details block. `skills/pr-recap/CREDITS.md` carries the MIT notices for the six skills its rules adapt and the OFL notice for the vendored Excalifont subset. On sync, keep the skill, its trigger row, the **Recap** paragraph in Opening a PR, the sketch tests in `tests/skills/pr-recap/`, and their `lint.yml`, `tools/gate-check.sh`, and Dependabot entries. Its refresh trigger in `skills/poteto-mode/references/task-triggers.md` and the `threads-only` sentence in step 1 of `skills/poteto-mode/playbooks/babysit.md` are also port additions, so keep that line and that sentence when a sync rewrites them.
- **statechart** (`skills/statechart/`) keeps upstream's scripts. Its tests live in `tests/skills/statechart/scripts/test/`, per the tests-out-of-`skills/` rule. Upstream runs them in a `validate-plugins.yml` step. Here they run in the `statechart script tests` step of the `lint.yml` skills job and in the `statechart node tests` line of the `gate-check.sh` test tier, both as `node --test` over `*.test.mjs`. CI uses the runner's preinstalled Node, because `tools/test_repository_hardening.py` bans `setup-node`. On sync, carry upstream changes to that step into both places.
- **deslop** (`skills/deslop/`) is a port addition that replaces cursor-team-kit's `/deslop` with a pstack-owned code cleanup pass: nineteen numbered rules over the branch's changed hunks, a test run that proves behavior unchanged, and a report. `skills/deslop/CREDITS.md` ships inside the skill directory so the MIT notices travel with every `npx skills` copy. On sync, keep the skill, its trigger row in `tools/skill-trigger-cases.json`, the README and guide entries, poteto-mode's Before every commit or amend trigger, the deslop lines in Opening a PR, both autopilot playbooks, and the multi-phase checklist, step 5's hand-off to the no-comments skill and its Report line, and the ledger promises `deslop-available-for-code`, `opening-a-pr-deslops-diff`, `deslop-cleans-code-slop`, and `deslop-hands-unsettled-comments-to-no-comments`. Upstream never writes `skills/deslop/`; if it ever does, keep whichever version has the rule table.
- **Gated publish** (port addition, 2026-10). In a repository that gates pushes through no-mistakes, Opening a PR's **Gated publish** section routes every publish, PR creation, restack, and retarget through the no-mistakes CLI, sends work-in-progress snapshots to `refs/pstack/wip/<branch>` or the repository's own agent ref convention, and hands sandbox work to the host. On sync, keep that section, the gated pointers in Babysit, Shipping, Autopilot-full, Autopilot-stack, Orchestrate, and the multi-phase checklist, the guide paragraph in `docs/guide/06-verify-and-ship.md`, the `no-mistakes` line in `tools/cross-suite-foreign.txt`, and the `opening-a-pr-gated-publish-*` ledger promises with the `open-pr-gated-run` case.
Expand Down
2 changes: 1 addition & 1 deletion skills/poteto-mode/playbooks/babysit.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Babysitting starts when the user asks for it, which is normally once a phase or

`drive` reaches merge-ready when forge readiness and the current author result hold, plus a current independent review when that result requires one. Landing the stack is `playbooks/shipping.md`.

1. **Declare the mode and resolve the forge before any poll.** `drive` runs the loop to merge-ready, for "babysit this", "get it green", "merge-ready". `background` triages without blocking, which is the mode for a plan still executing. `threads-only` answers review comments and touches nothing else, for "address the bugbot comments" or "address the copilot comments". `check` is one status pass and a report, for "check on X" and "is it green". Undeclared defaults to `drive`. Small or docs-only PRs get `check`, not `drive`. GitHub CLI (`gh`) is the default. If `command -v origin` succeeds and Origin can resolve the repository, use `origin pr ...` for view, checks, threads, and later shipping. Otherwise stay on `gh` and record the fallback. Never require Graphite (`gt`).
1. **Declare the mode and resolve the forge before any poll.** `drive` runs the loop to merge-ready, for "babysit this", "get it green", "merge-ready". `background` triages without blocking, which is the mode for a plan still executing. `threads-only` answers review comments and touches nothing else, for "address the bugbot comments" or "address the copilot comments". A fix push in this mode still refreshes the PR recap per [task triggers](../references/task-triggers.md). `check` is one status pass and a report, for "check on X" and "is it green". Undeclared defaults to `drive`. Small or docs-only PRs get `check`, not `drive`. GitHub CLI (`gh`) is the default. If `command -v origin` succeeds and Origin can resolve the repository, use `origin pr ...` for view, checks, threads, and later shipping. Otherwise stay on `gh` and record the fallback. Never require Graphite (`gt`).
2. **Work the merge frontier and nothing above it.** The lowest unmerged PR is the only one that matters until it merges. Upstack threads get read and batched, never fixed at the cost of restarting the frontier's checks. If you catch yourself upstack while the frontier is red, stop and go back down.
3. **One babysitter per stack.** Before starting, check nothing else is already on it.
4. **Never mutate stack topology.** No base retarget, rebase, stack-wide submit, or force-push from inside a babysit. Fix on the owning branch, report anything rebase-shaped upward, and let the owner do it. An Autopilot-full owner babysitting its own PR is that owner. Where this playbook says to report a rebase, that owner rebases its own branch and publishes it with `git push --force-with-lease` per `playbooks/autopilot-full.md` step 2. In Autopilot-stack, the root is that owner. The one sanctioned creation: when a fix's owning PR has already merged, it becomes a new PR on top of the remaining stack, never a rewrite of merged history, and it is the single case where the frozen queue list of step 6 changes. In a gated repository, follow the gated publish rules in `playbooks/opening-a-pr.md`. Nobody force-pushes a PR branch, and the owner's rebase follows the `rerun` rule there.
Expand Down
2 changes: 1 addition & 1 deletion skills/poteto-mode/references/task-triggers.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Read this reference for the actions named by the mode entry, or when scope chang
- Shipping UI / IDE / CLI → use the project's verification skill (`verify-<app>`, generated by the **create-verification-skill** skill), which drives the real surface — browser, Electron, web UI, CLI, or TUI. 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 → use 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 skill your CLI ships, even when its 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.
- A push changed an open PR's diff, whether yours, an Autopilot owner's, a Babysit or Shipping wave, or a gate fix round → once the new head is published and any gate run has reached its outcome, use the **pr-recap** skill to refresh the PR's recap.
- A push changed an open PR's diff, whether yours, an Autopilot owner's, a Babysit or Shipping wave, or a gate fix round → once the new head is published and any gate run has reached its outcome, use the **pr-recap** skill to refresh the PR's recap. A `threads-only` Babysit fix push refreshes it like any other push. An operator's hold or zero-writes order wins: post no recap, and report the refresh as pending until the operator releases the hold.
- 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.
- Bugbot, Copilot code review, GitHub Advanced Security, or another automated security reviewer commented → skeptical posture. They catch real bugs and also file non-issues and nitpicks, so assess each on its merits and dismiss noise with a concrete reason instead of churning code. Triage fix / dismiss / ask per `bugbot-triage.md`.
- Broken skill mid-task → fix it in its own PR. Don't block. Don't silently work around it.
Expand Down
2 changes: 1 addition & 1 deletion skills/pr-recap/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ When your runtime cannot run Bun, or cannot show you an image, skip the sketch.
1. List each factual sentence in the recap and each label in the sketch.
2. Check each one against a hunk of the diff or a SHA-pinned line. Mark it verified, corrected, unsupported, or unverifiable.
3. Fix each corrected claim. Delete each unsupported or unverifiable claim, or rewrite it as a guess. Re-render the sketch if a label changed.
4. Check each link. Pin source links to the recorded head SHA. Review and CI links must point at records on the PR, with CI runs on that head. Never link a bot's review, because a recap does not triage its findings, and watch-pr and merge-gate never count a recap as acknowledging one.
4. Check each link. Pin source links to the recorded head SHA. Review and CI links must point at records on the PR, with CI runs on that head. Never include a bot review's URL anywhere in the comment, code spans included. A recap does not triage a review's findings, and watch-pr and merge-gate never count a recap as acknowledging one.
5. Read `headRefOid` again. If it moved, rebuild the recap from the new diff.

Keep the marks in your notes, not in the comment. Report the counts in your reply.
Expand Down
8 changes: 5 additions & 3 deletions skills/pr-recap/references/sketch.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,10 @@ Render again and repeat the read once. Report the reader's model and what you ch

## Setup

The tool needs Bun. Its pinned dependencies are in [its package.json](../scripts/sketch/package.json): Rough.js for the strokes, opentype.js to measure text, and resvg to write the PNG. On its first run, and after `package.json` or `bun.lock` changes, the tool runs `bun install --frozen-lockfile`, which needs network access. It first tries its own folder. If installation there fails, it creates a fresh private temporary folder and installs there for that invocation. None of the packages starts a browser. A sandbox needs a writable output folder and either a writable skill folder or a writable temporary folder for the dependencies.
The tool needs Bun 1.4.0 or later. Earlier releases cannot read its `bun.lock`. Most fail, for example with `Unknown lockfile version`, and the tool exits 2. Some ignore the lockfile and install unpinned packages. With a Bun older than 1.4.0, run `npx --allow-scripts=bun [email protected] "<skill>/scripts/sketch/sketch.mjs" scene.json sketch.png`, which needs Node and network access. Without `--allow-scripts=bun`, npm 12 skips Bun's install script and the command fails. `npm ci` does not work here, because the folder has no `package-lock.json`.

Image viewing and Bun execution remain untested on Hermes only. Follow the skill's [sketch fallback](../SKILL.md#draw-the-sketch) when either capability is unavailable.
Its pinned dependencies are in [its package.json](../scripts/sketch/package.json): Rough.js for the strokes, opentype.js to measure text, and resvg to write the PNG. On its first run, and after `package.json` or `bun.lock` changes, the tool runs `bun install --frozen-lockfile`, which needs network access. It first tries its own folder. If installation there fails, it creates a fresh private temporary folder and installs there for that invocation. None of the packages starts a browser. A sandbox needs a writable output folder and either a writable skill folder or a writable temporary folder for the dependencies.

When the tool exits 2, read its message. If it cannot install a package or write the PNG, skip the sketch and say why in your reply.
Hermes v0.22.4 has run the tool and viewed the PNG with `vision_analyze`. Follow the skill's [sketch fallback](../SKILL.md#draw-the-sketch) when either capability is unavailable.

When the tool exits 2, read its message. If it could not install a package, run the `npx` command above unless you already did. Skip the sketch and say why in your reply when that command also fails or the tool cannot write the PNG.
22 changes: 22 additions & 0 deletions tests/skills/poteto-mode/scripts/watch-pr/review-bodies.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { describe, expect, it } from "bun:test";
import { readFileSync } from "node:fs";
import { join } from "node:path";
import {
buildReviewState,
parseReviewStatePage,
Expand Down Expand Up @@ -326,6 +328,26 @@ describe("acknowledging a flagged review", () => {
).toEqual(["open"]);
});

describe("the comment the pr-recap skill writes", () => {
const skill = join(import.meta.dir, "../../../../../skills/pr-recap");
const block = readFileSync(join(skill, "references/block.md"), "utf8");
const template = block.match(/````markdown\n([\s\S]*?)\n````/)?.[1] ?? "";

it("never acknowledges a review, even when it names the review's URL", () => {
expect(template).toStartWith("<!-- pstack-recap:start -->");
expect(
statusOf([
comment({
id: 1,
body: `${template}\n\nReviewed: ${link}`,
login: "mdsmithaustin",
association: "OWNER",
}),
])
).toEqual(["open"]);
});
});

it("rejects a comment that mentions the review without linking it", () => {
expect(
statusOf([
Expand Down
Loading