diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index d1e920db..cf9c7c18 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -10,7 +10,7 @@ "name": "t3-pstack", "source": "./plugins/pstack", "description": "pstack for T3 Code: rigorous agent workflows whose panels and fan-outs run across model families through T3. Original pstack by Lauren Tan (poteto).", - "version": "2.0.0-rc.4" + "version": "2.0.0-rc.5" } ] } diff --git a/CHANGES.md b/CHANGES.md index 772cdeba..269e5452 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,18 @@ This file is the release changelog, with one `## - ` entry per release, newest first. The Cursor-to-T3 rewrite rules live in [`tools/substitutions.json`](tools/substitutions.json), and the [sync boundary](CONTRIBUTING.md#the-sync-boundary) in `CONTRIBUTING.md` defines how a change to upstream's skill content is declared. +## 2.0.0-rc.5 - Lauren's `e5136d8`: four principles restated as reasoning + +t3-pstack moves to Lauren Tan's pstack at cursor/plugins `e5136d8` for all three components. Only pstack changed upstream, and its version stays 0.15.25: four principles that banned or prescribed specific mechanisms now state the idea an agent derives each call from ([pstack #633](https://github.com/cursor/plugins/pull/633)). `poteto-mode`'s principles index and `/correct`'s test step follow. `bun tools/sync.mjs` wrote the four principle leaves and `/correct` cleanly, and merged `poteto-mode` around its declared fork's four rules with no conflict. No rule anchors on the changed text, so the port's diff to these six files is upstream's line for line. At `e5136d8` each component's dry run reports no undeclared fork, no denylist hit, and no substitution that matches nothing. Upstream's README and guide changes fall under paths the port excludes, and neither hooks file changes. + +| Change | 2.0.0-rc.4 | 2.0.0-rc.5 | Source | +| --- | --- | --- | --- | +| Test Behavior, Not Implementation | A test calls the code as its users do and asserts the exact result they see. Five assertion shapes fail, among them `toBeDefined` and `toHaveBeenCalled`, and a test that would pass if every imported function returned `undefined` is rewritten or deleted. | A test asserts what the code's users can observe. Judge it against two imagined edits: it must fail when the behavior breaks and keep passing when only the internals change. The contract decides, not the assertion's shape, so an absence check or a mock payload can be behavior. | pstack #633 | +| Fix Root Causes | Reproduce, ask why until the root cause, and never add a guard, since a nil check that silences a crash is a symptom fix. | The root cause is the first place the system went wrong. A guard is the fix when the state it handles is legitimate, and hides the bug when that state should never exist. | pstack #633 | +| Attack the Premise | After two failed fixes on one premise, take a per-actor census of the imbalance before the next fix, and rotate or move the role the skew reveals. | Write the premise down and test it with an observation that would differ if it were false, then follow the evidence. The census and the actor framing are gone. | pstack #633 | +| Make Operations Idempotent | Four prescribed patterns: convergent startup, content-based cleanup, PID-based stale locks, idempotent scheduling. | Derive each step from the state that exists and apply only the difference. Anything a run leaves behind must be recognizable as stale by the next run, wherever the previous one stopped. | pstack #633 | +| `/correct` test step | Fix or delete a test that would pass if every function it calls returned nothing. | Fix or delete a test that passes when the behavior it checks breaks, or fails when only the internals change. | pstack #633 | + ## 2.0.0-rc.4 - Lauren's 0.15.25: `/ketchup` explains changes with pictures t3-pstack moves to Lauren Tan's pstack 0.15.25, cursor/plugins `6ce45c5`, for all three components. Only pstack changed upstream: `/ketchup` now helps the user understand each change, not only where it stands ([pstack #628](https://github.com/cursor/plugins/pull/628)), and the version moves to 0.15.25 ([pstack #614](https://github.com/cursor/plugins/pull/614)). `bun tools/sync.mjs` wrote the `/ketchup` change cleanly. Its three rules, `html_render` for upstream's `/visualize` and the T3 state checks, each still match once. At `6ce45c5` each component's dry run reports no undeclared fork, no denylist hit, and no substitution that matches nothing. The version bump touches only upstream's `plugin.json` files, which the port excludes, and neither hooks file changes. diff --git a/NOTICE-skills.md b/NOTICE-skills.md index df193c91..88d97602 100644 --- a/NOTICE-skills.md +++ b/NOTICE-skills.md @@ -4,9 +4,9 @@ This plugin contains MIT-licensed work from five sources. The copyright notices | Included work | Upstream | Copyright | License | | --- | --- | --- | --- | -| The pstack skills, principles, scripts, and the `poteto-agent` and `comment-sicko` definitions | [cursor/plugins/pstack](https://github.com/cursor/plugins/tree/6ce45c59b9301a638c1fe1a7b8dc2a82b650898f/pstack) | (c) 2026 Lauren Tan | [MIT](LICENSE) | -| `deslop`, `make-pr-easy-to-review`, `fix-ci`, `fix-merge-conflicts`, `get-pr-comments`, and `what-did-i-get-done` | [cursor/plugins/cursor-team-kit](https://github.com/cursor/plugins/tree/6ce45c59b9301a638c1fe1a7b8dc2a82b650898f/cursor-team-kit) | (c) 2026 Cursor | [MIT](LICENSE-cursor-team-kit) | -| `thermos`, `thermo-nuclear-review`, `thermo-nuclear-code-quality-review`, and the `thermo-nuclear-review-subagent` and `thermo-nuclear-code-quality-review-subagent` definitions | [cursor/plugins/thermos](https://github.com/cursor/plugins/tree/6ce45c59b9301a638c1fe1a7b8dc2a82b650898f/thermos) | (c) 2026 Cursor | [MIT](LICENSE-thermos) | +| The pstack skills, principles, scripts, and the `poteto-agent` and `comment-sicko` definitions | [cursor/plugins/pstack](https://github.com/cursor/plugins/tree/e5136d82418d2db3165ea1050d17577cd618cc05/pstack) | (c) 2026 Lauren Tan | [MIT](LICENSE) | +| `deslop`, `make-pr-easy-to-review`, `fix-ci`, `fix-merge-conflicts`, `get-pr-comments`, and `what-did-i-get-done` | [cursor/plugins/cursor-team-kit](https://github.com/cursor/plugins/tree/e5136d82418d2db3165ea1050d17577cd618cc05/cursor-team-kit) | (c) 2026 Cursor | [MIT](LICENSE-cursor-team-kit) | +| `thermos`, `thermo-nuclear-review`, `thermo-nuclear-code-quality-review`, and the `thermo-nuclear-review-subagent` and `thermo-nuclear-code-quality-review-subagent` definitions | [cursor/plugins/thermos](https://github.com/cursor/plugins/tree/e5136d82418d2db3165ea1050d17577cd618cc05/thermos) | (c) 2026 Cursor | [MIT](LICENSE-thermos) | | The session-start hook scripts, `read-sheet.sh`, and `reflect/scripts/find-transcript.mjs`, which t3-pstack modified, and four `poteto-mode` rules, the worktree and head-guard rules in the Feature, Opening a PR, and Shipping playbooks, and three `watch-pr` fixes, which t3-pstack reworded or adapted for T3 | [michael-denyer/pstack-claude](https://github.com/michael-denyer/pstack-claude) | (c) 2026 Michael Denyer | [MIT](LICENSE) | | `poteto-mode/scripts/resolve-codex-transcript` and `resolve-codex-transcript.ts`, which t3-pstack modified | [ericlitman/open-pstack](https://github.com/ericlitman/open-pstack/tree/c5c8e237c324359a3d1929037da78fe66da3d1ed/plugins/pstack/skills/poteto-mode/scripts), [PR #151](https://github.com/ericlitman/open-pstack/pull/151) | (c) 2026 Eric A. Litman and Donncha O'Toole | [MIT](LICENSE) | diff --git a/NOTICE.md b/NOTICE.md index 14bcd271..533b43e9 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -6,9 +6,9 @@ t3-pstack is a port of [pstack](https://github.com/cursor/plugins/tree/main/psta | Component | Upstream | Copyright | License | License file | | --- | --- | --- | --- | --- | -| Every skill under `plugins/pstack/skills/` except those named in the next two rows, `plugins/pstack/agents/poteto-agent.md`, `plugins/pstack/agents/comment-sicko.md`, and the vendored scripts under `plugins/pstack/skills/poteto-mode/scripts/` | [cursor/plugins/pstack @ 6ce45c5](https://github.com/cursor/plugins/tree/6ce45c59b9301a638c1fe1a7b8dc2a82b650898f/pstack) | (c) 2026 Lauren Tan | MIT | [LICENSE](LICENSE) | -| `plugins/pstack/skills/{deslop,fix-ci,fix-merge-conflicts,get-pr-comments,make-pr-easy-to-review,what-did-i-get-done}/` | [cursor/plugins/cursor-team-kit @ 6ce45c5](https://github.com/cursor/plugins/tree/6ce45c59b9301a638c1fe1a7b8dc2a82b650898f/cursor-team-kit) | (c) 2026 Cursor | MIT | [LICENSE-cursor-team-kit](LICENSE-cursor-team-kit) | -| `plugins/pstack/skills/{thermos,thermo-nuclear-review,thermo-nuclear-code-quality-review}/`, `plugins/pstack/agents/thermo-nuclear-review-subagent.md`, `plugins/pstack/agents/thermo-nuclear-code-quality-review-subagent.md` | [cursor/plugins/thermos @ 6ce45c5](https://github.com/cursor/plugins/tree/6ce45c59b9301a638c1fe1a7b8dc2a82b650898f/thermos) | (c) 2026 Cursor | MIT | [LICENSE-thermos](LICENSE-thermos) | +| Every skill under `plugins/pstack/skills/` except those named in the next two rows, `plugins/pstack/agents/poteto-agent.md`, `plugins/pstack/agents/comment-sicko.md`, and the vendored scripts under `plugins/pstack/skills/poteto-mode/scripts/` | [cursor/plugins/pstack @ e5136d8](https://github.com/cursor/plugins/tree/e5136d82418d2db3165ea1050d17577cd618cc05/pstack) | (c) 2026 Lauren Tan | MIT | [LICENSE](LICENSE) | +| `plugins/pstack/skills/{deslop,fix-ci,fix-merge-conflicts,get-pr-comments,make-pr-easy-to-review,what-did-i-get-done}/` | [cursor/plugins/cursor-team-kit @ e5136d8](https://github.com/cursor/plugins/tree/e5136d82418d2db3165ea1050d17577cd618cc05/cursor-team-kit) | (c) 2026 Cursor | MIT | [LICENSE-cursor-team-kit](LICENSE-cursor-team-kit) | +| `plugins/pstack/skills/{thermos,thermo-nuclear-review,thermo-nuclear-code-quality-review}/`, `plugins/pstack/agents/thermo-nuclear-review-subagent.md`, `plugins/pstack/agents/thermo-nuclear-code-quality-review-subagent.md` | [cursor/plugins/thermos @ e5136d8](https://github.com/cursor/plugins/tree/e5136d82418d2db3165ea1050d17577cd618cc05/thermos) | (c) 2026 Cursor | MIT | [LICENSE-thermos](LICENSE-thermos) | | `tools/sync.mjs`, `tools/generate.mjs`, `tools/validate-skills.mjs`, `tools/plugin.mjs`, `plugins/pstack/skills/reflect/scripts/find-transcript.mjs`, `plugins/pstack/hooks/session-start.sh`, `plugins/pstack/hooks/session-start.ps1`, `plugins/pstack/skills/setup-pstack/scripts/read-sheet.sh`, and the tests that cover them, each modified by t3-pstack | [michael-denyer/pstack-claude](https://github.com/michael-denyer/pstack-claude), as merged into t3-pstack through 1.0.14 | (c) 2026 Michael Denyer | MIT | [LICENSE](LICENSE) | | Four rules in `plugins/pstack/skills/poteto-mode/SKILL.md` (load a platform's skill before deploying, stop an abandoned agent and confirm it stopped, keep a review gate closed with no independent reviewer, the `todo.md` fallback), the per-delegate worktree rule in `playbooks/feature.md`, the stop-live-agents rule in `playbooks/opening-a-pr.md`, the `--match-head-commit` guard in `playbooks/shipping.md`, and the review-gate, stale-check, and no-checks fixes in `plugins/pstack/skills/poteto-mode/scripts/watch-pr/` with their tests in `verdicts.test.ts`, each reworded or adapted for T3 by t3-pstack | [michael-denyer/pstack-claude](https://github.com/michael-denyer/pstack-claude), pull requests [#95](https://github.com/michael-denyer/pstack-claude/pull/95), [#97](https://github.com/michael-denyer/pstack-claude/pull/97), and [#153](https://github.com/michael-denyer/pstack-claude/pull/153) for watch-pr | (c) 2026 Michael Denyer | MIT | [LICENSE](LICENSE) | | `plugins/pstack/skills/poteto-mode/scripts/resolve-codex-transcript` (verbatim) and `resolve-codex-transcript.ts` (modified, see below), `tests/resolve-codex-transcript.test.mjs` (ported from its `resolve-codex-transcript.test.ts`) | [ericlitman/open-pstack @ c5c8e23](https://github.com/ericlitman/open-pstack/tree/c5c8e237c324359a3d1929037da78fe66da3d1ed/plugins/pstack/skills/poteto-mode/scripts), [PR #151](https://github.com/ericlitman/open-pstack/pull/151) | (c) 2026 Eric A. Litman and Donncha O'Toole | MIT | [LICENSE](LICENSE) | diff --git a/README.md b/README.md index f8ba31d2..6b464713 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ npx -y github:chhoumann/t3-pstack update npx -y github:chhoumann/t3-pstack doctor ``` -`npx -y github:chhoumann/t3-pstack` runs the installer from the latest commit on `main`. That is the rolling channel, the same one each home's marketplace auto-updates from. To run one release's installer, name its tag, as in `npx -y github:chhoumann/t3-pstack#v2.0.0-rc.4 doctor`. +`npx -y github:chhoumann/t3-pstack` runs the installer from the latest commit on `main`. That is the rolling channel, the same one each home's marketplace auto-updates from. To run one release's installer, name its tag, as in `npx -y github:chhoumann/t3-pstack#v2.0.0-rc.5 doctor`. `install` and `update` are the same command, and a second run changes nothing. With Node 20 or later, it installs or updates the `t3-pstack@t3-pstack` plugin in every Claude Code and Codex config home T3 can run: `~/.claude` and `~/.codex`, `$CLAUDE_CONFIG_DIR` and `$CODEX_HOME`, and the home of each `claudeAgent` and `codex` instance in T3's settings, disabled ones included. Name any other home with `--claude-home <dir>` or `--codex-home <dir>`. Each home's `t3-pstack` marketplace must come from `chhoumann/t3-pstack`, or from `--source <owner/repo|git URL|dir>` on the same run, and a home whose marketplace has another source is left as it is. A local directory needs a path such as `./t3-pstack`, since `owner/repo` always means GitHub. On Codex it also trusts t3-pstack's session-start hook, once its hooks file is the one this release pins. Codex runs a plugin's hook only once it is trusted, and T3's Codex sessions never ask, so without this step the hook never runs. Run `update` after each release. @@ -34,7 +34,7 @@ The plugin carries 62 skill directories, 24 of them `principle-*` leaves, and 4 ## Staying current -This repository syncs from Lauren's tree directly, synced against upstream `6ce45c5`. `tools/upstream.json` pins each component, `tools/substitutions.json` holds the rewrite rules and a denylist of Cursor terms, and `tools/forks.json` declares every file the port keeps in its own form and why. `bun tools/sync.mjs <component> <sha>` derives each upstream file through the rules, merges it three ways with the port's copy, and fails on an undeclared fork, a denylist hit, or a rule that no longer matches upstream. [CONTRIBUTING.md](CONTRIBUTING.md#the-sync-boundary) has the details. +This repository syncs from Lauren's tree directly, synced against upstream `e5136d8`. `tools/upstream.json` pins each component, `tools/substitutions.json` holds the rewrite rules and a denylist of Cursor terms, and `tools/forks.json` declares every file the port keeps in its own form and why. `bun tools/sync.mjs <component> <sha>` derives each upstream file through the rules, merges it three ways with the port's copy, and fails on an undeclared fork, a denylist hit, or a rule that no longer matches upstream. [CONTRIBUTING.md](CONTRIBUTING.md#the-sync-boundary) has the details. ## Data handling diff --git a/VERSION b/VERSION index dd42f9a9..e0934080 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.0.0-rc.4 +2.0.0-rc.5 diff --git a/package.json b/package.json index ed1deee9..bf3c39f0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "t3-pstack", "private": true, - "version": "2.0.0-rc.4", + "version": "2.0.0-rc.5", "description": "The installer and development tooling for t3-pstack, Lauren Tan's pstack rewritten in place for T3 Code. The plugin itself lives in plugins/pstack.", "author": { "name": "Christian Bager Bach Houmann", diff --git a/plugins/pstack/.claude-plugin/plugin.json b/plugins/pstack/.claude-plugin/plugin.json index a911a4fe..19348e5f 100644 --- a/plugins/pstack/.claude-plugin/plugin.json +++ b/plugins/pstack/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "t3-pstack", "displayName": "t3-pstack (pstack for T3 Code)", - "version": "2.0.0-rc.4", + "version": "2.0.0-rc.5", "description": "pstack for T3 Code: Lauren Tan's pstack with its Cursor mechanics rewritten in place for T3, so subagents, panels, schedules, and PR watches dispatch through T3's orchestration and panels mix Claude, GPT, and Grok.", "author": { "name": "Christian Bager Bach Houmann", diff --git a/plugins/pstack/.codex-plugin/plugin.json b/plugins/pstack/.codex-plugin/plugin.json index 5288998c..333f66cd 100644 --- a/plugins/pstack/.codex-plugin/plugin.json +++ b/plugins/pstack/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "t3-pstack", - "version": "2.0.0-rc.4", + "version": "2.0.0-rc.5", "description": "pstack for T3 Code on a Codex host: Lauren Tan's pstack with its Cursor mechanics rewritten in place for T3, so subagents, panels, schedules, and PR watches dispatch through T3's orchestration.", "author": { "name": "Christian Bager Bach Houmann", diff --git a/plugins/pstack/skills/correct/SKILL.md b/plugins/pstack/skills/correct/SKILL.md index c09f486e..c45e06f4 100644 --- a/plugins/pstack/skills/correct/SKILL.md +++ b/plugins/pstack/skills/correct/SKILL.md @@ -18,7 +18,7 @@ First, read recent commits, reverts, review comments, agent instruction files, a 1. **Eliminate it with architecture.** Give each piece of state one owner and each task one supported way. Hide internals so the wrong import fails. Replace hand-synced lists with one source of truth. Delete old ways and dead code an agent would copy. 2. **Enforce it with types so the bad state can't be written.** If bad code still compiles, add a lint or CI check whose error names the file, type, or function to use instead. If the pattern is already common, fail only when a change adds more. -3. **Test the behavior.** Fix or delete any test that would still pass if every function it calls returned nothing. +3. **Test the behavior.** Fix or delete any test that still passes when the behavior it checks breaks, or that fails when only the internals change. 4. **Write docs or agent rules last, only for judgment calls.** Nothing fails when an agent skips them. ## Fix and prove diff --git a/plugins/pstack/skills/poteto-mode/SKILL.md b/plugins/pstack/skills/poteto-mode/SKILL.md index 344539fd..d79c74f2 100644 --- a/plugins/pstack/skills/poteto-mode/SKILL.md +++ b/plugins/pstack/skills/poteto-mode/SKILL.md @@ -45,7 +45,7 @@ Read the leaf skill in full for any principle you apply. Each entry names when i - **Laziness Protocol.** Refactoring, sizing a diff, or tempted to add abstractions, layers, or signal threading. Bias to deletion and the smallest change that solves the problem. - **Foundational Thinking.** Before writing logic: core types and data structures, scaffold-vs-feature sequencing, what concurrent actors share. - **Redesign from First Principles.** Integrating a new requirement into an existing design. Redesign as if it had been foundational from day one. -- **Attack the Premise.** Two or more fixes that share one premise have failed the same gate. Take a census of which actors hold the imbalance before the next fix, then question the premise instead of writing another fix that assumes it. +- **Attack the Premise.** Two or more fixes that share one premise have failed the same gate. Write the premise down and test it directly before you write another fix that assumes it. - **Subtract Before You Add.** Sequencing an addition, refactor, or rewrite. Remove dead weight first, then build on the simpler base. - **Minimize Reader Load.** Reviewing or shaping code that's hard to trace. Count layers and hidden state, collapse one-caller wrappers, shrink mutable scope. - **Outcome-Oriented Execution.** Planned rewrites and migrations with explicit phase boundaries. Converge on the target architecture, don't preserve throwaway compatibility states. @@ -65,9 +65,9 @@ Read the leaf skill in full for any principle you apply. Each entry names when i **Verification** - **Prove It Works.** After a task, before declaring done. Verify against the real artifact, not a proxy or "it compiles". -- **Fix Root Causes.** Debugging. Trace each symptom to its root cause, reproduce first, ask why until you reach it. +- **Fix Root Causes.** Debugging. Trace each symptom back to the first place the system went wrong and fix it there. A guard is a fix only when the state it handles is legitimate. - **Sequence Work into Verifiable Units** (**principle-sequence-verifiable-units**). Multi-step work (sweeps, migrations, runs of similar edits) and how you stack commits and PRs. Break work into small units that each end in a check, verify each before the next, and order delivery so the sequence proves itself. -- **Test Behavior, Not Implementation.** Writing, changing, or keeping a test. Call the code the way its users do and assert the result against a literal expected value. If the test would still pass when every imported function returns `undefined`, rewrite the assertion or delete the test. +- **Test Behavior, Not Implementation.** Writing, changing, or keeping a test. Assert what the code's users can observe, so the test fails when that behavior breaks and keeps passing when only the internals change. - **Explain the Number.** Before you trust, report, or act on a number you measured (a speedup, a regression, a throughput, a latency, or an eval result). Find what limits it, and rule out that it measured something other than the work you think. **Delegation** diff --git a/plugins/pstack/skills/poteto-mode/references/licenses/NOTICE.md b/plugins/pstack/skills/poteto-mode/references/licenses/NOTICE.md index df193c91..88d97602 100644 --- a/plugins/pstack/skills/poteto-mode/references/licenses/NOTICE.md +++ b/plugins/pstack/skills/poteto-mode/references/licenses/NOTICE.md @@ -4,9 +4,9 @@ This plugin contains MIT-licensed work from five sources. The copyright notices | Included work | Upstream | Copyright | License | | --- | --- | --- | --- | -| The pstack skills, principles, scripts, and the `poteto-agent` and `comment-sicko` definitions | [cursor/plugins/pstack](https://github.com/cursor/plugins/tree/6ce45c59b9301a638c1fe1a7b8dc2a82b650898f/pstack) | (c) 2026 Lauren Tan | [MIT](LICENSE) | -| `deslop`, `make-pr-easy-to-review`, `fix-ci`, `fix-merge-conflicts`, `get-pr-comments`, and `what-did-i-get-done` | [cursor/plugins/cursor-team-kit](https://github.com/cursor/plugins/tree/6ce45c59b9301a638c1fe1a7b8dc2a82b650898f/cursor-team-kit) | (c) 2026 Cursor | [MIT](LICENSE-cursor-team-kit) | -| `thermos`, `thermo-nuclear-review`, `thermo-nuclear-code-quality-review`, and the `thermo-nuclear-review-subagent` and `thermo-nuclear-code-quality-review-subagent` definitions | [cursor/plugins/thermos](https://github.com/cursor/plugins/tree/6ce45c59b9301a638c1fe1a7b8dc2a82b650898f/thermos) | (c) 2026 Cursor | [MIT](LICENSE-thermos) | +| The pstack skills, principles, scripts, and the `poteto-agent` and `comment-sicko` definitions | [cursor/plugins/pstack](https://github.com/cursor/plugins/tree/e5136d82418d2db3165ea1050d17577cd618cc05/pstack) | (c) 2026 Lauren Tan | [MIT](LICENSE) | +| `deslop`, `make-pr-easy-to-review`, `fix-ci`, `fix-merge-conflicts`, `get-pr-comments`, and `what-did-i-get-done` | [cursor/plugins/cursor-team-kit](https://github.com/cursor/plugins/tree/e5136d82418d2db3165ea1050d17577cd618cc05/cursor-team-kit) | (c) 2026 Cursor | [MIT](LICENSE-cursor-team-kit) | +| `thermos`, `thermo-nuclear-review`, `thermo-nuclear-code-quality-review`, and the `thermo-nuclear-review-subagent` and `thermo-nuclear-code-quality-review-subagent` definitions | [cursor/plugins/thermos](https://github.com/cursor/plugins/tree/e5136d82418d2db3165ea1050d17577cd618cc05/thermos) | (c) 2026 Cursor | [MIT](LICENSE-thermos) | | The session-start hook scripts, `read-sheet.sh`, and `reflect/scripts/find-transcript.mjs`, which t3-pstack modified, and four `poteto-mode` rules, the worktree and head-guard rules in the Feature, Opening a PR, and Shipping playbooks, and three `watch-pr` fixes, which t3-pstack reworded or adapted for T3 | [michael-denyer/pstack-claude](https://github.com/michael-denyer/pstack-claude) | (c) 2026 Michael Denyer | [MIT](LICENSE) | | `poteto-mode/scripts/resolve-codex-transcript` and `resolve-codex-transcript.ts`, which t3-pstack modified | [ericlitman/open-pstack](https://github.com/ericlitman/open-pstack/tree/c5c8e237c324359a3d1929037da78fe66da3d1ed/plugins/pstack/skills/poteto-mode/scripts), [PR #151](https://github.com/ericlitman/open-pstack/pull/151) | (c) 2026 Eric A. Litman and Donncha O'Toole | [MIT](LICENSE) | diff --git a/plugins/pstack/skills/principle-attack-the-premise/SKILL.md b/plugins/pstack/skills/principle-attack-the-premise/SKILL.md index f9785ff9..e9a6d499 100644 --- a/plugins/pstack/skills/principle-attack-the-premise/SKILL.md +++ b/plugins/pstack/skills/principle-attack-the-premise/SKILL.md @@ -1,6 +1,6 @@ --- name: principle-attack-the-premise -description: "Apply when two or more fixes that share one premise have failed the same gate. Take a census of which actors hold the imbalance before the next fix, then question the premise instead of writing another fix that assumes it." +description: "Apply when two or more fixes that share one premise have failed the same gate. Write the premise down and test it directly before you write another fix that assumes it." disable-model-invocation: true --- @@ -8,16 +8,14 @@ disable-model-invocation: true When two or more fixes that share one premise have failed the same gate, suspect the premise, not the fixes. -**Why:** Each failure under a shared premise is evidence about the premise. +**Why:** Each failed fix is evidence against the belief it assumed. A third fix on the same premise spends effort where the evidence already says the cause is not. **Pattern:** - **Write the premise down.** The premise is the one sentence that every failed fix assumed. -- **Take a census before the next fix.** Count the imbalance per actor. The census shows which actors hold the imbalance, not how large it is. Write the census as a rerunnable script per [Build the Lever](../principle-build-the-lever/SKILL.md). -- **Read the skew.** If the same few actors hold most of the imbalance on every run, something assigns them that role. Find what assigns the role. That assignment is the next "why" per [Fix Root Causes](../principle-fix-root-causes/SKILL.md). -- **Remove the asymmetry instead of compensating for it**, per the [Laziness Protocol](../principle-laziness-protocol/SKILL.md). Rotate the role between actors, randomize the assignment, or move the role, so that no actor holds it on every run. A return path, a shared pool, a batched hand-off, or a periodic rebalance leaves the assignment in place and adds work on every run. +- **Test the premise before the next fix.** Find an observation that would come out differently if the premise were false, and make it. Look at how the failures are distributed, not only at how large they are. Make the check rerunnable per [Build the Lever](../principle-build-the-lever/SKILL.md). +- **Follow the evidence.** If it contradicts the premise, the cause is elsewhere. Look for what the failures have in common that the premise did not predict. If it confirms the premise, ask the next "why" per [Fix Root Causes](../principle-fix-root-causes/SKILL.md). The earlier fixes may have treated a consequence instead of the cause. +- **Remove the condition instead of compensating for it**, per the [Laziness Protocol](../principle-laziness-protocol/SKILL.md). If the evidence shows that one part always lands on the losing side, change what puts it there. A mechanism that cleans up after it leaves the cause in place and adds work on every run. -**Stop:** -- Do not start the next fix before the premise is written down and the census exists. -- If the census is even across actors, the premise is not the cause. Look for the cause elsewhere and keep the census as evidence. +**Stop:** Do not start the next fix before the premise is written down and tested. This principle is distinct from [Redesign from First Principles](../principle-redesign-from-first-principles/SKILL.md), which rebuilds a design around a new requirement. It questions a fact the current design assumes. diff --git a/plugins/pstack/skills/principle-fix-root-causes/SKILL.md b/plugins/pstack/skills/principle-fix-root-causes/SKILL.md index 5291682d..14fc189f 100644 --- a/plugins/pstack/skills/principle-fix-root-causes/SKILL.md +++ b/plugins/pstack/skills/principle-fix-root-causes/SKILL.md @@ -1,24 +1,21 @@ --- name: principle-fix-root-causes -description: "Apply when debugging. Trace each symptom to its root cause and fix it there; reproduce first, ask why until you reach it, resist nil-check guards that silence crashes." +description: "Apply when debugging. Trace each symptom back to the first place the system went wrong and fix it there. A guard is a fix only when the state it handles is legitimate." disable-model-invocation: true --- # Fix Root Causes -When debugging, do not fix symptoms. Trace every problem to its root cause and fix it there. +When debugging, fix the fault, not the place where it surfaced. The symptom is where a wrong state became visible. The root cause is the first place the system did something it should not do, or failed to handle a state it should handle. -**Why:** Symptom fixes accumulate. Each workaround makes the system harder to reason about, and the real bug remains. Root-cause fixes are slower upfront but reduce total debugging time. +**Why:** A symptom fix hides the evidence and leaves the fault free to surface somewhere else. Each one makes the system harder to reason about, because the code now carries a workaround for a bug that nobody named. **Pattern:** -- Reproduce first -- Ask "why" until you hit the root cause -- Do not add guards (adding a nil check to silence a crash is a symptom fix) -- If a workaround needs a paragraph-long comment to justify it, the code is wrong (fix the code, not the comment) -- Check for the pattern, not just the instance (grep for the same pattern, fix all instances) -- When stuck, instrument. Don't guess (add logging, read the actual error) -- If the deciding fact took a deep dig to find, propose the cheap, always-on signal that would have shown it at first look - -**Restart bugs: suspect state before code** - -When something "fails after restart," suspect stale persistent state first: config files, caches, lock files, serialized state. If clearing a state file restores behavior, prioritize state validation as the fix. +- Reproduce first. +- Ask "why" at each step until the answer is a wrong decision in the code, not a consequence of an earlier one. +- When stuck, instrument. Read the actual error and the actual state. Do not guess. +- Ask whether the state that triggered the symptom is legitimate. If the system may be in that state, the code that broke on it is the root cause, and handling the state there is the fix. If the state should never exist, a check where it broke hides the bug. Find what produced the state. Guards, retries, swallowed errors, clamped values, and discarded state are the usual ways to hide a bug. +- When something fails only after a restart, suspect persisted state first: config files, caches, lock files, serialized state. +- Check for the pattern, not just the instance. Find every place with the same fault and fix them all. +- If a workaround needs a paragraph-long comment to justify it, the code is wrong. Fix the code, not the comment. +- If the deciding fact took a deep dig to find, propose the cheap, always-on signal that would have shown it at first look. diff --git a/plugins/pstack/skills/principle-make-operations-idempotent/SKILL.md b/plugins/pstack/skills/principle-make-operations-idempotent/SKILL.md index a0834247..c93f323d 100644 --- a/plugins/pstack/skills/principle-make-operations-idempotent/SKILL.md +++ b/plugins/pstack/skills/principle-make-operations-idempotent/SKILL.md @@ -6,15 +6,13 @@ disable-model-invocation: true # Make Operations Idempotent -Design operations so they converge to the correct state regardless of how many times they run or where they start from. Every state-mutating operation should answer: "What happens if this runs twice? What happens if the previous run crashed halfway?" +Design operations so they converge to the correct state regardless of how many times they run or where the previous run stopped. Every state-mutating operation should answer: "What happens if this runs twice? What happens if the previous run crashed halfway?" **Why:** Commands, lifecycle operations, and processing loops run where crashes, restarts, and retries are normal. If partial state changes the next run's outcome, every restart becomes a debugging session. -**The pattern:** -- Convergent startup: scan for existing state, clean stale artifacts, adopt live sessions -- Content-based cleanup: compare by content equivalence, not creation order -- Self-healing locks: use PID-based stale lock detection -- Idempotent scheduling: failed work respawns cleanly, fresh input regenerated after each cycle +**The idea:** derive each step from the state that exists, not from what the previous run meant to do. Read the current state, compare it to the goal, and apply only the difference. A step written this way is safe to repeat, because a repeat finds nothing left to do. + +Anything a run leaves behind, such as a lock, a temporary file, a half-written record, or a claimed job, must be recognizable as stale by the next run. Judge staleness by evidence that stays true wherever the previous run could have stopped, not only in the common case. A marker that the next run cannot judge turns every crash into manual cleanup. For example, write to a temporary path and rename it into place, or compare artifacts by content instead of by creation order. **The test:** 1. What happens if this runs twice in a row? diff --git a/plugins/pstack/skills/principle-test-behavior-not-implementation/SKILL.md b/plugins/pstack/skills/principle-test-behavior-not-implementation/SKILL.md index f5a603e3..78c9389b 100644 --- a/plugins/pstack/skills/principle-test-behavior-not-implementation/SKILL.md +++ b/plugins/pstack/skills/principle-test-behavior-not-implementation/SKILL.md @@ -1,21 +1,20 @@ --- name: principle-test-behavior-not-implementation -description: "Apply when you write, change, or keep a test. Call the code as its users do and assert the exact result they see. Rewrite or delete a test that would pass if every imported function returned undefined." +description: "Apply when you write, change, or keep a test. Assert what the code's users can observe, so that the test fails when that behavior breaks and keeps passing when only the internals change." disable-model-invocation: true --- # Test Behavior, Not Implementation -A test calls the code as its users do and asserts the exact result they see. Rewrite or delete any test that would still pass if every imported function returned `undefined` or a wrong value. +A test is a claim about what the code does for its users: a caller, an end user, or another service. Behavior is what those users can observe through the interface they use. That includes return values, errors, state they can read back, and effects on systems outside the code, such as a request sent, a row written, or a message emitted. Implementation is what they cannot observe: private helpers, internal call order, intermediate data, and which internal collaborator did the work. -These shapes fail that check: +Judge each test against two imagined edits: -- Loose or no assertion: `toBeDefined`, `toBeTruthy`, `not.toThrow`, `toBeGreaterThan(0)`. -- Call or absence only: `toHaveBeenCalled`, `not.toHaveBeenCalled`, `toBeUndefined`, `toEqual([])`. -- Expected value computed by the code under test: `expect(f(a)).toBe(f(a))`. -- Restated constant, config default, table row, or prompt string. -- Assertions on data the test built, with no call to the subject. +- **Break the behavior.** Make the code return a wrong value, skip an effect, or do the effect twice. If the test still passes, it proves nothing. The usual causes are an assertion looser than the contract, an expected value computed by the code under test, a restated constant or prompt string that never runs the code that reads it, and an assertion on data that the test built itself. +- **Change the internals.** Keep every observable result the same and restructure the code underneath. If the test now fails, it is pinned to the implementation. It will need a rewrite on every refactor and still catches no bug. -Fix: call the subject in the test body with one concrete input and assert the literal output or effect. For a mock, assert the payload it received. For an absence, also assert the presence on another input. For a constant, test the mechanism that reads it with one input instead of restating the value. +Keep a test that catches the first edit and survives the second. Rewrite or delete the rest. To write a test that does both, drive the code through its users' interface with a concrete input. Derive the expected value from the requirement, not from a run of the code. Assert what the contract promises, no less and no more. -Keep relation checks across table rows (a key in two tables, a parent that exists) and `*.test-d.ts` type checks. +The contract decides, not the shape of the assertion. When "an empty cart never charges" is the promise, an assertion that the payment client got no call is behavior. Pair it with a case where the charge happens, so that the test shows it can see a call. The payload that a mocked external service receives is behavior, because that service observes it. A call to an internal helper is implementation, because no user can see it. An empty list is the exact answer when no record matches, and a hollow check when the test only needs some result. An exact error message pins wording that no caller reads. The error type that callers branch on is the contract. + +A test can pin an invariant instead of a call, such as a key that must exist in two tables or a compile-time type check. The invariant is the behavior. diff --git a/tools/upstream.json b/tools/upstream.json index bdd646b2..70d2cc69 100644 --- a/tools/upstream.json +++ b/tools/upstream.json @@ -4,7 +4,7 @@ "pstack": { "upstreamPath": "pstack", "localPath": "plugins/pstack", - "sha": "6ce45c59b9301a638c1fe1a7b8dc2a82b650898f", + "sha": "e5136d82418d2db3165ea1050d17577cd618cc05", "exclude": [ ".cursor-plugin/", ".gitignore", @@ -20,7 +20,7 @@ "cursor-team-kit": { "upstreamPath": "cursor-team-kit/skills", "localPath": "plugins/pstack/skills", - "sha": "6ce45c59b9301a638c1fe1a7b8dc2a82b650898f", + "sha": "e5136d82418d2db3165ea1050d17577cd618cc05", "exclude": [ "check-compiler-errors/", "control-cli/", @@ -39,7 +39,7 @@ "thermos": { "upstreamPath": "thermos", "localPath": "plugins/pstack", - "sha": "6ce45c59b9301a638c1fe1a7b8dc2a82b650898f", + "sha": "e5136d82418d2db3165ea1050d17577cd618cc05", "exclude": [ ".cursor-plugin/", "CHANGELOG.md",