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.
Files changed (70) hide show
  1. package/ARCHITECTURE.zh-CN.md +37 -19
  2. package/README.md +80 -13
  3. package/package.json +12 -7
  4. package/procedures/code-review.md +25 -17
  5. package/procedures/codebase-design.md +11 -10
  6. package/procedures/deslop.md +4 -2
  7. package/procedures/diagnosing-bugs.md +25 -25
  8. package/procedures/domain-modeling.md +18 -20
  9. package/procedures/grill-me.md +1 -1
  10. package/procedures/grill-with-docs.md +1 -1
  11. package/procedures/grilling.md +29 -5
  12. package/procedures/handoff.md +1 -1
  13. package/procedures/implement.md +7 -1
  14. package/procedures/improve-codebase-architecture.md +22 -22
  15. package/procedures/pr.md +169 -0
  16. package/procedures/prototype.md +7 -6
  17. package/procedures/research.md +2 -2
  18. package/procedures/retro.md +42 -0
  19. package/procedures/setup-matt-pocock-skills.md +26 -22
  20. package/procedures/tdd.md +17 -15
  21. package/procedures/teach.md +11 -7
  22. package/procedures/to-questionnaire.md +7 -5
  23. package/procedures/to-spec.md +2 -2
  24. package/procedures/to-tickets.md +12 -12
  25. package/procedures/triage.md +22 -22
  26. package/procedures/wait-what.md +1 -1
  27. package/procedures/wayfinder.md +24 -24
  28. package/procedures/wizard.md +7 -7
  29. package/procedures/writing-for-agents.md +14 -14
  30. package/{procedures → references}/ADR-FORMAT.md +11 -11
  31. package/{procedures → references}/AGENT-BRIEF.md +4 -4
  32. package/{procedures → references}/DEEPENING.md +3 -3
  33. package/{procedures → references}/DESIGN-IT-TWICE.md +7 -7
  34. package/{procedures → references}/GLOSSARY-FORMAT.md +9 -2
  35. package/{procedures → references}/HTML-REPORT.md +15 -15
  36. package/{procedures → references}/LEARNING-RECORD-FORMAT.md +10 -10
  37. package/{procedures → references}/LOGIC.md +5 -5
  38. package/{procedures → references}/MISSION-FORMAT.md +2 -2
  39. package/{procedures → references}/OUT-OF-SCOPE.md +11 -11
  40. package/{procedures → references}/RESOURCES-FORMAT.md +1 -1
  41. package/{procedures → references}/SKILL-MECHANICS.md +3 -3
  42. package/{procedures → references}/UI.md +14 -14
  43. package/{procedures → references}/bdd-best-practices.md +3 -3
  44. package/{procedures → references}/bdd.md +9 -9
  45. package/{procedures → references}/domain.md +12 -12
  46. package/references/issue-tracker-github.md +50 -0
  47. package/{procedures → references}/issue-tracker-gitlab.md +9 -9
  48. package/{procedures → references}/issue-tracker-local.md +3 -3
  49. package/{procedures → references}/phase-boundaries.md +8 -8
  50. package/src/catalog.json +49 -28
  51. package/src/catalog.ts +58 -2
  52. package/src/index.ts +521 -383
  53. package/src/native-dialog.ts +149 -213
  54. package/src/resolver.ts +30 -14
  55. package/src/workflow.ts +55 -16
  56. package/upstream/UPSTREAM.md +116 -0
  57. package/{scripts → upstream}/check-upstream-sync.mjs +12 -12
  58. package/{upstream-selection.json → upstream/upstream-selection.json} +9 -7
  59. package/UPSTREAM.md +0 -63
  60. package/procedures/CONTEXT-FORMAT.md +0 -60
  61. package/procedures/issue-tracker-github.md +0 -45
  62. /package/{procedures → assets}/hitl-loop.template.sh +0 -0
  63. /package/{procedures → assets}/template.sh +0 -0
  64. /package/{procedures → references}/GLOSSARY.md +0 -0
  65. /package/{procedures → references}/gherkin-guide.md +0 -0
  66. /package/{procedures → references}/mocking.md +0 -0
  67. /package/{procedures → references}/testing-anti-patterns.md +0 -0
  68. /package/{procedures → references}/tests.md +0 -0
  69. /package/{procedures → references}/triage-labels.md +0 -0
  70. /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** — `(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.
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 `pnpm run <prototype-name>` or equivalent — never need to remember a path.
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 — what to teach next, which resources to surface, which exercises to design — should trace back to this document.
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 — don't leave a stale mission steering future sessions.
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** — 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
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 — 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.
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 — not "we don't want this" but why. Good reasons reference:
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") — those aren't real rejections, they're deferrals.
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 — "night theme" matches `dark-mode.md`
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** — 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
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 — a rejected PR is recorded here so the same request doesn't return as fresh code.
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 — they're historical records
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](./teach.md). It is fine for a resource to appear in only one group.
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 — 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.
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 — 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.
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 — strongly prefer sub-shape A
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** — 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.
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 — adjustment to an existing page (preferred)
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 — a new page (last resort)
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 — e.g. an entirely new top-level surface, or a flow that can't be embedded anywhere sensible.
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** — 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.
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** — 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).
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 — gate on `process.env.NODE_ENV !== 'production'` or an equivalent check, so a stray prototype merge can't ship the bar to users.
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** — 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.
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 — the question is "what should this look like", not "does the backend work".
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](./gherkin-guide.md).
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 `CONTEXT.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.
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
- - **`CONTEXT.md`** at the repo root, or
8
- - **`CONTEXT-MAP.md`** at the repo root if it exists — it points at one `CONTEXT.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.
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
- ├── CONTEXT.md
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 `CONTEXT-MAP.md` at the root):
26
+ Multi-context repo (presence of `GLOSSARY-MAP.md` at the root):
27
27
 
28
28
  ```
29
29
  /
30
- ├── CONTEXT-MAP.md
30
+ ├── GLOSSARY-MAP.md
31
31
  ├── docs/adr/ ← system-wide decisions
32
32
  └── src/
33
33
  ├── ordering/
34
- │ ├── CONTEXT.md
34
+ │ ├── GLOSSARY.md
35
35
  │ └── docs/adr/ ← context-specific decisions
36
36
  └── billing/
37
- ├── CONTEXT.md
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 `CONTEXT.md`. Don't drift to synonyms the glossary explicitly avoids.
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) — but worth reopening because…_
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. — the same shape as `gh pr ...` with `mr` in place of `pr` and `note`/`--message` in place of `comment`/`--body`.
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` — `glab` does this automatically when run inside a clone.
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 -F json`, then keep only MRs whose author is not a project member/owner (a contributor's MR, not a maintainer's in-flight work).
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** — 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**: `glab issue list -F json` scoped to the map's children, drop any with an open blocker — a native `blocked_by` link to an open issue (`glab api projects/:id/issues/: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.
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` — never a single combined tickets file
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` — the Notes / Decisions-so-far / Fog body.
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 — the grilling, the implementation, the QA. The definition is fuzzy on purpose: a phase ends when you think *"ok, we're done with that"*.
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 — 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.
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** — the session as it happened, replaced by a summary of it. The trade is always the same shape:
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 — 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.
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.