pi-matt-pocock 0.2.2 → 0.3.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/ARCHITECTURE.zh-CN.md +37 -19
- package/README.md +80 -13
- package/package.json +12 -7
- package/procedures/code-review.md +25 -17
- package/procedures/codebase-design.md +11 -10
- package/procedures/deslop.md +4 -2
- package/procedures/diagnosing-bugs.md +25 -25
- package/procedures/domain-modeling.md +18 -20
- package/procedures/grill-me.md +1 -1
- package/procedures/grill-with-docs.md +1 -1
- package/procedures/grilling.md +29 -5
- package/procedures/handoff.md +1 -1
- package/procedures/implement.md +7 -1
- package/procedures/improve-codebase-architecture.md +22 -22
- package/procedures/pr.md +169 -0
- package/procedures/prototype.md +7 -6
- package/procedures/research.md +2 -2
- package/procedures/retro.md +42 -0
- package/procedures/setup-matt-pocock-skills.md +26 -22
- package/procedures/tdd.md +17 -15
- package/procedures/teach.md +11 -7
- package/procedures/to-questionnaire.md +7 -5
- package/procedures/to-spec.md +2 -2
- package/procedures/to-tickets.md +12 -12
- package/procedures/triage.md +22 -22
- package/procedures/wait-what.md +1 -1
- package/procedures/wayfinder.md +24 -24
- package/procedures/wizard.md +7 -7
- package/procedures/writing-for-agents.md +14 -14
- package/{procedures → references}/ADR-FORMAT.md +11 -11
- package/{procedures → references}/AGENT-BRIEF.md +4 -4
- package/{procedures → references}/DEEPENING.md +3 -3
- package/{procedures → references}/DESIGN-IT-TWICE.md +7 -7
- package/{procedures → references}/GLOSSARY-FORMAT.md +9 -2
- package/{procedures → references}/HTML-REPORT.md +15 -15
- package/{procedures → references}/LEARNING-RECORD-FORMAT.md +10 -10
- package/{procedures → references}/LOGIC.md +5 -5
- package/{procedures → references}/MISSION-FORMAT.md +2 -2
- package/{procedures → references}/OUT-OF-SCOPE.md +11 -11
- package/{procedures → references}/RESOURCES-FORMAT.md +1 -1
- package/{procedures → references}/SKILL-MECHANICS.md +3 -3
- package/{procedures → references}/UI.md +14 -14
- package/{procedures → references}/bdd-best-practices.md +3 -3
- package/{procedures → references}/bdd.md +9 -9
- package/{procedures → references}/domain.md +12 -12
- package/references/issue-tracker-github.md +50 -0
- package/{procedures → references}/issue-tracker-gitlab.md +9 -9
- package/{procedures → references}/issue-tracker-local.md +3 -3
- package/{procedures → references}/phase-boundaries.md +8 -8
- package/src/catalog.json +49 -28
- package/src/catalog.ts +58 -2
- package/src/index.ts +521 -383
- package/src/native-dialog.ts +149 -213
- package/src/resolver.ts +30 -14
- package/src/workflow.ts +55 -16
- package/upstream/UPSTREAM.md +116 -0
- package/{scripts → upstream}/check-upstream-sync.mjs +12 -12
- package/{upstream-selection.json → upstream/upstream-selection.json} +9 -7
- package/UPSTREAM.md +0 -63
- package/procedures/CONTEXT-FORMAT.md +0 -60
- package/procedures/issue-tracker-github.md +0 -45
- /package/{procedures → assets}/hitl-loop.template.sh +0 -0
- /package/{procedures → assets}/template.sh +0 -0
- /package/{procedures → references}/GLOSSARY.md +0 -0
- /package/{procedures → references}/gherkin-guide.md +0 -0
- /package/{procedures → references}/mocking.md +0 -0
- /package/{procedures → references}/testing-anti-patterns.md +0 -0
- /package/{procedures → references}/tests.md +0 -0
- /package/{procedures → references}/triage-labels.md +0 -0
- /package/{procedures → references}/writing-great-skills.md +0 -0
|
@@ -29,9 +29,9 @@ Put the actual logic — the bit that's answering the question — behind a smal
|
|
|
29
29
|
|
|
30
30
|
The right shape depends on the question:
|
|
31
31
|
|
|
32
|
-
- **A pure reducer
|
|
33
|
-
- **A state machine
|
|
34
|
-
- **A small set of pure functions** over a plain data type. Good when there's no implicit current state
|
|
32
|
+
- **A pure reducer**: `(state, action) => state`. Good when actions are discrete events and state is a single value.
|
|
33
|
+
- **A state machine**: explicit states and transitions. Good when "which actions are even legal right now" is part of the question.
|
|
34
|
+
- **A small set of pure functions** over a plain data type. Good when there's no implicit current state, just transformations.
|
|
35
35
|
- **A class or module with a clear method surface** when the logic genuinely owns ongoing internal state.
|
|
36
36
|
|
|
37
37
|
Pick whichever shape best fits the question being asked, *not* whichever is easiest to wire to a TUI. Keep it pure: no I/O, no terminal code, no `console.log` for control flow. The TUI imports it and calls into it; nothing flows the other direction.
|
|
@@ -58,7 +58,7 @@ The whole frame should fit on one screen.
|
|
|
58
58
|
|
|
59
59
|
### 5. Make it runnable in one command
|
|
60
60
|
|
|
61
|
-
Add a script to the project's existing task runner (`package.json` scripts, `Makefile`, `justfile`, `pyproject.toml`). The user should run `
|
|
61
|
+
Add a script to the project's existing task runner (`package.json` scripts, `Makefile`, `justfile`, `pyproject.toml`). The user should run `bun run <prototype-name>` or the project's equivalent — never need to remember a path.
|
|
62
62
|
|
|
63
63
|
If the host project has no task runner, just put the command at the top of the prototype's README.
|
|
64
64
|
|
|
@@ -68,7 +68,7 @@ Give the user the run command. They'll drive it themselves; the interesting mome
|
|
|
68
68
|
|
|
69
69
|
### 7. Capture the answer and the prototype
|
|
70
70
|
|
|
71
|
-
Once the prototype has answered its question, capture the answer, then capture the prototype the way the [SKILL](prototype.md) describes. The logic-specific mapping: the validated reducer / machine / function set lifts into the real module (the decision, absorbed); the TUI shell rides along to the throwaway branch that keeps the prototype as a primary source.
|
|
71
|
+
Once the prototype has answered its question, capture the answer, then capture the prototype the way the [SKILL](../procedures/prototype.md) describes. The logic-specific mapping: the validated reducer / machine / function set lifts into the real module (the decision, absorbed); the TUI shell rides along to the throwaway branch that keeps the prototype as a primary source.
|
|
72
72
|
|
|
73
73
|
## Anti-patterns
|
|
74
74
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# MISSION.md Format
|
|
2
2
|
|
|
3
|
-
`MISSION.md` lives at the workspace root. It captures the _reason_ the user is learning this topic. Every teaching decision
|
|
3
|
+
`MISSION.md` lives at the workspace root. It captures the _reason_ the user is learning this topic. Every teaching decision (what to teach next, which resources to surface, which exercises to design) should trace back to this document.
|
|
4
4
|
|
|
5
5
|
## Template
|
|
6
6
|
|
|
@@ -27,5 +27,5 @@
|
|
|
27
27
|
- **One mission per workspace.** If the user wants to learn two unrelated things, that is two workspaces.
|
|
28
28
|
- **Concrete over abstract.** "Run a half marathon by October" beats "get fitter." "Ship a Rust CLI to my team" beats "learn Rust."
|
|
29
29
|
- **Push back on vagueness.** If the user cannot articulate why, interview them before writing anything. A bad mission is worse than no mission.
|
|
30
|
-
- **Revise when reality shifts.** Missions change. When the user's goal moves, update this file
|
|
30
|
+
- **Revise when reality shifts.** Missions change. When the user's goal moves, update this file: don't leave a stale mission steering future sessions.
|
|
31
31
|
- **Keep it short.** If `MISSION.md` runs past a screen, it has stopped being a compass and started being a plan.
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
The `.out-of-scope/` directory in a repo stores persistent records of rejected feature requests. It serves two purposes:
|
|
4
4
|
|
|
5
|
-
1. **Institutional memory
|
|
6
|
-
2. **Deduplication
|
|
5
|
+
1. **Institutional memory**: why a feature was rejected, so the reasoning isn't lost when the issue is closed
|
|
6
|
+
2. **Deduplication**: when a new issue comes in that matches a prior rejection, the skill can surface the previous decision instead of re-litigating it
|
|
7
7
|
|
|
8
8
|
## Directory structure
|
|
9
9
|
|
|
@@ -18,7 +18,7 @@ One file per **concept**, not per issue. Multiple issues requesting the same thi
|
|
|
18
18
|
|
|
19
19
|
## File format
|
|
20
20
|
|
|
21
|
-
The file should be written in a relaxed, readable style
|
|
21
|
+
The file should be written in a relaxed, readable style, more like a short design document than a database entry. Use paragraphs, code samples, and examples to make the reasoning clear and useful to someone encountering it for the first time.
|
|
22
22
|
|
|
23
23
|
```markdown
|
|
24
24
|
# Dark Mode
|
|
@@ -59,31 +59,31 @@ Use a short, descriptive kebab-case name for the concept: `dark-mode.md`, `plugi
|
|
|
59
59
|
|
|
60
60
|
### Writing the reason
|
|
61
61
|
|
|
62
|
-
The reason should be substantive
|
|
62
|
+
The reason should be substantive: not "we don't want this" but why. Good reasons reference:
|
|
63
63
|
|
|
64
64
|
- Project scope or philosophy ("This project focuses on X; theming is a downstream concern")
|
|
65
65
|
- Technical constraints ("Supporting this would require Y, which conflicts with our Z architecture")
|
|
66
66
|
- Strategic decisions ("We chose to use A instead of B because...")
|
|
67
67
|
|
|
68
|
-
The reason should be durable. Avoid referencing temporary circumstances ("we're too busy right now")
|
|
68
|
+
The reason should be durable. Avoid referencing temporary circumstances ("we're too busy right now"); those aren't real rejections, they're deferrals.
|
|
69
69
|
|
|
70
70
|
## When to check `.out-of-scope/`
|
|
71
71
|
|
|
72
72
|
During triage (Step 1: Gather context), read all files in `.out-of-scope/`. When evaluating a new issue:
|
|
73
73
|
|
|
74
74
|
- Check if the request matches an existing out-of-scope concept
|
|
75
|
-
- Matching is by concept similarity, not keyword
|
|
75
|
+
- Matching is by concept similarity, not keyword: "night theme" matches `dark-mode.md`
|
|
76
76
|
- If there's a match, surface it to the maintainer: "This is similar to `.out-of-scope/dark-mode.md` — we rejected this before because [reason]. Do you still feel the same way?"
|
|
77
77
|
|
|
78
78
|
The maintainer may:
|
|
79
79
|
|
|
80
|
-
- **Confirm
|
|
81
|
-
- **Reconsider
|
|
82
|
-
- **Disagree
|
|
80
|
+
- **Confirm**: the new issue gets added to the existing file's "Prior requests" list, then closed
|
|
81
|
+
- **Reconsider**: the out-of-scope file gets deleted or updated, and the issue proceeds through normal triage
|
|
82
|
+
- **Disagree**: the issues are related but distinct, proceed with normal triage
|
|
83
83
|
|
|
84
84
|
## When to write to `.out-of-scope/`
|
|
85
85
|
|
|
86
|
-
Only when an **enhancement** (not a bug) is *rejected* as `wontfix`. This applies to enhancement PRs exactly as it does to issues
|
|
86
|
+
Only when an **enhancement** (not a bug) is *rejected* as `wontfix`. This applies to enhancement PRs exactly as it does to issues: a rejected PR is recorded here so the same request doesn't return as fresh code.
|
|
87
87
|
|
|
88
88
|
Do **not** write here when something is closed as `wontfix` because it's **already implemented**. That's a built feature, not a rejected one; recording it would poison the dedup checks with false rejections. Instead, the closing comment points to where the feature already lives.
|
|
89
89
|
|
|
@@ -101,5 +101,5 @@ The flow:
|
|
|
101
101
|
If the maintainer changes their mind about a previously rejected concept:
|
|
102
102
|
|
|
103
103
|
- Delete the `.out-of-scope/` file
|
|
104
|
-
- The skill does not need to reopen old issues
|
|
104
|
+
- The skill does not need to reopen old issues; they're historical records
|
|
105
105
|
- The new issue that triggered the reconsideration proceeds through normal triage
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
|
|
27
27
|
- **High-trust only.** Prefer primary sources, recognised experts, peer-reviewed work, and communities with strong moderation. If a resource is marketing dressed as education, leave it out.
|
|
28
28
|
- **Annotate every entry.** A bare link is useless in three months. Add one line: what it covers and when to reach for it.
|
|
29
|
-
- **Group by Knowledge / Wisdom.** Mirrors the philosophy in [teach.md](
|
|
29
|
+
- **Group by Knowledge / Wisdom.** Mirrors the philosophy in [teach.md](../procedures/teach.md). It is fine for a resource to appear in only one group.
|
|
30
30
|
- **Surface gaps explicitly.** If no good resource exists for an area the mission needs, write a `## Gaps` section listing what is missing. This drives future search.
|
|
31
31
|
- **Prune ruthlessly.** A resource that turned out to be wrong, shallow, or off-mission should be removed, not buried. Better five sharp sources than thirty mediocre ones.
|
|
32
32
|
- **Record community preferences.** If the user has opted out of joining communities, note it here so future sessions don't keep proposing them.
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
# Skill mechanics
|
|
2
2
|
|
|
3
|
-
The skill-specific branch of [`writing-for-agents`](writing-for-agents.md): what changes when the document is a skill — frontmatter, the invocation choice, and router skills. Everything else about writing it is the universal reference in `writing-for-agents.md`.
|
|
3
|
+
The skill-specific branch of [`writing-for-agents`](../procedures/writing-for-agents.md): what changes when the document is a skill — frontmatter, the invocation choice, and router skills. Everything else about writing it is the universal reference in `writing-for-agents.md`.
|
|
4
4
|
|
|
5
5
|
## Invocation
|
|
6
6
|
|
|
7
7
|
Two choices, trading the two loads:
|
|
8
8
|
|
|
9
9
|
- A **model-invoked** skill keeps a `description`, so the agent can fire it autonomously — and other skills can reach it. You can still type its name: model-invocation always _includes_ user reach; a description only ever adds agent discovery, never removes the human's. The description is the skill's top-level context pointer, forced to stay loaded at all times — permanent context load in exchange for discoverability. A model-invoked skill whose content is all reference is also one home for shared reference: another skill can invoke it, so reference needed by several skills lives in one place. Mechanics: omit `disable-model-invocation`, and write a model-facing description carrying the trigger branches (the pointer-writing rules in `writing-for-agents.md` apply in full).
|
|
10
|
-
- A **user-invoked** skill strips the description from the agent's reach: only the human typing its name can invoke it, and no other skill can. Zero context load, but it spends cognitive load
|
|
10
|
+
- A **user-invoked** skill strips the description from the agent's reach: only the human typing its name can invoke it, and no other skill can. Zero context load, but it spends cognitive load: you are the index that must remember it exists. Mechanics: set `disable-model-invocation: true`; the `description` becomes human-facing: a one-line summary, trigger lists stripped.
|
|
11
11
|
|
|
12
12
|
Pick model-invocation only when the agent must reach the skill on its own, or another skill must. If it only ever fires by hand, make it user-invoked and pay no context load.
|
|
13
13
|
|
|
14
|
-
Shared reference that two user-invoked skills both need can live in neither
|
|
14
|
+
Shared reference that two user-invoked skills both need can live in neither: with no descriptions, neither can fire the other. Push it to a plain file outside the skill system: external reference any skill can point at.
|
|
15
15
|
|
|
16
16
|
## Splitting by invocation
|
|
17
17
|
|
|
@@ -11,19 +11,19 @@ If the question is about logic/state rather than what something looks like — w
|
|
|
11
11
|
- "Try a different layout for the settings screen."
|
|
12
12
|
- Any time the user would otherwise spend a day picking between three vague mockups in their head.
|
|
13
13
|
|
|
14
|
-
## Two sub-shapes
|
|
14
|
+
## Two sub-shapes: strongly prefer sub-shape A
|
|
15
15
|
|
|
16
|
-
A UI prototype is much easier to judge when it's **butting up against the rest of the app
|
|
16
|
+
A UI prototype is much easier to judge when it's **butting up against the rest of the app**: real header, real sidebar, real data, real density. A throwaway route on its own is a vacuum: every variant looks fine in isolation. Default to sub-shape A whenever there's a plausible existing page to host the variants. Only reach for sub-shape B if the prototype genuinely has no nearby home.
|
|
17
17
|
|
|
18
|
-
### Sub-shape A
|
|
18
|
+
### Sub-shape A: adjustment to an existing page (preferred)
|
|
19
19
|
|
|
20
20
|
The route already exists. Variants are rendered **on the same route**, gated by a `?variant=` URL search param. The existing data fetching, params, and auth all stay — only the rendering swaps. This is the default; pick it unless there's a specific reason not to.
|
|
21
21
|
|
|
22
22
|
If the prototype is for something that doesn't yet have a page but *would naturally live inside one* (a new section of the dashboard, a new card on the settings screen, a new step in an existing flow) — that's still sub-shape A. Mount the variants inside the host page.
|
|
23
23
|
|
|
24
|
-
### Sub-shape B
|
|
24
|
+
### Sub-shape B: a new page (last resort)
|
|
25
25
|
|
|
26
|
-
Only use this when the thing being prototyped genuinely has no existing page to live inside
|
|
26
|
+
Only use this when the thing being prototyped genuinely has no existing page to live inside (e.g. an entirely new top-level surface, or a flow that can't be embedded anywhere sensible).
|
|
27
27
|
|
|
28
28
|
Create a **throwaway route** following whatever routing convention the project already uses — don't invent a new top-level structure. Name it so it's obviously a prototype (e.g. include the word `prototype` in the path or filename). Same `?variant=` pattern.
|
|
29
29
|
|
|
@@ -51,7 +51,7 @@ Draft each variant. Hold each one to:
|
|
|
51
51
|
- The project's component library / styling system (TailwindCSS, shadcn, MUI, plain CSS, whatever).
|
|
52
52
|
- A clear exported component name, e.g. `VariantA`, `VariantB`, `VariantC`.
|
|
53
53
|
|
|
54
|
-
Variants must be **structurally different
|
|
54
|
+
Variants must be **structurally different**: different layout, different information hierarchy, different primary affordance, not just different colours. Three slightly-tweaked card grids isn't a UI prototype, it's wallpaper. If two drafts come out too similar, redo one with explicit "do not use a card grid" guidance.
|
|
55
55
|
|
|
56
56
|
### 3. Wire them together
|
|
57
57
|
|
|
@@ -78,16 +78,16 @@ For sub-shape B (new page): the throwaway route under `/prototype/<name>` mounts
|
|
|
78
78
|
|
|
79
79
|
A small fixed-position bar at the bottom-centre of the screen with three pieces:
|
|
80
80
|
|
|
81
|
-
- **Left arrow
|
|
82
|
-
- **Variant label
|
|
83
|
-
- **Right arrow
|
|
81
|
+
- **Left arrow**: cycles to the previous variant (wraps around).
|
|
82
|
+
- **Variant label**: shows the current variant key and, if the variant exports a name, that name too. e.g. `B (Sidebar layout)`.
|
|
83
|
+
- **Right arrow**: cycles forward (wraps around).
|
|
84
84
|
|
|
85
85
|
Behaviour:
|
|
86
86
|
|
|
87
87
|
- Clicking an arrow updates the URL search param (use the framework's router — `router.replace` on Next, `navigate` on React Router, etc) so the variant is shareable and reload-stable.
|
|
88
88
|
- Keyboard: `←` and `→` arrow keys also cycle. Don't intercept arrow keys when an `<input>`, `<textarea>`, or `[contenteditable]` is focused.
|
|
89
89
|
- Visually distinct from the page (e.g. high-contrast pill, subtle shadow) so it's obviously not part of the design being evaluated.
|
|
90
|
-
- Hidden in production builds
|
|
90
|
+
- Hidden in production builds: gate on `process.env.NODE_ENV !== 'production'` or an equivalent check, so a stray prototype merge can't ship the bar to users.
|
|
91
91
|
|
|
92
92
|
Put the switcher in a single shared component so both sub-shapes can reuse it. Locate it wherever shared UI lives in the project.
|
|
93
93
|
|
|
@@ -97,10 +97,10 @@ Surface the URL (and the `?variant=` keys). The user will flip through whenever
|
|
|
97
97
|
|
|
98
98
|
### 6. Capture the answer and clean up
|
|
99
99
|
|
|
100
|
-
Once a variant has won, capture the answer — which variant and why — then capture the prototype the way the [SKILL](prototype.md) describes. Fold the winner into the real code and move the rest onto the throwaway branch, not into main:
|
|
100
|
+
Once a variant has won, capture the answer — which variant and why — then capture the prototype the way the [SKILL](../procedures/prototype.md) describes. Fold the winner into the real code and move the rest onto the throwaway branch, not into main:
|
|
101
101
|
|
|
102
|
-
- **Sub-shape A
|
|
103
|
-
- **Sub-shape B
|
|
102
|
+
- **Sub-shape A**: fold the winner into the existing page; drop the losing variants and the switcher from main.
|
|
103
|
+
- **Sub-shape B**: promote the winning variant to a real route; drop the throwaway route and the switcher from main.
|
|
104
104
|
|
|
105
105
|
The full set of variants is the primary source, so it lands on the throwaway branch, not the bin — variant components and the switcher left in the main branch rot fast and confuse the next reader.
|
|
106
106
|
|
|
@@ -108,5 +108,5 @@ The full set of variants is the primary source, so it lands on the throwaway bra
|
|
|
108
108
|
|
|
109
109
|
- **Variants that differ only in colour or copy.** That's a tweak, not a prototype. Real variants disagree about structure.
|
|
110
110
|
- **Sharing too much code between variants.** A shared `<Header>` is fine; a shared `<Layout>` defeats the point. Each variant should be free to throw out the layout.
|
|
111
|
-
- **Wiring variants to real mutations.** Read-only prototypes are fine. If a variant needs to mutate, point it at a stub
|
|
111
|
+
- **Wiring variants to real mutations.** Read-only prototypes are fine. If a variant needs to mutate, point it at a stub: the question is "what should this look like", not "does the backend work".
|
|
112
112
|
- **Promoting the prototype directly to production.** The variant code was written under prototype constraints (no tests, minimal error handling). Rewrite it properly when you fold it in.
|
|
@@ -16,7 +16,7 @@ Before writing code or tests, the "Three Amigos" (Business/PO, Developer, Tester
|
|
|
16
16
|
Convert those examples into structured scenarios using Gherkin syntax (Given/When/Then).
|
|
17
17
|
* **Goal:** Executable specifications / Living Documentation.
|
|
18
18
|
* **Standard:** Write *declarative* scenarios that describe business behavior, not UI implementation details.
|
|
19
|
-
* **Reference:** See [Gherkin Guide](
|
|
19
|
+
* **Reference:** See [Gherkin Guide](gherkin-guide.md).
|
|
20
20
|
|
|
21
21
|
### Automation (BDD-Driven TDD / Red-Green-Refactor)
|
|
22
22
|
Implement the scenarios using the Red-Green-Refactor cycle.
|
|
@@ -53,14 +53,14 @@ This is the engine of implementation.
|
|
|
53
53
|
In this plugin, TDD is always **BDD-driven** — the Automation phase of the BDD lifecycle:
|
|
54
54
|
|
|
55
55
|
* **BDD** ([bdd](bdd.md)) — Discovery (conversations → examples) → Formulation (Gherkin scenarios) → Automation (BDD-driven red-green loop).
|
|
56
|
-
* **TDD** ([tdd](tdd.md)) — The BDD-driven Automation phase reference: test quality, seams, mocking, anti-patterns, and the red-green loop rules. It is invoked during [bdd](bdd.md) and [implement](implement.md) for test implementation guidance.
|
|
56
|
+
* **TDD** ([tdd](../procedures/tdd.md)) — The BDD-driven Automation phase reference: test quality, seams, mocking, anti-patterns, and the red-green loop rules. It is invoked during [bdd](bdd.md) and [implement](../procedures/implement.md) for test implementation guidance.
|
|
57
57
|
* **Usage:** BDD defines *what* to build (the Gherkin scenarios). BDD-driven TDD ensures the *implementation* is correct and robust via the red-green loop. They are a unified pipeline, not two practices.
|
|
58
58
|
|
|
59
59
|
## 5. Iron Law Exceptions
|
|
60
60
|
|
|
61
61
|
The Iron Law ("no production code without a failing test first") has exactly three legitimate exceptions — and even these should be raised with the user, not silently assumed:
|
|
62
62
|
|
|
63
|
-
* **One-off prototypes** — throwaway code answering a design question (see [prototype](prototype.md)). It will be deleted, not shipped, so a regression guard adds nothing. If the prototype survives into the real codebase, the Iron Law re-applies.
|
|
63
|
+
* **One-off prototypes** — throwaway code answering a design question (see [prototype](../procedures/prototype.md)). It will be deleted, not shipped, so a regression guard adds nothing. If the prototype survives into the real codebase, the Iron Law re-applies.
|
|
64
64
|
* **Generated code** — output of a code generator or scaffolder where the *generator* is the system under test, not the generated artifact. Test the generator's contract; the generated files are downstream artifacts, not hand-written behavior.
|
|
65
65
|
* **Config files** — declarative configuration (`.feature` step definitions aside) that carries no executable behavior of its own. A misconfigured file fails at load time or via an integration test; a unit test against its literal contents would be tautological.
|
|
66
66
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Behavior-Driven Development (BDD)
|
|
2
2
|
|
|
3
|
-
BDD is not just about tools; it's a methodology for shared understanding and high-quality implementation. This procedure governs the **Discovery → Formulation → Automation** lifecycle: Gherkin scenarios define the behavior, and the Automation phase (red-green loop) is delegated to [tdd](tdd.md) (BDD-driven).
|
|
3
|
+
BDD is not just about tools; it's a methodology for shared understanding and high-quality implementation. This procedure governs the **Discovery → Formulation → Automation** lifecycle: Gherkin scenarios define the behavior, and the Automation phase (red-green loop) is delegated to [tdd](../procedures/tdd.md) (BDD-driven).
|
|
4
4
|
|
|
5
|
-
When exploring the codebase, read `
|
|
5
|
+
When exploring the codebase, read `GLOSSARY.md` (if it exists) so test names and interface vocabulary match the project's domain language, and respect ADRs in the area you're touching.
|
|
6
6
|
|
|
7
7
|
## How to Use This Procedure
|
|
8
8
|
|
|
@@ -18,7 +18,7 @@ The process flows from requirements to code:
|
|
|
18
18
|
|
|
19
19
|
* **Discovery:** Clarify requirements through examples (The "Three Amigos").
|
|
20
20
|
* **Formulation:** Write these examples as specific scenarios (Given/When/Then).
|
|
21
|
-
* **Automation:** Implement using the red-green-refactor cycle via [tdd](tdd.md), which governs test quality, seams, mocking, and anti-patterns.
|
|
21
|
+
* **Automation:** Implement using the red-green-refactor cycle via [tdd](../procedures/tdd.md), which governs test quality, seams, mocking, and anti-patterns.
|
|
22
22
|
|
|
23
23
|
See `./references/bdd-best-practices.md` for a detailed guide.
|
|
24
24
|
|
|
@@ -35,7 +35,7 @@ See `./references/gherkin-guide.md` for syntax and storage structure.
|
|
|
35
35
|
|
|
36
36
|
## Automation Phase
|
|
37
37
|
|
|
38
|
-
The Automation phase (red-green loop) is governed by the [tdd](tdd.md) capability (BDD-driven). When the Gherkin scenario is defined and the seam is agreed, load [tdd](tdd.md) with `matt_pocock_workflow` (`mode: "capability"`) — it is a package capability, not a Pi skill — for:
|
|
38
|
+
The Automation phase (red-green loop) is governed by the [tdd](../procedures/tdd.md) capability (BDD-driven). When the Gherkin scenario is defined and the seam is agreed, load [tdd](../procedures/tdd.md) with `matt_pocock_workflow` (`mode: "capability"`) — it is a package capability, not a Pi skill — for:
|
|
39
39
|
|
|
40
40
|
- **Seams** — where tests go at the public boundary
|
|
41
41
|
- **Test quality** — what makes a good test, anti-patterns
|
|
@@ -44,13 +44,13 @@ The Automation phase (red-green loop) is governed by the [tdd](tdd.md) capabilit
|
|
|
44
44
|
|
|
45
45
|
## Seams — where tests go
|
|
46
46
|
|
|
47
|
-
Seams are the public boundaries you test at. See [tdd](tdd.md) for the full seam guidance.
|
|
47
|
+
Seams are the public boundaries you test at. See [tdd](../procedures/tdd.md) for the full seam guidance.
|
|
48
48
|
|
|
49
49
|
**Test at the highest established seam.** Before writing a test, inspect the existing public boundaries, record the seam under test, and choose the highest one that expresses the confirmed behavior. Testing everything isn't possible — deliberately choosing the critical public seam is how effort lands on complex behavior instead of every edge case. Ask the user only when the behavior or public-contract choice is genuinely unresolved; otherwise begin the red-green loop immediately.
|
|
50
50
|
|
|
51
51
|
## What a good test is
|
|
52
52
|
|
|
53
|
-
Tests verify behavior through public interfaces, not implementation details. See [tdd](tdd.md) for the full guidance, examples, and anti-patterns.
|
|
53
|
+
Tests verify behavior through public interfaces, not implementation details. See [tdd](../procedures/tdd.md) for the full guidance, examples, and anti-patterns.
|
|
54
54
|
|
|
55
55
|
## CRITICAL: The Iron Law
|
|
56
56
|
|
|
@@ -84,15 +84,15 @@ A test-first test encodes "this is what the system is contracted to do." A test-
|
|
|
84
84
|
|
|
85
85
|
## Rules of the loop
|
|
86
86
|
|
|
87
|
-
See [tdd](tdd.md) (BDD-driven) for the full red-green loop rules, anti-patterns, and test quality guidance. The key points:
|
|
87
|
+
See [tdd](../procedures/tdd.md) (BDD-driven) for the full red-green loop rules, anti-patterns, and test quality guidance. The key points:
|
|
88
88
|
|
|
89
89
|
- **Red before green.** Write the failing test first, then only enough code to pass it.
|
|
90
90
|
- **One slice at a time.** One seam, one test, one minimal implementation per cycle.
|
|
91
|
-
- **Refactoring is not part of the loop.** It belongs to the review stage (see [code-review](code-review.md)), not the red → green implementation cycle.
|
|
91
|
+
- **Refactoring is not part of the loop.** It belongs to the review stage (see [code-review](../procedures/code-review.md)), not the red → green implementation cycle.
|
|
92
92
|
|
|
93
93
|
## References
|
|
94
94
|
|
|
95
95
|
- `./references/bdd-best-practices.md` - BDD methodology: discovery, formulation, automation
|
|
96
96
|
- `./references/gherkin-guide.md` - Gherkin syntax, storage structure, examples
|
|
97
97
|
- `./references/testing-anti-patterns.md` - Mocking pitfalls and vacuous-passing tests
|
|
98
|
-
- [tdd](tdd.md) - BDD-driven test implementation: seams, mocking, test quality, red-green loop
|
|
98
|
+
- [tdd](../procedures/tdd.md) - BDD-driven test implementation: seams, mocking, test quality, red-green loop
|
|
@@ -4,11 +4,11 @@ How the engineering skills should consume this repo's domain documentation when
|
|
|
4
4
|
|
|
5
5
|
## Before exploring, read these
|
|
6
6
|
|
|
7
|
-
- **`
|
|
8
|
-
- **`
|
|
9
|
-
- **`docs/adr
|
|
7
|
+
- **`GLOSSARY.md`** at the repo root, or
|
|
8
|
+
- **`GLOSSARY-MAP.md`** at the repo root if it exists: it points at one `GLOSSARY.md` per context. Read each one relevant to the topic.
|
|
9
|
+
- **`docs/adr/`**: read ADRs that touch the area you're about to work in. In multi-context repos, also check `src/<context>/docs/adr/` for context-scoped decisions.
|
|
10
10
|
|
|
11
|
-
If any of these files don't exist, **proceed silently**. Don't flag their absence; don't suggest creating them upfront. The [domain-modeling](domain-modeling.md) capability (bundled with [grill-with-docs](grill-with-docs.md), disclosed by [improve-codebase-architecture](improve-codebase-architecture.md)) creates them lazily when terms or decisions actually get resolved.
|
|
11
|
+
If any of these files don't exist, **proceed silently**. Don't flag their absence; don't suggest creating them upfront. The [domain-modeling](../procedures/domain-modeling.md) capability (bundled with [grill-with-docs](../procedures/grill-with-docs.md), disclosed by [improve-codebase-architecture](../procedures/improve-codebase-architecture.md)) creates them lazily when terms or decisions actually get resolved.
|
|
12
12
|
|
|
13
13
|
## File structure
|
|
14
14
|
|
|
@@ -16,36 +16,36 @@ Single-context repo (most repos):
|
|
|
16
16
|
|
|
17
17
|
```
|
|
18
18
|
/
|
|
19
|
-
├──
|
|
19
|
+
├── GLOSSARY.md
|
|
20
20
|
├── docs/adr/
|
|
21
21
|
│ ├── 0001-event-sourced-orders.md
|
|
22
22
|
│ └── 0002-postgres-for-write-model.md
|
|
23
23
|
└── src/
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
Multi-context repo (presence of `
|
|
26
|
+
Multi-context repo (presence of `GLOSSARY-MAP.md` at the root):
|
|
27
27
|
|
|
28
28
|
```
|
|
29
29
|
/
|
|
30
|
-
├──
|
|
30
|
+
├── GLOSSARY-MAP.md
|
|
31
31
|
├── docs/adr/ ← system-wide decisions
|
|
32
32
|
└── src/
|
|
33
33
|
├── ordering/
|
|
34
|
-
│ ├──
|
|
34
|
+
│ ├── GLOSSARY.md
|
|
35
35
|
│ └── docs/adr/ ← context-specific decisions
|
|
36
36
|
└── billing/
|
|
37
|
-
├──
|
|
37
|
+
├── GLOSSARY.md
|
|
38
38
|
└── docs/adr/
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
## Use the glossary's vocabulary
|
|
42
42
|
|
|
43
|
-
When your output names a domain concept (in an issue title, a refactor proposal, a hypothesis, a test name), use the term as defined in `
|
|
43
|
+
When your output names a domain concept (in an issue title, a refactor proposal, a hypothesis, a test name), use the term as defined in `GLOSSARY.md`. Don't drift to synonyms the glossary explicitly avoids.
|
|
44
44
|
|
|
45
|
-
If the concept you need isn't in the glossary yet, that's a signal — either you're inventing language the project doesn't use (reconsider) or there's a real gap (note it for [domain-modeling](domain-modeling.md)).
|
|
45
|
+
If the concept you need isn't in the glossary yet, that's a signal — either you're inventing language the project doesn't use (reconsider) or there's a real gap (note it for [domain-modeling](../procedures/domain-modeling.md)).
|
|
46
46
|
|
|
47
47
|
## Flag ADR conflicts
|
|
48
48
|
|
|
49
49
|
If your output contradicts an existing ADR, surface it explicitly rather than silently overriding:
|
|
50
50
|
|
|
51
|
-
> _Contradicts ADR-0007 (event-sourced orders)
|
|
51
|
+
> _Contradicts ADR-0007 (event-sourced orders), but worth reopening because…_
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Issue tracker: GitHub
|
|
2
|
+
|
|
3
|
+
Issues and PRDs for this repo live as GitHub issues. Use the `gh` CLI for all operations.
|
|
4
|
+
|
|
5
|
+
## Conventions
|
|
6
|
+
|
|
7
|
+
- **Create an issue**: `gh issue create --title "..." --body "..."`. Use a heredoc for multi-line bodies.
|
|
8
|
+
- **Read an issue**: `gh issue view <number> --comments`, filtering comments by `jq` and also fetching labels.
|
|
9
|
+
- **List issues**: `gh issue list --state open --json number,title,body,labels,comments --jq '[.[] | {number, title, body, labels: [.labels[].name], comments: [.comments[].body]}]'` with appropriate `--label` and `--state` filters.
|
|
10
|
+
- **Make an issue a sub-issue of a parent**: `gh issue create --parent <parent> ...`, or `gh issue edit <parent> --add-sub-issue <child>` afterwards (`gh` 2.94+). Older `gh`: `gh api --method POST repos/<owner>/<repo>/issues/<parent>/sub_issues -F sub_issue_id=<child-db-id>` (database id, as in **Blocking** below). Without sub-issues, put `Part of #<parent>` at the top of the child body.
|
|
11
|
+
- **Blocking**: GitHub's **native issue dependencies**, the canonical, UI-visible representation. Add an edge with `gh issue create --blocked-by <n>,<n> ...` or `gh issue edit <child> --add-blocked-by <blocker>` (`gh` 2.94+). Older `gh`: `gh api --method POST repos/<owner>/<repo>/issues/<child>/dependencies/blocked_by -F issue_id=<blocker-db-id>`, where `<blocker-db-id>` is the blocker's numeric **database id** (`gh api repos/<owner>/<repo>/issues/<n> --jq .id`, _not_ the `#number` or `node_id`). Where dependencies aren't available, fall back to a `Blocked by: #<n>, #<n>` line at the top of the child body. A ticket is unblocked when every blocker is closed.
|
|
12
|
+
- **Count open blockers**: `gh api repos/<owner>/<repo>/issues/<n> --jq .issue_dependencies_summary.blocked_by` (open blockers only; 0 means startable). `gh issue view <n> --json blockedBy` also lists closed blockers, so filter it: `--jq '[.blockedBy.nodes[] | select(.state == "OPEN")] | length'`.
|
|
13
|
+
- **Comment on an issue**: `gh issue comment <number> --body "..."`
|
|
14
|
+
- **Apply / remove labels**: `gh issue edit <number> --add-label "..."` / `--remove-label "..."`
|
|
15
|
+
- **Close**: post the explanation with `gh issue comment <number> --body "..."`, then `gh issue close <number>`. On an already-closed issue, `gh issue close --comment` drops the comment and still exits 0.
|
|
16
|
+
|
|
17
|
+
Infer the repo from `git remote -v`; `gh` does this automatically when run inside a clone.
|
|
18
|
+
|
|
19
|
+
File issues only into the user's own repo. Never file into `mattpocock/skills` (the repo these skills come from) unless the user owns it. In a fork, `gh` can default to the upstream parent, so before the first `gh issue create` of a session, check the target with `gh repo view --json nameWithOwner` and confirm it with the user if it is not their repo.
|
|
20
|
+
|
|
21
|
+
## Pull requests as a triage surface
|
|
22
|
+
|
|
23
|
+
**PRs as a request surface: no.** _(Set to `yes` if this repo treats external PRs as feature requests; [triage](../procedures/triage.md) reads this flag.)_
|
|
24
|
+
|
|
25
|
+
When set to `yes`, PRs run through the same labels and states as issues, using the `gh pr` equivalents:
|
|
26
|
+
|
|
27
|
+
- **Read a PR**: `gh pr view <number>`, then `gh pr view <number> --comments` (off a TTY, `--comments` prints only the comments, not the body), and `gh pr diff <number>` for the diff.
|
|
28
|
+
- **List external PRs for triage**: `gh pr list --state open --json number,title,body,labels,author,authorAssociation,comments` then keep only `authorAssociation` of `CONTRIBUTOR`, `FIRST_TIME_CONTRIBUTOR`, or `NONE` (drop `OWNER`/`MEMBER`/`COLLABORATOR`).
|
|
29
|
+
- **Comment / label / close**: `gh pr comment`, `gh pr edit --add-label`/`--remove-label`, `gh pr close`.
|
|
30
|
+
|
|
31
|
+
GitHub shares one number space across issues and PRs, so a bare `#42` may be either: resolve with `gh pr view 42` and fall back to `gh issue view 42`.
|
|
32
|
+
|
|
33
|
+
## When a skill says "publish to the issue tracker"
|
|
34
|
+
|
|
35
|
+
Create a GitHub issue.
|
|
36
|
+
|
|
37
|
+
## When a skill says "fetch the relevant ticket"
|
|
38
|
+
|
|
39
|
+
Run `gh issue view <number> --comments`.
|
|
40
|
+
|
|
41
|
+
## Wayfinding operations
|
|
42
|
+
|
|
43
|
+
Used by [wayfinder](../procedures/wayfinder.md). The **map** is a single issue with **child** issues as tickets.
|
|
44
|
+
|
|
45
|
+
- **Map**: a single issue labelled `wayfinder:map`, holding the Notes / Decisions-so-far / Fog body. `gh issue create --label wayfinder:map`.
|
|
46
|
+
- **Child ticket**: an issue linked to the map as a GitHub sub-issue (see **Make an issue a sub-issue of a parent**). Where sub-issues aren't enabled, add the child to a task list in the map body and put `Part of #<map>` at the top of the child body. Labels: `wayfinder:<type>` (`research`/`prototype`/`grilling`/`task`). Once claimed, the ticket is assigned to the driving dev.
|
|
47
|
+
- **Blocking**: see **Blocking** under Conventions.
|
|
48
|
+
- **Frontier query**: list the map's open children (`gh issue list --state open`, scoped to the map's sub-issues / task list), drop any with an open blocker (see **Count open blockers**, or an open issue in the `Blocked by` line) or an assignee; first in map order wins.
|
|
49
|
+
- **Claim**: `gh issue edit <n> --add-assignee @me`, the session's first write.
|
|
50
|
+
- **Resolve**: `gh issue comment <n> --body "<answer>"`, then `gh issue close <n>`, then append a context pointer (gist + link) to the map's Decisions-so-far.
|
|
@@ -10,18 +10,18 @@ Issues and PRDs for this repo live as GitLab issues. Use the [`glab`](https://gi
|
|
|
10
10
|
- **Comment on an issue**: `glab issue note <number> --message "..."`. GitLab calls comments "notes".
|
|
11
11
|
- **Apply / remove labels**: `glab issue update <number> --label "..."` / `--unlabel "..."`. Multiple labels can be comma-separated or by repeating the flag.
|
|
12
12
|
- **Close**: `glab issue close <number>`. `glab issue close` does not accept a closing comment, so post the explanation first with `glab issue note <number> --message "..."`, then close.
|
|
13
|
-
- **Merge requests**: GitLab calls PRs "merge requests". Use `glab mr create`, `glab mr view`, `glab mr note`, etc
|
|
13
|
+
- **Merge requests**: GitLab calls PRs "merge requests". Use `glab mr create`, `glab mr view`, `glab mr note`, etc., the same shape as `gh pr ...` with `mr` in place of `pr` and `note`/`--message` in place of `comment`/`--body`.
|
|
14
14
|
|
|
15
|
-
Infer the repo from `git remote -v
|
|
15
|
+
Infer the repo from `git remote -v`; `glab` does this automatically when run inside a clone.
|
|
16
16
|
|
|
17
17
|
## Merge requests as a triage surface
|
|
18
18
|
|
|
19
|
-
**MRs as a request surface: no.** _(Set to `yes` if this repo treats external merge requests as feature requests; [triage](triage.md) reads this flag.)_
|
|
19
|
+
**MRs as a request surface: no.** _(Set to `yes` if this repo treats external merge requests as feature requests; [triage](../procedures/triage.md) reads this flag.)_
|
|
20
20
|
|
|
21
21
|
When set to `yes`, MRs run through the same labels and states as issues, using the `glab mr` equivalents:
|
|
22
22
|
|
|
23
23
|
- **Read an MR**: `glab mr view <number> --comments` and `glab mr diff <number>` for the diff.
|
|
24
|
-
- **List external MRs for triage**: `glab mr list -
|
|
24
|
+
- **List external MRs for triage**: `glab mr list -O json`, then keep only MRs whose author is not a project member/owner (a contributor's MR, not a maintainer's in-flight work).
|
|
25
25
|
- **Comment / label / close**: `glab mr note`, `glab mr update --label`/`--unlabel`, `glab mr close`.
|
|
26
26
|
|
|
27
27
|
Unlike GitHub, GitLab numbers issues and MRs separately, so `#42` is unambiguous once you know which surface the maintainer means.
|
|
@@ -36,11 +36,11 @@ Run `glab issue view <number> --comments`.
|
|
|
36
36
|
|
|
37
37
|
## Wayfinding operations
|
|
38
38
|
|
|
39
|
-
Used by [wayfinder](wayfinder.md). The **map** is a single issue with **child** issues as tickets.
|
|
39
|
+
Used by [wayfinder](../procedures/wayfinder.md). The **map** is a single issue with **child** issues as tickets.
|
|
40
40
|
|
|
41
41
|
- **Map**: a single issue labelled `wayfinder:map`, holding the Notes / Decisions-so-far / Fog body. `glab issue create --label wayfinder:map`. (On GitLab tiers with native epics, an epic may hold the map instead; a labelled issue works everywhere.)
|
|
42
|
-
- **Child ticket**: an issue carrying `Part of #<map>` at the top of its description and labels `wayfinder:<type>` (`research`/`prototype`/`grilling`/`task`). Once claimed, the ticket is assigned to the driving dev.
|
|
43
|
-
- **Blocking**: GitLab's **native blocking link
|
|
44
|
-
- **Frontier query**: `glab
|
|
45
|
-
- **Claim**: `glab issue update <n> --assignee @me
|
|
42
|
+
- **Child ticket**: an issue carrying `Part of #<map>` at the top of its description, linked to the map (`glab issue create --linked-issues <map> --link-type relates_to`), and labels `wayfinder:<type>` (`research`/`prototype`/`grilling`/`task`). Once claimed, the ticket is assigned to the driving dev.
|
|
43
|
+
- **Blocking**: GitLab's **native blocking link**, the canonical, UI-visible representation. Add it with the `/blocked_by #<n>` quick action, posted as a note (`glab issue note <child> --message "/blocked_by #<blocker>"`). Native blocking links are a Premium/Ultimate feature; on the free tier (or where unavailable) fall back to a `Blocked by: #<n>, #<n>` line at the top of the description. A ticket is unblocked when every blocker is closed.
|
|
44
|
+
- **Frontier query**: list the map's children with `glab api projects/:id/issues/<map>/links`, keeping open issues that carry a `wayfinder:<type>` label; drop any with an open blocker: a native `blocked_by` link to an open issue (`glab api projects/:id/issues/<child-iid>/links`), or an open issue in the `Blocked by` line, or an assignee; first in map order wins.
|
|
45
|
+
- **Claim**: `glab issue update <n> --assignee @me`, the session's first write.
|
|
46
46
|
- **Resolve**: `glab issue note <n> --message "<answer>"`, then `glab issue close <n>`, then append a context pointer (gist + link) to the map's Decisions-so-far.
|
|
@@ -6,7 +6,7 @@ Issues and specs (you may know a spec as a PRD) for this repo live as markdown f
|
|
|
6
6
|
|
|
7
7
|
- One feature per directory: `.scratch/<feature-slug>/`
|
|
8
8
|
- The spec is `.scratch/<feature-slug>/spec.md`
|
|
9
|
-
- Implementation issues are one file per ticket at `.scratch/<feature-slug>/issues/<NN>-<slug>.md`, numbered from `01
|
|
9
|
+
- Implementation issues are one file per ticket at `.scratch/<feature-slug>/issues/<NN>-<slug>.md`, numbered from `01`, never a single combined tickets file
|
|
10
10
|
- Triage state is recorded as a `Status:` line near the top of each issue file (see `triage-labels.md` for the role strings)
|
|
11
11
|
- Comments and conversation history append to the bottom of the file under a `## Comments` heading
|
|
12
12
|
|
|
@@ -20,9 +20,9 @@ Read the file at the referenced path. The user will normally pass the path or th
|
|
|
20
20
|
|
|
21
21
|
## Wayfinding operations
|
|
22
22
|
|
|
23
|
-
Used by [wayfinder](wayfinder.md). The **map** is a file with one **child** file per ticket.
|
|
23
|
+
Used by [wayfinder](../procedures/wayfinder.md). The **map** is a file with one **child** file per ticket.
|
|
24
24
|
|
|
25
|
-
- **Map**: `.scratch/<effort>/map.md`
|
|
25
|
+
- **Map**: `.scratch/<effort>/map.md` (the Notes / Decisions-so-far / Fog body).
|
|
26
26
|
- **Child ticket**: `.scratch/<effort>/issues/NN-<slug>.md`, numbered from `01`, with the question in the body. A `Type:` line records the ticket type (`research`/`prototype`/`grilling`/`task`); a `Status:` line records `claimed`/`resolved`.
|
|
27
27
|
- **Blocking**: a `Blocked by: NN, NN` line near the top. A ticket is unblocked when every file it lists is `resolved`.
|
|
28
28
|
- **Frontier**: scan `.scratch/<effort>/issues/` for files that are open, unblocked, and unclaimed; first by number wins.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Phase boundaries
|
|
2
2
|
|
|
3
|
-
A **phase** is a chunk of work inside a session
|
|
3
|
+
A **phase** is a chunk of work inside a session: the grilling, the implementation, the QA. The definition is fuzzy on purpose: a phase ends when you think *"ok, we're done with that"*.
|
|
4
4
|
|
|
5
5
|
The **phase boundary** is the gap between two phases, and it is the only place this decision belongs. Mid-phase there is no decision to make — continue, or delegate the work that remains to a teammate when that facility is available. Compacting mid-phase makes the agent lose the thread.
|
|
6
6
|
|
|
@@ -10,7 +10,7 @@ The **phase boundary** is the gap between two phases, and it is the only place t
|
|
|
10
10
|
| ------------ | --------------------------------------------------------------- |
|
|
11
11
|
| **Continue** | Stay in the session. No context switch at all. |
|
|
12
12
|
| **`/new`** | Start a fresh session when the old context is irrelevant. |
|
|
13
|
-
| **[handoff](handoff.md)** | Write a portable Markdown document; it does not create, fork, or seed a session. |
|
|
13
|
+
| **[handoff](../procedures/handoff.md)** | Write a portable Markdown document; it does not create, fork, or seed a session. |
|
|
14
14
|
| **Teammate** | Delegate a tightly scoped task when the teammate facility is available. |
|
|
15
15
|
| **`/compact`** | Compress this context and seed a fresh session with the summary. |
|
|
16
16
|
|
|
@@ -24,32 +24,32 @@ Work top to bottom at the boundary. The first **yes** wins.
|
|
|
24
24
|
|
|
25
25
|
The cost of getting this wrong is one-way. Leave a *relevant* context and you lose the **why** behind what you built, and no amount of reading the diff back gets it returned.
|
|
26
26
|
|
|
27
|
-
**3. Do you need to hand off?** [handoff](handoff.md) is narrow. You need it only when you are:
|
|
27
|
+
**3. Do you need to hand off?** [handoff](../procedures/handoff.md) is narrow. You need it only when you are:
|
|
28
28
|
|
|
29
29
|
- swapping to a **new harness** (one harness → another harness),
|
|
30
30
|
- moving to a **new directory** or repo,
|
|
31
31
|
- sending the work to a **colleague**,
|
|
32
32
|
- or recording a side task you found **mid-phase** without derailing what you're doing.
|
|
33
33
|
|
|
34
|
-
That list is the whole clause. What [handoff](handoff.md) buys is **portability** — a document that travels. It only writes the document; it does not create, fork, or seed a session. If nothing is travelling, you don't need it.
|
|
34
|
+
That list is the whole clause. What [handoff](../procedures/handoff.md) buys is **portability** — a document that travels. It only writes the document; it does not create, fork, or seed a session. If nothing is travelling, you don't need it.
|
|
35
35
|
|
|
36
36
|
**4. Can the task be done AFK?** Is it scoped tightly enough to run with you away from the keyboard, no steering? If the teammate facility is available, delegate it to a teammate and leave this session untouched. Otherwise complete it sequentially in the current context. Automated review is the standard case: the reviewer reads the diff and reports, and you aren't needed while it does.
|
|
37
37
|
|
|
38
|
-
**5. Otherwise, `/compact`.** Relevant context, same harness, same directory, and you need to stay in the loop
|
|
38
|
+
**5. Otherwise, `/compact`.** Relevant context, same harness, same directory, and you need to stay in the loop: this is where the tree lands, and it lands here often. Pass it an instruction (`/compact we're going to QA this area`) so the summary keeps what the next phase needs.
|
|
39
39
|
|
|
40
40
|
`/compact` is the **default, not the first reach**. It sits at the bottom because the four questions above it are all cheaper or more precise. The failure mode when people start here is a fresh session that is confidently wrong about a decision the summary flattened.
|
|
41
41
|
|
|
42
42
|
## Primary and secondary sources
|
|
43
43
|
|
|
44
|
-
Every move except **Continue** turns a **primary source** into a **secondary source
|
|
44
|
+
Every move except **Continue** turns a **primary source** into a **secondary source**: the session as it happened, replaced by a summary of it. The trade is always the same shape:
|
|
45
45
|
|
|
46
46
|
| Source | Information | Noise | Room to move |
|
|
47
47
|
| --------------------------------- | ----------- | ----- | ------------ |
|
|
48
48
|
| Primary (Continue) | Full | Lots | Little |
|
|
49
|
-
| Secondary (`/compact`, [handoff](handoff.md)) | Lossy | Less | Lots |
|
|
49
|
+
| Secondary (`/compact`, [handoff](../procedures/handoff.md)) | Lossy | Less | Lots |
|
|
50
50
|
|
|
51
51
|
This is why question 1 comes first. You only pay the lossiness when staying costs more than it saves.
|
|
52
52
|
|
|
53
53
|
## These are judgement calls
|
|
54
54
|
|
|
55
|
-
The questions are not objective
|
|
55
|
+
The questions are not objective: each has taste in it, and the same boundary can go two ways on two days. The value is in asking them **in order**, at the boundary rather than in the middle of the work.
|