@leing2021/super-pi 0.25.2 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/extensions/ce-core/index.ts +23 -8
- package/extensions/ce-core/tools/compaction-optimizer.ts +16 -4
- package/package.json +5 -5
- package/skills/01-brainstorm/SKILL.md +3 -3
- package/skills/01-brainstorm/references/premise-challenge.md +5 -0
- package/skills/02-plan/SKILL.md +7 -6
- package/skills/03-work/SKILL.md +2 -1
- package/skills/03-work/references/debug-discipline.md +97 -27
- package/skills/04-review/SKILL.md +5 -3
- package/skills/04-review/references/reviewer-selection.md +1 -0
- package/skills/05-learn/SKILL.md +1 -0
- package/skills/05-learn/assets/out-of-scope-template.md +20 -0
- package/skills/references/domain-language.md +55 -0
- package/skills/references/module-design.md +63 -0
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ Install, describe what you want to build, then keep saying "continue." Super Pi
|
|
|
18
18
|
pi install npm:@leing2021/super-pi
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
> **Project trust (pi ≥ 0.79):** Pi asks before loading project-local settings, resources, and packages. On first use, approve the project trust prompt so Super Pi can read `.pi/settings.json` and load its skills/extensions. Use `pi --approve` for non-interactive runs.
|
|
22
22
|
|
|
23
23
|
## Highlights
|
|
24
24
|
|
|
@@ -73,7 +73,7 @@ You: /skill:03-work docs/plans/plan.md
|
|
|
73
73
|
| **01-brainstorm** | Structured multi-round discovery, domain vocabulary persistence | `brainstorm_dialog` |
|
|
74
74
|
| **02-plan** | TDD-gated implementation units, optional CEO Review | `plan_diff` |
|
|
75
75
|
| **03-work** | Inline execution, checkpoint resume, strict TDD, stop-the-line | `session_checkpoint`, `task_splitter` |
|
|
76
|
-
| **04-review** | Auto-assigned reviewers,
|
|
76
|
+
| **04-review** | Auto-assigned reviewers, six-axis findings (Standards + Spec), autofix loop | `review_router` |
|
|
77
77
|
| **05-learn** | Pattern extraction → searchable solution artifacts | `pattern_extractor` |
|
|
78
78
|
| **06-next** | Next-step recommendation + workflow status | `workflow_state` |
|
|
79
79
|
| **07-worktree** | Isolated git worktree development | `worktree_manager` |
|
|
@@ -114,7 +114,7 @@ Super Pi is not a fork or wrapper. It extracts useful methods from the projects
|
|
|
114
114
|
| [superpowers](https://github.com/obra/superpowers) | Strict TDD gates, design checklists, review discipline, and the idea that agents need hard gates instead of gentle suggestions. |
|
|
115
115
|
| [compound-engineering-plugin](https://github.com/EveryInc/compound-engineering-plugin) | The five-step think → plan → build → review → learn loop and the knowledge-compounding backbone. |
|
|
116
116
|
| [gstack](https://github.com/garrytan/gstack) | YC-style forcing questions, CEO Review cognitive frameworks, browser QA patterns, failure maps, and evidence-first validation. |
|
|
117
|
-
| [mattpocock/skills](https://github.com/mattpocock/skills) | Context glossary (`CONTEXT.md`) for cross-session term persistence, lightweight ADR with three-condition threshold,
|
|
117
|
+
| [mattpocock/skills](https://github.com/mattpocock/skills) | Context glossary (`CONTEXT.md`) for cross-session term persistence, lightweight ADR with three-condition threshold, feedback-loop-first debug discipline (full diagnosis loop with completion criteria and post-mortem handoff), deep-module vocabulary, the review Spec axis (plan-vs-diff with traceback to original wording), and the out-of-scope knowledge base. Adopted as self-contained `skills/references/` — no external path deps, no issue-tracker deps. |
|
|
118
118
|
|
|
119
119
|
---
|
|
120
120
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises"
|
|
2
2
|
import path from "node:path"
|
|
3
3
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"
|
|
4
|
+
import { CONFIG_DIR_NAME } from "@earendil-works/pi-coding-agent"
|
|
4
5
|
import { Type } from "typebox"
|
|
5
6
|
import { createArtifactHelperTool, type ArtifactType } from "./tools/artifact-helper"
|
|
6
7
|
import { createAskUserQuestionTool, CUSTOM_SENTINEL } from "./tools/ask-user-question"
|
|
@@ -97,15 +98,17 @@ interface StrategySettings {
|
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
/**
|
|
100
|
-
* Read settings from two locations
|
|
101
|
-
*
|
|
102
|
-
*
|
|
101
|
+
* Read settings from two locations (config dir honors pi's `CONFIG_DIR_NAME`,
|
|
102
|
+
* which defaults to `.pi` but is user-configurable since pi 0.79.7):
|
|
103
|
+
* 1. Project-level: {cwd}/{CONFIG_DIR_NAME}/settings.json (highest priority)
|
|
104
|
+
* 2. Global-level: ~/{CONFIG_DIR_NAME}/agent/settings.json (fallback)
|
|
103
105
|
*
|
|
104
106
|
* Project-level takes precedence; global-level is used as fallback.
|
|
105
107
|
*/
|
|
106
108
|
async function readSettings(cwd: string): Promise<StrategySettings | null> {
|
|
109
|
+
const agentHome = process.env.HOME || "~"
|
|
107
110
|
// Try project-level first
|
|
108
|
-
const projectPath = path.join(cwd,
|
|
111
|
+
const projectPath = path.join(cwd, CONFIG_DIR_NAME, "settings.json")
|
|
109
112
|
try {
|
|
110
113
|
const content = await readFile(projectPath, "utf8")
|
|
111
114
|
const projectSettings = JSON.parse(content) as StrategySettings
|
|
@@ -118,7 +121,7 @@ async function readSettings(cwd: string): Promise<StrategySettings | null> {
|
|
|
118
121
|
}
|
|
119
122
|
|
|
120
123
|
// Fallback to global-level
|
|
121
|
-
const globalPath = path.join(
|
|
124
|
+
const globalPath = path.join(agentHome, CONFIG_DIR_NAME, "agent", "settings.json")
|
|
122
125
|
try {
|
|
123
126
|
const content = await readFile(globalPath, "utf8")
|
|
124
127
|
return JSON.parse(content) as StrategySettings
|
|
@@ -126,8 +129,8 @@ async function readSettings(cwd: string): Promise<StrategySettings | null> {
|
|
|
126
129
|
// Global settings not found either
|
|
127
130
|
}
|
|
128
131
|
|
|
129
|
-
// Try
|
|
130
|
-
const altGlobalPath = path.join(
|
|
132
|
+
// Try ~/{CONFIG_DIR_NAME}/settings.json as another fallback
|
|
133
|
+
const altGlobalPath = path.join(agentHome, CONFIG_DIR_NAME, "settings.json")
|
|
131
134
|
try {
|
|
132
135
|
const content = await readFile(altGlobalPath, "utf8")
|
|
133
136
|
return JSON.parse(content) as StrategySettings
|
|
@@ -805,7 +808,19 @@ export default function ceCoreExtension(pi: ExtensionAPI) {
|
|
|
805
808
|
}
|
|
806
809
|
})
|
|
807
810
|
|
|
808
|
-
//
|
|
811
|
+
// Branch summary prompt optimizer — appends focus instructions to `/tree`
|
|
812
|
+
// navigation summaries. `SessionBeforeTreeResult.customInstructions` is
|
|
813
|
+
// consumed by pi (agent-session.js navigateTree), so this return shape is
|
|
814
|
+
// effective for branch summaries.
|
|
815
|
+
//
|
|
816
|
+
// NOTE on regular context compaction (manual `/compact`, threshold,
|
|
817
|
+
// overflow): pi's `session_before_compact` result only accepts `cancel` or
|
|
818
|
+
// a full `compaction` replacement — there is NO prompt-only injection
|
|
819
|
+
// field (`customInstructions` is an event *input*, not a return value).
|
|
820
|
+
// So we cannot append focus instructions to regular compaction summaries
|
|
821
|
+
// without replacing pi's entire summarizer. We deliberately do not hook
|
|
822
|
+
// `session_before_compact` to avoid dead handlers and needless emit()
|
|
823
|
+
// overhead on every compaction.
|
|
809
824
|
pi.on("session_before_tree", async (_event, _ctx) => {
|
|
810
825
|
return {
|
|
811
826
|
customInstructions: COMPACTION_FOCUS_INSTRUCTIONS,
|
|
@@ -2,11 +2,23 @@
|
|
|
2
2
|
// Compaction Prompt Optimizer
|
|
3
3
|
// ============================================================================
|
|
4
4
|
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
5
|
+
// Focus instructions injected into pi's branch-summary prompts so summaries
|
|
6
|
+
// stay useful for coding-agent continuation.
|
|
7
7
|
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
8
|
+
// Consumed by the `session_before_tree` hook in `index.ts`, which returns
|
|
9
|
+
// `{ customInstructions, replaceInstructions }`. This return shape IS
|
|
10
|
+
// supported by pi (consumed in `agent-session.js` navigateTree →
|
|
11
|
+
// SessionBeforeTreeResult) and appends focus instructions to summaries
|
|
12
|
+
// generated on `/tree` navigation.
|
|
13
|
+
//
|
|
14
|
+
// Regular context compaction (manual `/compact`, threshold, overflow) is
|
|
15
|
+
// NOT covered: pi's `SessionBeforeCompactResult` only accepts `cancel` or a
|
|
16
|
+
// full `compaction` replacement — there is no prompt-only injection field
|
|
17
|
+
// (`customInstructions` is an event *input*, not a return value). Appending
|
|
18
|
+
// focus instructions there would require replacing pi's entire summarizer,
|
|
19
|
+
// so we deliberately do not hook it.
|
|
20
|
+
//
|
|
21
|
+
// This is a "prompt-only" optimization; it does not replace pi's flows.
|
|
10
22
|
|
|
11
23
|
/**
|
|
12
24
|
* Custom instructions appended to compaction summarization prompts.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leing2021/super-pi",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Pi-native Compound Engineering package for iterative development workflows",
|
|
@@ -35,13 +35,13 @@
|
|
|
35
35
|
"test": "bun test"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
|
-
"@earendil-works/pi-coding-agent": ">=0.
|
|
39
|
-
"@earendil-works/pi-tui": ">=0.
|
|
38
|
+
"@earendil-works/pi-coding-agent": ">=0.79.10",
|
|
39
|
+
"@earendil-works/pi-tui": ">=0.79.10",
|
|
40
40
|
"typebox": ">=1.0.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@earendil-works/pi-coding-agent": "^0.
|
|
44
|
-
"@earendil-works/pi-tui": "^0.
|
|
43
|
+
"@earendil-works/pi-coding-agent": "^0.80.0",
|
|
44
|
+
"@earendil-works/pi-tui": "^0.80.0",
|
|
45
45
|
"bun-types": "^1.3.12"
|
|
46
46
|
},
|
|
47
47
|
"pi": {
|
|
@@ -63,14 +63,14 @@ Before summarizing, ensure the design answers:
|
|
|
63
63
|
|
|
64
64
|
After mode-specific questions, check if the project has a `CONTEXT.md` at root.
|
|
65
65
|
If not, and the brainstorm reveals 3+ domain-specific terms with ambiguous meanings,
|
|
66
|
-
offer to create one using `references/context-glossary.md
|
|
67
|
-
the session — don't batch. If it exists, cross-reference and flag conflicts:
|
|
66
|
+
offer to create one using `references/context-glossary.md` (contract: `../references/domain-language.md`).
|
|
67
|
+
Update it inline during the session — don't batch. If it exists, cross-reference and flag conflicts:
|
|
68
68
|
|
|
69
69
|
> "Your CONTEXT.md defines 'cancellation' as X, but you seem to mean Y — which is it?"
|
|
70
70
|
|
|
71
71
|
## Stop conditions
|
|
72
72
|
|
|
73
|
-
Stop and ask instead of guessing when: requirements conflict, success criteria unclear, task spans multiple systems, or user hasn't approved design.
|
|
73
|
+
Stop and ask instead of guessing when: requirements conflict, success criteria unclear, task spans multiple systems, or user hasn't approved design. Before fleshing out an idea, grep `docs/out-of-scope/` for prior rejections — surface matches before proceeding.
|
|
74
74
|
|
|
75
75
|
## Approval gate
|
|
76
76
|
|
|
@@ -8,6 +8,11 @@ Before proposing solutions, challenge the premises. Run this after the diagnosti
|
|
|
8
8
|
2. **What happens if we do nothing?** Real pain point or hypothetical one?
|
|
9
9
|
3. **What existing code already partially solves this?** Map existing patterns, utilities, and flows that could be reused.
|
|
10
10
|
4. **If the deliverable is a new artifact** (CLI binary, library, package, container image, mobile app): **how will users get it?** Code without distribution is code nobody can use.
|
|
11
|
+
5. **External resource signal — verify intent before scope.** When the user mentions an existing resource ("I already have X", "I wrote a skill for Y", "we use Z elsewhere"), do not assume it means "include X in this project." It may mean the opposite: the problem is already solved and should be excluded. Reverse-verify with one question: "You mentioned X — do you want it incorporated here, or is it noting that X already handles this so we don't need to?" A wrong assumption here propagates through every downstream stage (plan, work, review) and surfaces only at merge — three gates that all trust the upstream.
|
|
12
|
+
|
|
13
|
+
## Failure mode
|
|
14
|
+
|
|
15
|
+
Skipping this check when the user references an external resource leads to scope creep in the opposite direction assumed: incorporating something the user considered already-handled. The later it surfaces, the costlier the rollback.
|
|
11
16
|
|
|
12
17
|
## Output format
|
|
13
18
|
|
package/skills/02-plan/SKILL.md
CHANGED
|
@@ -39,14 +39,15 @@ Every unit follows **RED → GREEN → REFACTOR**:
|
|
|
39
39
|
|
|
40
40
|
## Planning flow
|
|
41
41
|
|
|
42
|
-
1. **Load context**: consume latest handoff before any broad file reads — `context_handoff load` or read `.context/compound-engineering/handoffs/latest.md`. If found, use `activeFiles` and `blocker` as starting point. If not found, proceed normally (new project).
|
|
42
|
+
1. **Load context**: consume latest handoff before any broad file reads — `context_handoff load` or read `.context/compound-engineering/handoffs/latest.md`. If found, use `activeFiles` and `blocker` as starting point. If not found, proceed normally (new project). Read `CONTEXT.md` if it exists at root — see `../references/domain-language.md`.
|
|
43
43
|
2. Read relevant brainstorm from `docs/brainstorms/`
|
|
44
44
|
3. Run solution search (keywords → grep frontmatter → read top 3)
|
|
45
|
-
4.
|
|
46
|
-
5.
|
|
47
|
-
6.
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
4. Grep `docs/out-of-scope/` for prior rejections of features in this plan
|
|
46
|
+
5. Gather repository context
|
|
47
|
+
6. **Source-driven check:** For each unit that involves framework/library APIs, add a note: "Verify against official docs before implementing."
|
|
48
|
+
7. If plan exists: use `plan_diff` `compare` → review with user → `patch`
|
|
49
|
+
8. If no plan: write new plan under `docs/plans/` using `references/plan-template.md`
|
|
50
|
+
9. Structure work using `references/implementation-unit-template.md`
|
|
50
51
|
8. Verify every unit follows TDD gates
|
|
51
52
|
|
|
52
53
|
## Optional: CEO Review
|
package/skills/03-work/SKILL.md
CHANGED
|
@@ -24,6 +24,7 @@ See [shared pipeline instructions](../references/pipeline-config.md) for model r
|
|
|
24
24
|
7. Use **`task_splitter`** to analyze dependencies before execution
|
|
25
25
|
8. If in **worktree** (via `07-worktree`), execute inside it
|
|
26
26
|
9. End by recommending `04-review`
|
|
27
|
+
10. When designing/restructuring modules, use the deep-module vocabulary (`../references/module-design.md`) — evaluate depth and seam placement.
|
|
27
28
|
|
|
28
29
|
> **Advanced:** If you need external child agent delegation (background runs, parallel audits), install `pi-subagents` separately. Super Pi does not require it.
|
|
29
30
|
|
|
@@ -69,7 +70,7 @@ If the same tool, command, or implementation unit fails 3 consecutive times, sto
|
|
|
69
70
|
|
|
70
71
|
## Workflow
|
|
71
72
|
|
|
72
|
-
1. **Load context**: consume latest handoff before any broad file reads — `context_handoff load` or read `.context/compound-engineering/handoffs/latest.md`. If found, use `activeFiles`, `blocker`, `verification`, `activeRules` as starting point. If not found, proceed normally.
|
|
73
|
+
1. **Load context**: consume latest handoff before any broad file reads — `context_handoff load` or read `.context/compound-engineering/handoffs/latest.md`. If found, use `activeFiles`, `blocker`, `verification`, `activeRules` as starting point. If not found, proceed normally. Read `CONTEXT.md` if it exists at root — see `../references/domain-language.md`.
|
|
73
74
|
2. Detect input type (plan path vs bare prompt)
|
|
74
75
|
3. Read implementation units if plan path
|
|
75
76
|
4. Load `session_checkpoint` to skip completed units
|
|
@@ -2,52 +2,122 @@
|
|
|
2
2
|
|
|
3
3
|
When stop-the-line triggers, follow this order. Skip phases only when explicitly justified.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**Root principle:** a **tight loop** is the skill. A pass/fail signal that is fast, deterministic, and goes red on *this* bug. Everything else is mechanical — bisection, hypothesis-testing, instrumentation all just consume it. No tight loop, no amount of staring at code will save you.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## Phase 1 — Build a tight loop
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
If you don't, no amount of staring at code will save you. Spend disproportionate effort here.
|
|
9
|
+
**This is the skill. Everything else is mechanical.** Spend disproportionate effort here. Be aggressive, be creative, refuse to give up.
|
|
11
10
|
|
|
12
|
-
###
|
|
11
|
+
### Ways to construct one — try in roughly this order
|
|
13
12
|
|
|
14
|
-
1. **Failing test** at
|
|
15
|
-
2. **CLI invocation** with fixture input,
|
|
16
|
-
3. **Curl/HTTP script** against running dev server
|
|
17
|
-
4. **
|
|
18
|
-
5. **
|
|
13
|
+
1. **Failing test** at whatever seam reaches the bug — unit, integration, e2e.
|
|
14
|
+
2. **CLI invocation** with a fixture input, diffing stdout against a known-good snapshot.
|
|
15
|
+
3. **Curl / HTTP script** against a running dev server.
|
|
16
|
+
4. **Headless browser script** (Playwright / Puppeteer) — drives the UI, asserts on DOM/console/network.
|
|
17
|
+
5. **Throwaway harness** — spin up a minimal subset (one service, mocked deps) that exercises the bug code path with a single function call.
|
|
18
|
+
6. **Replay a captured trace** — save a real network request / payload / event log to disk; replay it through the code path in isolation.
|
|
19
|
+
7. **Property / fuzz loop** — if the bug is "sometimes wrong output", run 1000 random inputs and look for the failure mode.
|
|
20
|
+
8. **Bisection harness** — automate "boot at state X, check, repeat" so `git bisect run` can drive it between known-good and known-bad states.
|
|
21
|
+
9. **Differential loop** — run the same input through old-version vs new-version (or two configs) and diff outputs.
|
|
22
|
+
10. **HITL bash script** (last resort) — if a human must click, drive them with a structured script so the loop is still disciplined. Captured output feeds back to you.
|
|
19
23
|
|
|
20
|
-
###
|
|
24
|
+
### Tighten the loop
|
|
21
25
|
|
|
22
|
-
|
|
23
|
-
- Sharper signal? (Assert the specific symptom, not "didn't crash")
|
|
24
|
-
- More deterministic? (Pin time, seed RNG, isolate filesystem)
|
|
26
|
+
Treat the loop as a product. Once you have *a* loop, tighten it on three axes:
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
- **Faster** — cache setup, skip unrelated init, narrow the test scope.
|
|
29
|
+
- **Sharper signal** — assert the specific symptom, not "didn't crash".
|
|
30
|
+
- **More deterministic** — pin time, seed RNG, isolate filesystem, freeze network.
|
|
28
31
|
|
|
29
|
-
|
|
32
|
+
A 30-second flaky loop is barely better than no loop; a 2-second deterministic one is a debugging superpower.
|
|
30
33
|
|
|
31
|
-
|
|
34
|
+
### Non-deterministic bugs
|
|
35
|
+
|
|
36
|
+
The goal is not a clean repro but a **higher reproduction rate**. Loop the trigger 100×, parallelise, add stress, narrow timing windows, inject sleeps. A 50%-flake bug is debuggable; 1% is not — keep raising the rate until it's debuggable.
|
|
37
|
+
|
|
38
|
+
### When you genuinely cannot build a loop
|
|
39
|
+
|
|
40
|
+
Stop and say so explicitly. List what you tried. Ask the user for: (a) access to whatever environment reproduces it, (b) a captured artifact (HAR file, log dump, core dump, screen recording with timestamps), or (c) permission to add temporary production instrumentation. Do **not** proceed to hypothesise without a loop.
|
|
41
|
+
|
|
42
|
+
### Completion criterion — a tight loop that goes red
|
|
43
|
+
|
|
44
|
+
Phase 1 is done when you can name **one command** — a script path, a test invocation, a curl — that you have **already run at least once** (paste the invocation and its output), and that is:
|
|
45
|
+
|
|
46
|
+
- [ ] **Red-capable** — drives the actual bug code path and asserts the **user's exact symptom**, so it can go red on this bug and green once fixed. Not "runs without erroring" — it must be able to *catch this specific bug*.
|
|
47
|
+
- [ ] **Deterministic** — same verdict every run (flaky bugs: a pinned, high reproduction rate).
|
|
48
|
+
- [ ] **Fast** — seconds, not minutes.
|
|
49
|
+
- [ ] **Agent-runnable** — you can run it unattended.
|
|
50
|
+
|
|
51
|
+
If you catch yourself reading code to build a theory before this command exists, **stop — jumping straight to a hypothesis is the exact failure this skill prevents.** No red-capable command, no Phase 2.
|
|
52
|
+
|
|
53
|
+
## Phase 2 — Reproduce + minimise
|
|
54
|
+
|
|
55
|
+
Run the loop. Watch it go red — the bug appears.
|
|
56
|
+
|
|
57
|
+
Confirm:
|
|
58
|
+
|
|
59
|
+
- [ ] The loop produces the failure mode the **user** described — not a different failure that happens to be nearby. Wrong bug = wrong fix.
|
|
60
|
+
- [ ] The failure is reproducible across multiple runs (or, for non-deterministic bugs, at a high enough rate to debug against).
|
|
61
|
+
- [ ] You have captured the exact symptom (error message, wrong output, slow timing) so later phases can verify the fix actually addresses it.
|
|
62
|
+
|
|
63
|
+
### Minimise
|
|
64
|
+
|
|
65
|
+
Once it's red, shrink the repro to the **smallest scenario that still goes red**. Cut inputs, callers, config, data, and steps **one at a time**, re-running the loop after each cut — keep only what is load-bearing for the failure.
|
|
66
|
+
|
|
67
|
+
Why bother: a minimal repro shrinks the hypothesis space in Phase 3 (fewer moving parts left to suspect) and becomes the clean regression test in Phase 5.
|
|
68
|
+
|
|
69
|
+
Done when **every remaining element is load-bearing** — removing any one of them makes the loop go green.
|
|
32
70
|
|
|
33
71
|
## Phase 3 — Hypothesise
|
|
34
72
|
|
|
35
|
-
Generate 3
|
|
73
|
+
Generate **3–5 ranked hypotheses** before testing any of them. Single-hypothesis generation anchors on the first plausible idea.
|
|
74
|
+
|
|
75
|
+
Each hypothesis must be **falsifiable**: state the prediction it makes.
|
|
36
76
|
|
|
37
|
-
> "If <X> is the cause, then <Y> will make the bug disappear."
|
|
77
|
+
> Format: "If <X> is the cause, then <changing Y> will make the bug disappear / <changing Z> will make it worse."
|
|
38
78
|
|
|
39
|
-
|
|
40
|
-
|
|
79
|
+
If you cannot state the prediction, the hypothesis is a vibe — discard or sharpen it.
|
|
80
|
+
|
|
81
|
+
**Show the ranked list to the user before testing.** They often have domain knowledge that re-ranks instantly ("we just deployed a change to #3"), or know hypotheses they've already ruled out. Cheap checkpoint, big time saver. Don't block on it — proceed with your ranking if the user is AFK.
|
|
41
82
|
|
|
42
83
|
## Phase 4 — Instrument
|
|
43
84
|
|
|
44
|
-
|
|
85
|
+
Each probe must map to a specific prediction from Phase 3. **Change one variable at a time.**
|
|
86
|
+
|
|
87
|
+
Tool preference:
|
|
45
88
|
|
|
46
|
-
|
|
89
|
+
1. **Debugger / REPL inspection** if the env supports it. One breakpoint beats ten logs.
|
|
90
|
+
2. **Targeted logs** at the boundaries that distinguish hypotheses.
|
|
91
|
+
3. Never "log everything and grep".
|
|
92
|
+
|
|
93
|
+
**Tag every debug log** with a unique prefix, e.g. `[DEBUG-a4f2]`. Cleanup at the end becomes a single grep. Untagged logs survive; tagged logs die.
|
|
94
|
+
|
|
95
|
+
**Perf branch.** For performance regressions, logs are usually wrong. Instead: establish a baseline measurement (timing harness, `performance.now()`, profiler, query plan), then bisect. Measure first, fix second.
|
|
47
96
|
|
|
48
97
|
## Phase 5 — Fix + regression test
|
|
49
98
|
|
|
50
|
-
Write regression test
|
|
51
|
-
|
|
99
|
+
Write the regression test **before the fix** — but only if there is a **correct seam** for it.
|
|
100
|
+
|
|
101
|
+
A correct seam is one where the test exercises the **real bug pattern** as it occurs at the call site. If the only available seam is too shallow (single-caller test when the bug needs multiple callers, unit test that can't replicate the chain that triggered the bug), a regression test there gives false confidence.
|
|
102
|
+
|
|
103
|
+
**If no correct seam exists, that itself is the finding.** Note it. The codebase architecture is preventing the bug from being locked down. Flag this for Phase 6.
|
|
104
|
+
|
|
105
|
+
If a correct seam exists:
|
|
106
|
+
|
|
107
|
+
1. Turn the minimised repro into a failing test at that seam.
|
|
108
|
+
2. Watch it fail.
|
|
109
|
+
3. Apply the fix.
|
|
110
|
+
4. Watch it pass.
|
|
111
|
+
5. Re-run the Phase 1 tight loop against the original (un-minimised) scenario.
|
|
112
|
+
|
|
113
|
+
## Phase 6 — Cleanup + post-mortem
|
|
114
|
+
|
|
115
|
+
Required before declaring done:
|
|
116
|
+
|
|
117
|
+
- [ ] Original repro no longer reproduces (re-run the Phase 1 loop)
|
|
118
|
+
- [ ] Regression test passes (or absence of correct seam is documented)
|
|
119
|
+
- [ ] All `[DEBUG-...]` instrumentation removed (`grep` the prefix)
|
|
120
|
+
- [ ] Throwaway prototypes deleted (or moved to a clearly-marked debug location)
|
|
121
|
+
- [ ] The hypothesis that turned out correct is stated in the commit / PR message — so the next debugger learns
|
|
52
122
|
|
|
53
|
-
|
|
123
|
+
**Then ask: what would have prevented this bug?** If the answer involves architectural change (no good test seam, tangled callers, hidden coupling), capture it as a `docs/solutions/` artifact via `05-learn`, or flag it for the next planning cycle. Make the recommendation **after** the fix is in, not before — you have more information now than when you started.
|
|
@@ -24,8 +24,9 @@ See [shared pipeline instructions](../references/pipeline-config.md) for model r
|
|
|
24
24
|
- Extract keywords → `grep -rl "tags:.*keyword" docs/solutions/ ~/.pi/agent/docs/solutions/`
|
|
25
25
|
- Read **frontmatter** only (first 15 lines) of matches → score by severity + tag relevance
|
|
26
26
|
- Fully read top 3 candidates
|
|
27
|
-
7.
|
|
28
|
-
8.
|
|
27
|
+
7. **Spec axis:** when a plan artifact exists, compare diff against it — report **missing** requirements, **scope creep** (unrequested behaviour), and **wrong implementation** (looks done but isn't). Also **trace back** to the user's original wording (brainstorm scope) to catch directional misunderstandings the plan itself encoded. Skip if no plan.
|
|
28
|
+
8. Produce structured findings using `references/findings-schema.md`
|
|
29
|
+
9. **Autofixable findings:** apply and re-review (max 3 iterations)
|
|
29
30
|
|
|
30
31
|
## Review discipline
|
|
31
32
|
|
|
@@ -35,6 +36,7 @@ Code review is **technical evaluation**, not social performance:
|
|
|
35
36
|
- **No performative agreement:** verify before concurring
|
|
36
37
|
- **Push back** with reasoning when findings are incorrect
|
|
37
38
|
- **Evidence before assertions:** cite specific code, not principles
|
|
39
|
+
- **Architecture axis:** audit module depth and seams using `../references/module-design.md`
|
|
38
40
|
|
|
39
41
|
## Handling findings
|
|
40
42
|
|
|
@@ -46,7 +48,7 @@ Code review is **technical evaluation**, not social performance:
|
|
|
46
48
|
|
|
47
49
|
## Workflow
|
|
48
50
|
|
|
49
|
-
1. **Load context**: consume latest handoff before any broad file reads — `context_handoff load` or read `.context/compound-engineering/handoffs/latest.md`. If found, use `activeFiles`, `artifacts.plan` as starting point. If not found, proceed normally.
|
|
51
|
+
1. **Load context**: consume latest handoff before any broad file reads — `context_handoff load` or read `.context/compound-engineering/handoffs/latest.md`. If found, use `activeFiles`, `artifacts.plan` as starting point. If not found, proceed normally. Read `CONTEXT.md` if it exists at root — see `../references/domain-language.md`.
|
|
50
52
|
2. Determine diff scope from branch or explicit target
|
|
51
53
|
3. Collect stats (files, insertions, deletions) → call `review_router`
|
|
52
54
|
4. Read matching plan artifact
|
|
@@ -24,3 +24,4 @@ All reviewers evaluate changes across five axes: correctness, readability, archi
|
|
|
24
24
|
- **performance-reviewer**: Triggered when query, cache, database, or streaming files change. Reviews for N+1, unnecessary allocation, missing indexes.
|
|
25
25
|
- **integration-reviewer**: Triggered when CI/CD, Docker, package.json, or config files change. Reviews for dependency conflicts, build breakage, deployment issues.
|
|
26
26
|
- **thoroughness-reviewer**: Triggered for large diffs (5+ files or 300+ lines). Reviews for incomplete refactors, missed callers, inconsistent changes.
|
|
27
|
+
- **spec-reviewer**: Triggered when a plan artifact exists. Reviews the diff against the plan — reports **missing** requirements, **scope creep** (behaviour in the diff not asked for), and **wrong implementation** (requirements that look done but aren't). Skip when no plan artifact is found. Additionally, **trace back to the user's original wording**: re-read the brainstorm artifact's scope statements and confirm the plan interpreted them correctly — a plan that faithfully implements a *misunderstood* requirement passes missing/scope-creep checks but still ships the wrong thing. Flag directional misunderstandings even if the diff matches the plan.
|
package/skills/05-learn/SKILL.md
CHANGED
|
@@ -21,6 +21,7 @@ See [shared pipeline instructions](../references/pipeline-config.md) for model r
|
|
|
21
21
|
- **Project-specific** → `{project-root}/docs/solutions/` (only relevant to current project)
|
|
22
22
|
- **Cross-project (global)** → `~/.pi/agent/docs/solutions/` (applicable to any project)
|
|
23
23
|
- Default to **global** when uncertain.
|
|
24
|
+
- **Out-of-scope branch:** if the request was rejected or already implemented, write to `docs/out-of-scope/` (template: `assets/out-of-scope-template.md`, convention: `../../docs/out-of-scope/README.md`) instead of `docs/solutions/`.
|
|
24
25
|
- Make the result useful to future `02-plan` and `04-review` runs via the search strategy in `references/solution-search-strategy.md`.
|
|
25
26
|
|
|
26
27
|
## Workflow
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: <the request in one line>
|
|
3
|
+
status: rejected | already-implemented
|
|
4
|
+
date: <YYYY-MM-DD>
|
|
5
|
+
related_adr: <ADR path if relevant, else omit>
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Out-of-Scope Entry
|
|
9
|
+
|
|
10
|
+
## Request
|
|
11
|
+
|
|
12
|
+
<what was asked for>
|
|
13
|
+
|
|
14
|
+
## Disposition
|
|
15
|
+
|
|
16
|
+
<rejected: why it was ruled out | already-implemented: where it lives in the code>
|
|
17
|
+
|
|
18
|
+
## Trigger phrases
|
|
19
|
+
|
|
20
|
+
<words a future request might use that should match this entry — enables grep-based matching by 01-brainstorm and 02-plan>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Domain Language — CONTEXT.md + ADR consumption contract
|
|
2
|
+
|
|
3
|
+
A shared vocabulary layer that runs beneath every skill. Two artifacts hold it: `CONTEXT.md` (the glossary) and `docs/adr/` (architectural decisions). This file defines what they are and how every skill consumes them.
|
|
4
|
+
|
|
5
|
+
## CONTEXT.md — the glossary
|
|
6
|
+
|
|
7
|
+
A project-level glossary of domain terms. Lives at the repo root. Persists domain language across sessions so every skill speaks the project's vocabulary, not generic substitutes.
|
|
8
|
+
|
|
9
|
+
### What it is
|
|
10
|
+
|
|
11
|
+
- **Pure glossary** — definitions of domain terms only. One definition per term, 1–2 sentences.
|
|
12
|
+
- **No implementation details** — not a spec, not a scratchpad, not a repository for decisions. Define what a term *is*, not what it *does*.
|
|
13
|
+
- **Canonical term + _Avoid_ list** — pick one name, list aliases to discourage.
|
|
14
|
+
|
|
15
|
+
### When to create
|
|
16
|
+
|
|
17
|
+
Create `CONTEXT.md` when the user uses project-specific terms that have ambiguous or overloaded meanings, and no glossary exists yet. Skip for trivial features with no domain jargon.
|
|
18
|
+
|
|
19
|
+
### Single vs multiple contexts
|
|
20
|
+
|
|
21
|
+
- **Single context (default)** — one `CONTEXT.md` at repo root. Fits almost every repo.
|
|
22
|
+
- **Multiple contexts (monorepo)** — a root `CONTEXT-MAP.md` points to per-context `CONTEXT.md` files (e.g. `src/ordering/CONTEXT.md`, `src/billing/CONTEXT.md`). Use only when the repo has genuinely separated domains.
|
|
23
|
+
|
|
24
|
+
### Format
|
|
25
|
+
|
|
26
|
+
See `skills/01-brainstorm/references/context-glossary.md` for the creation template.
|
|
27
|
+
|
|
28
|
+
## ADR — architectural decision records
|
|
29
|
+
|
|
30
|
+
Records of decisions that are hard to reverse. Live at `docs/adr/` (or per-context `docs/adr/` in a multi-context repo). Numbered: `0001-slug.md`.
|
|
31
|
+
|
|
32
|
+
### When to create an ADR
|
|
33
|
+
|
|
34
|
+
Only when **all three** are true:
|
|
35
|
+
|
|
36
|
+
1. **Hard to reverse** — the cost of changing the decision later is meaningful.
|
|
37
|
+
2. **Surprising without context** — a future reader will wonder "why did they do it this way?"
|
|
38
|
+
3. **Real trade-off** — there were genuine alternatives and you picked one for specific reasons.
|
|
39
|
+
|
|
40
|
+
If any is missing, skip the ADR. Most decisions don't qualify.
|
|
41
|
+
|
|
42
|
+
## Consumption rules (every skill)
|
|
43
|
+
|
|
44
|
+
1. **Before broad project reads**, check if `CONTEXT.md` exists at the repo root (or the relevant context in a multi-context repo). If it exists, read it first so you use the project's vocabulary.
|
|
45
|
+
2. **Respect ADRs** — before proposing a design that touches an area with existing ADRs, read them. Don't re-litigate a settled decision unless the friction is real enough to warrant reopening.
|
|
46
|
+
3. **Update inline** — when a term is resolved during a session, update `CONTEXT.md` right there. Don't batch.
|
|
47
|
+
4. **Flag conflicts** — if the user uses a term that conflicts with the glossary, surface it: "Your CONTEXT.md defines 'cancellation' as X, but you seem to mean Y — which is it?"
|
|
48
|
+
5. **Challenge fuzzy language** — if the user uses an overloaded term, propose a precise canonical term.
|
|
49
|
+
|
|
50
|
+
## Where this is used
|
|
51
|
+
|
|
52
|
+
- **01-brainstorm** — creates/updates `CONTEXT.md` as domain terms emerge.
|
|
53
|
+
- **02-plan** — reads `CONTEXT.md` for vocabulary; offers ADRs when a decision meets the three-condition threshold.
|
|
54
|
+
- **03-work** — reads `CONTEXT.md` so test names and interface vocabulary match; respects ADRs in the area being touched.
|
|
55
|
+
- **04-review** — checks whether the diff uses consistent domain vocabulary; flags ADR conflicts.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Module Design — deep-module vocabulary
|
|
2
|
+
|
|
3
|
+
A shared vocabulary for designing module shapes. Use these terms wherever code is being designed or restructured — `03-work` when building a module, `04-review` when auditing architecture. Consistent language is the whole point; don't drift into "component", "service", "API", or "boundary".
|
|
4
|
+
|
|
5
|
+
## Glossary
|
|
6
|
+
|
|
7
|
+
**Module** — anything with an interface and an implementation. Scale-agnostic: a function, class, package, or tier-spanning slice. _Avoid_: unit, component, service.
|
|
8
|
+
|
|
9
|
+
**Interface** — everything a caller must know to use the module correctly: the type signature, but also invariants, ordering constraints, error modes, required configuration, performance characteristics. _Avoid_: API, signature (too narrow — they refer only to the type-level surface).
|
|
10
|
+
|
|
11
|
+
**Implementation** — what's inside a module, its body of code. Distinct from **Adapter**: a module can have a small adapter with a large implementation (a Postgres repo) or a large adapter with a small implementation (an in-memory fake).
|
|
12
|
+
|
|
13
|
+
**Depth** — leverage at the interface: the amount of behaviour a caller (or test) can exercise per unit of interface they must learn. A module is **deep** when a large amount of behaviour sits behind a small interface, **shallow** when the interface is nearly as complex as the implementation.
|
|
14
|
+
|
|
15
|
+
**Seam** _(Michael Feathers)_ — a place where you can alter behaviour without editing in that place; the *location* at which a module's interface lives. Where to put the seam is its own design decision, distinct from what goes behind it. _Avoid_: boundary (overloaded with DDD's bounded context).
|
|
16
|
+
|
|
17
|
+
**Adapter** — a concrete thing that satisfies an interface at a seam. Describes *role* (what slot it fills), not substance (what's inside).
|
|
18
|
+
|
|
19
|
+
**Leverage** — what callers get from depth: more capability per unit of interface they learn. One implementation pays back across N call sites and M tests.
|
|
20
|
+
|
|
21
|
+
**Locality** — what maintainers get from depth: change, bugs, knowledge, and verification concentrate in one place rather than spreading across callers. Fix once, fixed everywhere.
|
|
22
|
+
|
|
23
|
+
## Deep vs shallow
|
|
24
|
+
|
|
25
|
+
**Deep module** = small interface + lots of implementation:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
┌─────────────────────┐
|
|
29
|
+
│ Small Interface │ ← Few methods, simple params
|
|
30
|
+
├─────────────────────┤
|
|
31
|
+
│ │
|
|
32
|
+
│ Deep Implementation│ ← Complex logic hidden
|
|
33
|
+
│ │
|
|
34
|
+
└─────────────────────┘
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Shallow module** = large interface + little implementation (avoid):
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
┌─────────────────────────────────┐
|
|
41
|
+
│ Large Interface │ ← Many methods, complex params
|
|
42
|
+
├─────────────────────────────────┤
|
|
43
|
+
│ Thin Implementation │ ← Just passes through
|
|
44
|
+
└─────────────────────────────────┘
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Principles
|
|
48
|
+
|
|
49
|
+
- **Depth is a property of the interface, not the implementation.** A deep module can be internally composed of small, mockable parts — they just aren't part of the interface.
|
|
50
|
+
- **The deletion test.** Imagine deleting the module. If complexity vanishes, it was a pass-through. If complexity reappears across N callers, it was earning its keep.
|
|
51
|
+
- **The interface is the test surface.** Callers and tests cross the same seam. If you want to test *past* the interface, the module is probably the wrong shape.
|
|
52
|
+
- **One adapter means a hypothetical seam. Two adapters means a real one.** Don't introduce a seam unless something actually varies across it.
|
|
53
|
+
|
|
54
|
+
## Designing for testability
|
|
55
|
+
|
|
56
|
+
1. **Accept dependencies, don't create them.** `function processOrder(order, paymentGateway)` is testable; `function processOrder(order)` that news up its own gateway is not.
|
|
57
|
+
2. **Return results, don't produce side effects.** `function calculateDiscount(cart): Discount` is testable; `function applyDiscount(cart): void` that mutates is not.
|
|
58
|
+
3. **Small surface area.** Fewer methods = fewer tests needed. Fewer params = simpler test setup.
|
|
59
|
+
|
|
60
|
+
## Where this is used
|
|
61
|
+
|
|
62
|
+
- **03-work** — when designing or restructuring a module, use these terms to evaluate depth and seam placement.
|
|
63
|
+
- **04-review** — when auditing the architecture axis, flag shallow modules and missing seams using this vocabulary.
|