Compare commits
2 Commits
07e846f0a6
...
bb341d3c87
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb341d3c87 | ||
|
|
67c6a8165d |
@ -45,6 +45,7 @@ rules:
|
|||||||
| BDR-022 | 2026-06-18 | doc-syncer scoped to public docs; `.claude/` + `CLAUDE.md` read-only context, never targets; conventions + clean mode | accepted |
|
| BDR-022 | 2026-06-18 | doc-syncer scoped to public docs; `.claude/` + `CLAUDE.md` read-only context, never targets; conventions + clean mode | accepted |
|
||||||
| BDR-023 | 2026-06-19 | Merge /close into /capitalize — 2 modes + TODO reconcile; /close alias | accepted |
|
| BDR-023 | 2026-06-19 | Merge /close into /capitalize — 2 modes + TODO reconcile; /close alias | accepted |
|
||||||
| BDR-034 | 2026-06-26 | Coupled-capitalize invariant v1 — memory commit auto per dev flow (Frame 2) | accepted |
|
| BDR-034 | 2026-06-26 | Coupled-capitalize invariant v1 — memory commit auto per dev flow (Frame 2) | accepted |
|
||||||
|
| BDR-035 | 2026-06-26 | Analyze-before-plan invariant v1 — read-before bookend of coupled-capitalize | accepted |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -552,3 +553,15 @@ rules:
|
|||||||
- (c) single commit chokepoint — doesn't exist; 3 distinct commit mechanisms, one external/unmodifiable (`superpowers:finishing-a-development-branch`).
|
- (c) single commit chokepoint — doesn't exist; 3 distinct commit mechanisms, one external/unmodifiable (`superpowers:finishing-a-development-branch`).
|
||||||
- Frame 3 (single unified commit, drop hash) — sacrifices >50% entries' anchoring for history aesthetics.
|
- Frame 3 (single unified commit, drop hash) — sacrifices >50% entries' anchoring for history aesthetics.
|
||||||
- **Reference**: commits `58cb91d` (helper+tests) · `bbef41c` (hash/stdout + T6/T7) · `b44791b` (include) · `2763678` (4 flows) · `e8eff7e` (ship-feature reorder) · `df60df6` (init-project). Hook (v2, Stop-hook non-blocking BDR-033-style) + doc-sync twin chantier (same PR bug, reorder before FINISH) deferred. See [[LRN-051]], [[LRN-052]], [[EVAL-007]].
|
- **Reference**: commits `58cb91d` (helper+tests) · `bbef41c` (hash/stdout + T6/T7) · `b44791b` (include) · `2763678` (4 flows) · `e8eff7e` (ship-feature reorder) · `df60df6` (init-project). Hook (v2, Stop-hook non-blocking BDR-033-style) + doc-sync twin chantier (same PR bug, reorder before FINISH) deferred. See [[LRN-051]], [[LRN-052]], [[EVAL-007]].
|
||||||
|
|
||||||
|
## BDR-035 — Analyze-before-plan invariant v1 — read-before bookend of coupled-capitalize
|
||||||
|
|
||||||
|
- **Date**: 2026-06-26
|
||||||
|
- **Status**: accepted
|
||||||
|
- **Decision**: Dev flows now READ related memory before planning (ship-feature also reads related code), mirroring how [[BDR-034]] made them WRITE memory after. Shared include `lib/analyze-before-plan.md` (tête-bêche of `lib/capitalize-commit.md`). Invariant = DISPOSITION, not reading: the plan must NAME each surfaced ID (in-force / already-seen / non-binding) — a verifiable trace in the artifact, not "did it look". Two-pass: grep `## <PREFIX>-` body headings → select on titles → full-read only the selected bodies. Wiring: ship-feature STEP 0d (analyzer subagent code+memory, fed to brainstorm/plan by INPUT INJECTION + STEP 3 reconciliation gate); bugfix STEP 2.5 (blockers-first); feat STEP 0.6 (decisions-first, MINI-PLAN names in-force or states none); hotfix opt-in blockers-only; init-project + onboard = no-op exceptions. Guarded no-op (`[ -d .claude/memory ]`).
|
||||||
|
- **Why**: coupled-capitalize gave every flow a write-after; NO flow read the memory it feeds — bookend half-open. A bugfix wrote BLK at the end but never checked blockers.md for the same root cause already solved. Closes Gap B (memory, universal) + Gap A (code, ship-feature — the lone cold-planner).
|
||||||
|
- **Alternatives rejected**:
|
||||||
|
- Index two-pass — `## Index` drifted on this mature repo (decisions 11/34, learnings 21/52, blockers 2/9 missing) in scattered blocks → an Index-based selector silently misses a large unpredictable fraction. Body headings drift-immune (100% coverage). See [[LRN-055]].
|
||||||
|
- Extend analyzer only — inline flows (feat/bugfix/hotfix) never call analyzer pre-plan → would close Gap B for none. Needed both: include + analyzer RELATED MEMORY section.
|
||||||
|
- PASS-2 skip-if-already-in-context — no deterministic oracle for "in context"; reintroduces the behavioral guard. See [[LRN-054]].
|
||||||
|
- **Reference**: commit `67c6a81`, `lib/analyze-before-plan.md`, `agents/analyzer.md`. Bookend of [[BDR-034]]. See [[LRN-053]], [[LRN-054]], [[LRN-055]], [[LRN-056]], [[LRN-057]].
|
||||||
|
|||||||
@ -206,3 +206,4 @@ rules:
|
|||||||
- Coupled-capitalize invariant v1: dev flows auto-commit memory via include `lib/capitalize-commit.md` + helper `lib/memory-commit.sh` (surgical pathspec, never `-A`; hash→stdout). Frame 2 (après-code-couplé, hash-anchoring kept, 2 commits, memory commit automatic per flow). 6 commits `58cb91d..df60df6`. BDR-034, LRN-051/052, EVAL-007.
|
- Coupled-capitalize invariant v1: dev flows auto-commit memory via include `lib/capitalize-commit.md` + helper `lib/memory-commit.sh` (surgical pathspec, never `-A`; hash→stdout). Frame 2 (après-code-couplé, hash-anchoring kept, 2 commits, memory commit automatic per flow). 6 commits `58cb91d..df60df6`. BDR-034, LRN-051/052, EVAL-007.
|
||||||
- Caught `git commit -- pathspec` strict-on-no-match by real-exec test (would silent-abort on majority of flows) → `_changed_paths` filter (LRN-051). ship-feature reordered CAPITALIZE→before FINISH (fixes memory stranded outside PR). init-project STEP 10b founding decisions (no hash by nature, LRN-052). Hook v2 + doc-sync twin chantier deferred.
|
- Caught `git commit -- pathspec` strict-on-no-match by real-exec test (would silent-abort on majority of flows) → `_changed_paths` filter (LRN-051). ship-feature reordered CAPITALIZE→before FINISH (fixes memory stranded outside PR). init-project STEP 10b founding decisions (no hash by nature, LRN-052). Hook v2 + doc-sync twin chantier deferred.
|
||||||
- TDD: 13 deterministic + in-vivo e2e, shellcheck clean (EVAL-007). Pre-existing Index drift (decisions 11, learnings 21 rows missing) noted for /prune-memory — not backfilled here.
|
- TDD: 13 deterministic + in-vivo e2e, shellcheck clean (EVAL-007). Pre-existing Index drift (decisions 11, learnings 21 rows missing) noted for /prune-memory — not backfilled here.
|
||||||
|
- analyze-before-plan v1 — read-before bookend of coupled-capitalize. Include `lib/analyze-before-plan.md` (two-pass on `## ID` headings, disposition-not-reading invariant, guarded no-op). Wired: ship-feature 0d (inject+reconcile gate), bugfix 2.5, feat 0.6, hotfix opt-in; init/onboard no-op (test-backed). Index drift measured exact: decisions 11/34, learnings 21/52, blockers 2/9. Code commit 67c6a81. BDR-035, LRN-053/054/055/056/057.
|
||||||
|
|||||||
@ -51,6 +51,11 @@ rules:
|
|||||||
| LRN-048 | 2026-06-25 | A "0/OK/pass" must prove it LOOKED (counted both sides), else verify hard-wired to pass | any verify/test/lint reporting success |
|
| LRN-048 | 2026-06-25 | A "0/OK/pass" must prove it LOOKED (counted both sides), else verify hard-wired to pass | any verify/test/lint reporting success |
|
||||||
| LRN-051 | 2026-06-26 | `git commit -- pathspec` strict on no-match → filter scoped commits to changed paths | any scoped-commit automation |
|
| LRN-051 | 2026-06-26 | `git commit -- pathspec` strict on no-match → filter scoped commits to changed paths | any scoped-commit automation |
|
||||||
| LRN-052 | 2026-06-26 | Hash-anchoring: 2 cases it does NOT apply (pre-code founding, squash-merge) | capitalizing founding/arch decisions; squash repos |
|
| LRN-052 | 2026-06-26 | Hash-anchoring: 2 cases it does NOT apply (pre-code founding, squash-merge) | capitalizing founding/arch decisions; squash repos |
|
||||||
|
| LRN-053 | 2026-06-26 | Read-before teeth = verifiable disposition in the artifact, not the act of reading | any read-before / check-before wiring |
|
||||||
|
| LRN-054 | 2026-06-26 | No deterministic oracle for "already in context" → never add a presence-skip branch | skip-if-seen optimizations over conversation state |
|
||||||
|
| LRN-055 | 2026-06-26 | Body `## ID —` headings = drift-immune index; the `## Index` table is not | choosing a substrate to index/select over |
|
||||||
|
| LRN-056 | 2026-06-26 | `grep PAT dir/*.md` on absent dir ERRORS (exit 2), not no-op → guard `[ -d ]` | any glob-fed scan that must no-op on nothing |
|
||||||
|
| LRN-057 | 2026-06-26 | Match consumption mechanism to consumer (mechanical / external-cognitive / inline) | wiring any produce→consume invariant |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -661,3 +666,43 @@ rules:
|
|||||||
- **Context**: building init-project STEP 10b (capitalize founding architecture decisions). A founding "Astro not Next" has no implementing commit. Surfaced the BOUNDARY of the anchoring convention — completes it, not contradicts it.
|
- **Context**: building init-project STEP 10b (capitalize founding architecture decisions). A founding "Astro not Next" has no implementing commit. Surfaced the BOUNDARY of the anchoring convention — completes it, not contradicts it.
|
||||||
- **Future application**: capitalizing founding/architecture decisions, or working in squash-merge repos — do NOT fabricate a hash; the anchor only means something when a real implementing commit exists.
|
- **Future application**: capitalizing founding/architecture decisions, or working in squash-merge repos — do NOT fabricate a hash; the anchor only means something when a real implementing commit exists.
|
||||||
- **Reference**: commit `df60df6` (init-project STEP 10b hash rule), `lib/capitalize-commit.md` (2-hash non-confusion). See [[BDR-034]], [[BDR-033]].
|
- **Reference**: commit `df60df6` (init-project STEP 10b hash rule), `lib/capitalize-commit.md` (2-hash non-confusion). See [[BDR-034]], [[BDR-033]].
|
||||||
|
|
||||||
|
## LRN-053 — Read-before teeth = verifiable disposition in the artifact, not the act of reading
|
||||||
|
|
||||||
|
- **Date**: 2026-06-26
|
||||||
|
- **Pattern**: An "always read X before planning" invariant guarantees NOTHING by the read alone — "ran before the plan" proves the digest was PRODUCED, not CONSUMED. The teeth are a verifiable DISPOSITION: the plan/diagnosis must NAME each surfaced item it honors, or state none binds. [[LRN-048]] ("a 0/OK must prove it LOOKED") one step further — the guarantee is "did it STATE a verdict on each?" (checkable), not "did it look?" (not). Without the trace, even natural consumption (inline reader=planner) degrades to read-then-ignore.
|
||||||
|
- **Context**: analyze-before-plan ([[BDR-035]]). feat's first draft ("feed the MINI-PLAN") had no forced trace → user flagged it as the link where wiring goes cosmetic; strengthened to "MINI-PLAN names in-force or states none". bugfix DIAGNOSIS names `PRIOR: BLK-xxx`.
|
||||||
|
- **Future application**: any read-before / check-before / advisory wiring — force the consuming artifact to emit a per-item verdict; never trust "data was available" = "data was used".
|
||||||
|
- **Reference**: `lib/analyze-before-plan.md` (OUTPUT), `agents/feater.md` STEP 0.6, `agents/bugfixer.md` STEP 2.5. Extends [[LRN-048]]. See [[BDR-035]].
|
||||||
|
|
||||||
|
## LRN-054 — No deterministic oracle for "already in context" → never add a presence-skip branch
|
||||||
|
|
||||||
|
- **Date**: 2026-06-26
|
||||||
|
- **Pattern**: "Skip the work if the info is already in my context" has no clean implementation: (1) self-judgment = the behavioral guard [[LRN-046]] rejects, unreliable on long convos ([[LRN-034]]); (2) a session marker records "was read", NOT "still present" → after a compaction the body is gone but the marker says skip → FALSE-SKIP (the marker cost [[BDR-033]] priced); (3) the agent cannot grep its own context window. No presence oracle exists. Do the work unconditionally when cheap; bite on the verifiable disposition.
|
||||||
|
- **Context**: analyze-before-plan ([[BDR-035]]). Tried to skip PASS-2 full-read for "already in context" entries; predicate had no oracle. Resolved: PASS-2 reads selected set unconditionally (~tens of transient lines, digest-only persists). A decision WRITTEN earlier same-conversation must still re-surface as in-force (content in context ≠ flow treated it as a constraint).
|
||||||
|
- **Future application**: any "skip if already seen/in-context" optimization over conversation state — reject; no oracle. Make the work cheap+unconditional, or use a deterministic EXTERNAL ledger (not context introspection).
|
||||||
|
- **Reference**: `lib/analyze-before-plan.md` (THE INVARIANT). Conditions [[LRN-046]], [[LRN-034]], [[BDR-033]]. See [[BDR-035]].
|
||||||
|
|
||||||
|
## LRN-055 — Body `## ID —` headings are a drift-immune index; the maintained `## Index` table is not
|
||||||
|
|
||||||
|
- **Date**: 2026-06-26
|
||||||
|
- **Pattern**: When a registry keeps both per-entry `## ID — title` headings AND a hand-maintained `## Index` table, the Index DRIFTS (entries land in the body, the manual update lapses) while headings cannot (an entry IS its heading — 100% coverage by construction). Measured: decisions 11/34 (32%), learnings 21/52 (40%), blockers 2/9 (22%) missing from the Index — scattered in large blocks (e.g. decisions BDR-024–033 unindexed while the newer BDR-034 is), not an old/new split. The manual Index-update step is simply unreliable. Key any selector/scan off `grep '^## <PREFIX>-'`, never the convenience Index. Backfill (prune-memory passe D) = human-TOC hygiene, NOT a selector dependency.
|
||||||
|
- **Context**: analyze-before-plan ([[BDR-035]]) two-pass. First instinct "reuse the Index capitalize maintains"; measuring the drift killed it — the convenient artifact was the unreliable one, the guaranteed one (headings) sat free.
|
||||||
|
- **Future application**: choosing a substrate to index/select over — prefer what the STRUCTURE guarantees over what a step PROMISES to maintain. Verify maintained-artifact completeness before depending on it.
|
||||||
|
- **Reference**: `lib/analyze-before-plan.md` (PASS 1). `skills/prune-memory` passe D. See [[BDR-035]].
|
||||||
|
|
||||||
|
## LRN-056 — `grep PAT dir/*.md` on an absent dir ERRORS (exit 2), it does not no-op → guard with `[ -d ]`
|
||||||
|
|
||||||
|
- **Date**: 2026-06-26
|
||||||
|
- **Pattern**: A bare `grep -E PAT dir/*.md` over a glob matching nothing (dir absent, or present with no `.md`) does NOT return clean-empty — the unmatched glob is passed LITERALLY to grep, which fails: `No such file or directory`, **exit 2** (grep error). Distinct from a real no-match: grep over an existing file with no hit = **exit 1**. Verified: bare grep on absent dir → 2; `[ -d dir ] && ls dir/*.md >/dev/null 2>&1 && grep …` on absent dir → 1 (`[ -d ]` false, short-circuits, grep never runs); grep on present-but-empty registry → 1. exit 2 = grep error; exit 1 = guard-skip OR clean no-match.
|
||||||
|
- **Context**: analyze-before-plan include ([[BDR-035]]). DO step said "absent → no-op" but the bare grep would ERROR at init-project STEP 2 (registries created STEP 5, absent at analyze). Caught by exec-test, not assumption.
|
||||||
|
- **Future application**: any glob-fed scan that must no-op on "nothing there" — guard `[ -d dir ]` (+ file-exists) BEFORE the glob; never assume grep degrades. Exec-test the absent/empty case.
|
||||||
|
- **Reference**: `lib/analyze-before-plan.md` (PASS 1 guard). Sibling to [[LRN-051]] (exec-test tool behavior, never assume). See [[BDR-035]].
|
||||||
|
|
||||||
|
## LRN-057 — Match the consumption mechanism to the consumer (mechanical / external-cognitive / inline-cognitive)
|
||||||
|
|
||||||
|
- **Date**: 2026-06-26
|
||||||
|
- **Pattern**: When a produced artifact must be CONSUMED downstream, the mechanism depends on the consumer: (a) MECHANICAL (git merge integrating a branch) — production on the shared substrate = consumption, automatic ([[BDR-034]]'s "commit before FINISH"); (b) EXTERNAL-COGNITIVE (an unmodifiable skill like `superpowers:brainstorming`) — "produced before" ≠ "consumed"; INJECT the artifact into the consumer's INPUT at the invocation boundary (orchestrator = adapter) + a RECONCILIATION gate that EXPOSES the disposition for review (not auto-detect); (c) INLINE-COGNITIVE (same agent reads then plans) — reader=planner, same context → natural consumption, just force the trace ([[LRN-053]]). Don't import (b)'s machinery where (c) suffices, nor assume (a)'s automatism when the consumer is cognitive.
|
||||||
|
- **Context**: analyze-before-plan ([[BDR-035]]). ship-feature brainstorm = external-cognitive → STEP 0d injection + STEP 3 expose-for-review gate; feat/bugfix = inline-cognitive → natural + trace, no injection. The asymmetry vs [[BDR-034]] (mechanical merge) was the chantier's hardest point.
|
||||||
|
- **Future application**: wiring ANY produce→consume invariant — classify the consumer first (mechanical / external-cognitive / inline-cognitive), pick the lightest sufficient mechanism. Stops reflexively importing orchestrator-grade injection+gate where an inline trace would do.
|
||||||
|
- **Reference**: `skills/ship-feature/SKILL.md` STEP 0d/1/2/3, `agents/bugfixer.md`+`feater.md`. Contrast [[BDR-034]] (mechanical). See [[BDR-035]], [[LRN-053]].
|
||||||
|
|||||||
@ -64,6 +64,12 @@ RISKS:
|
|||||||
|
|
||||||
OPEN QUESTIONS:
|
OPEN QUESTIONS:
|
||||||
- <ambiguity to clarify>
|
- <ambiguity to clarify>
|
||||||
|
|
||||||
|
RELATED MEMORY:
|
||||||
|
- IN FORCE: <id> — <title> — <how it constrains this work> [status] (detail each)
|
||||||
|
- ALREADY SEEN: <BLK-id> — <title> [status] (known cause/fix — don't re-derive)
|
||||||
|
- NON-BINDING: <c> surfaced, none binding — <bare id refs> (superseded / N-A — counted)
|
||||||
|
- SELECTION: scanned <N> headings — surfaced <K> = in-force <a> + seen <b> + non-binding <c>
|
||||||
```
|
```
|
||||||
|
|
||||||
Surface discovered patterns and conventions in the analysis output
|
Surface discovered patterns and conventions in the analysis output
|
||||||
@ -73,6 +79,26 @@ happens in the main thread via the gated capitalize flow.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## RELATED MEMORY (read-before)
|
||||||
|
|
||||||
|
When `.claude/memory/` exists and holds entries, run the memory-relevance scan per
|
||||||
|
`$HOME/.claude/lib/analyze-before-plan.md` (PASS 1: grep `## <PREFIX>-` headings →
|
||||||
|
select on titles → PASS 2: full-read only the selected bodies) and populate the
|
||||||
|
RELATED MEMORY section of OUTPUT.
|
||||||
|
|
||||||
|
The contract is DISPOSITION, not retrieval: every surfaced ID gets a verdict —
|
||||||
|
in-force / already-seen / non-binding. Detail the binding ones (IN FORCE, ALREADY SEEN —
|
||||||
|
they constrain the work); COUNT the non-binding (superseded / N-A) as one line with bare
|
||||||
|
refs — a per-entry paragraph on a non-binding match dilutes the in-force ones that bite.
|
||||||
|
A surfaced ID left undisposed is the gap this closes. You judge bearing; the main-thread
|
||||||
|
plan decides what to DO.
|
||||||
|
|
||||||
|
Read-only here too: reading registries is within Read/Grep; the "Do not modify files" rule
|
||||||
|
still forbids any write — Index backfill or new entries are never your job. Empty or absent
|
||||||
|
registries → omit the section (no-op).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## EDGE CASES
|
## EDGE CASES
|
||||||
|
|
||||||
| Situation | Action |
|
| Situation | Action |
|
||||||
|
|||||||
@ -60,6 +60,18 @@ Trace the bug from symptom to root cause:
|
|||||||
# grep for the same pattern to assess blast radius
|
# grep for the same pattern to assess blast radius
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## STEP 2.5 — MEMORY READ-BEFORE (blockers-first)
|
||||||
|
|
||||||
|
Run the scan per `$HOME/.claude/lib/analyze-before-plan.md`, blockers-weighted: a resolved
|
||||||
|
BLK may already name THIS exact root cause; an in-force BDR may constrain the fix. Emit
|
||||||
|
RELATED MEMORY. Consumption is NATURAL — the agent emitting this IS the one writing STEP 3's
|
||||||
|
diagnosis (reader = planner, no external skill to inject into).
|
||||||
|
|
||||||
|
TEETH: STEP 3's DIAGNOSIS must name any binding prior (`PRIOR: BLK-xxx — known cause/fix`,
|
||||||
|
or `honors BDR-xxx`) OR the RELATED MEMORY line states none bears. Reading blockers then
|
||||||
|
diagnosing without naming a match is the read-then-ignore failure this prevents.
|
||||||
|
`.claude/memory/` absent → guarded no-op, proceed.
|
||||||
|
|
||||||
## STEP 3 — HYPOTHESIZE + PLAN
|
## STEP 3 — HYPOTHESIZE + PLAN
|
||||||
|
|
||||||
Present findings before fixing:
|
Present findings before fixing:
|
||||||
|
|||||||
@ -58,6 +58,13 @@ Follow `$HOME/.claude/lib/design-gate.md`:
|
|||||||
tell the user to run `/profile design` before proceeding.
|
tell the user to run `/profile design` before proceeding.
|
||||||
- If no signals → skip (zero overhead).
|
- If no signals → skip (zero overhead).
|
||||||
|
|
||||||
|
## STEP 0.6 — MEMORY READ-BEFORE (decisions-first)
|
||||||
|
|
||||||
|
Run the scan per `$HOME/.claude/lib/analyze-before-plan.md`, decisions-weighted: a BDR may
|
||||||
|
already constrain or forbid the approach; an LRN may name a gotcha to apply. Emit RELATED
|
||||||
|
MEMORY; feed STEP 1 MINI-PLAN. Inline consumption — reader = planner, no injection.
|
||||||
|
`.claude/memory/` absent → guarded no-op (zero overhead on a memory-less repo).
|
||||||
|
|
||||||
## STEP 1 — MINI-PLAN
|
## STEP 1 — MINI-PLAN
|
||||||
|
|
||||||
Quick mental model, not a formal plan document:
|
Quick mental model, not a formal plan document:
|
||||||
@ -66,6 +73,9 @@ Quick mental model, not a formal plan document:
|
|||||||
2. Describe the approach in 2-5 bullet points.
|
2. Describe the approach in 2-5 bullet points.
|
||||||
3. Note any edge cases to handle.
|
3. Note any edge cases to handle.
|
||||||
4. If tests exist for the area, note which tests to add/update.
|
4. If tests exist for the area, note which tests to add/update.
|
||||||
|
5. Disposition (from STEP 0.6): name each in-force BDR/LRN this plan honors
|
||||||
|
(`honors BDR-xxx by …`), or state `no in-force decision constrains this feature`.
|
||||||
|
A plan with neither = read-then-ignore; the disposition must surface as a trace.
|
||||||
|
|
||||||
Print the plan as a compact checklist:
|
Print the plan as a compact checklist:
|
||||||
```
|
```
|
||||||
|
|||||||
@ -31,6 +31,14 @@ git log --oneline -3
|
|||||||
"This looks deeper than a hotfix. Load `$HOME/.claude/agents/bugfixer.md`
|
"This looks deeper than a hotfix. Load `$HOME/.claude/agents/bugfixer.md`
|
||||||
and run the BUGFIXER agent on this target."
|
and run the BUGFIXER agent on this target."
|
||||||
|
|
||||||
|
OPTIONAL — memory check (exempt by default; hotfix = obvious fix, mirror of its capitalize
|
||||||
|
skip). For a RECURRING or urgent bug only, a quick blockers-only glance may save time:
|
||||||
|
|
||||||
|
[ -d .claude/memory ] && grep -nE '^## BLK-' .claude/memory/blockers.md # "déjà vu ?"
|
||||||
|
|
||||||
|
If a prior BLK names this bug, jump to its solution. Not mandatory; no RELATED MEMORY
|
||||||
|
disposition required at hotfix weight.
|
||||||
|
|
||||||
## STEP 1.5 — DESIGN GATE
|
## STEP 1.5 — DESIGN GATE
|
||||||
|
|
||||||
Follow `$HOME/.claude/lib/design-gate.md`:
|
Follow `$HOME/.claude/lib/design-gate.md`:
|
||||||
|
|||||||
123
lib/analyze-before-plan.md
Normal file
123
lib/analyze-before-plan.md
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
# ANALYZE-BEFORE-PLAN — couple the memory read to the dev flow
|
||||||
|
|
||||||
|
Inline snippet. Include at the START of a dev flow, BEFORE the plan forms. This is the
|
||||||
|
HEAD of analyze; `capitalize-commit.md` is the TAIL. Read-before / write-after — the two
|
||||||
|
ends of one bookend: a flow consults the decisions / blockers / learnings it will later add to.
|
||||||
|
|
||||||
|
It does NOT decide the plan. It hands the planner a DISPOSED list of prior entries that
|
||||||
|
bear on the work, so the plan cannot form blind to a decision already in force or a
|
||||||
|
blocker already solved.
|
||||||
|
|
||||||
|
## WHEN TO RUN
|
||||||
|
|
||||||
|
- Inline flow (feat / bugfix): main thread, AFTER the related code is read, BEFORE the
|
||||||
|
mini-plan / diagnosis. PASS 2 is bounded-tiny (selection narrows it); no subagent —
|
||||||
|
preserves stay-light.
|
||||||
|
- Orchestrator with a code-analysis step (ship-feature / init-project): run it INSIDE the
|
||||||
|
analyzer subagent. Its fresh context reads code + memory with zero redundancy against
|
||||||
|
the main thread; only its compact digest returns. The analyzer's RELATED MEMORY output
|
||||||
|
section IS this snippet's OUTPUT.
|
||||||
|
- hotfix: not wired by default (mirror of its capitalize skip). Available opt-in for a
|
||||||
|
blockers-only quick check ("urgent bug déjà vu ?").
|
||||||
|
|
||||||
|
## DO
|
||||||
|
|
||||||
|
1. PRECONDITION — NO-OP unless `.claude/memory/` exists AND holds at least one registry
|
||||||
|
file. TESTED reality: a bare `grep … .claude/memory/*.md` on an ABSENT dir (or a dir
|
||||||
|
with no `.md`) does NOT no-op — the unmatched glob is passed literally and grep ERRORS
|
||||||
|
(`No such file or directory`, exit 2). So the GUARD makes "absent → no-op", never the
|
||||||
|
grep. This is init-project's STEP 2 reality: the registries are created at STEP 5, so at
|
||||||
|
analyze time they are ABSENT — the guard must fire on absent, not merely on empty.
|
||||||
|
|
||||||
|
2. PASS 1 — list every entry, drift-proof, GUARDED:
|
||||||
|
|
||||||
|
[ -d .claude/memory ] && ls .claude/memory/*.md >/dev/null 2>&1 \
|
||||||
|
&& grep -nE '^## (BDR|LRN|BLK|EVAL)-[0-9]+' .claude/memory/*.md
|
||||||
|
|
||||||
|
One `ID — title` line per entry, for 100% of entries by construction (an entry IS its
|
||||||
|
heading). A present-but-template-empty registry (header only) → grep exits 1 (clean
|
||||||
|
no-match) → no-op naturally; only the ABSENT / no-file case needed the guard. The REGEX
|
||||||
|
is the filter, not the file list: the glob also reads journal.md (date-keyed
|
||||||
|
`## YYYY-MM-DD`) and any non-entry file, which contribute zero matches — no need to
|
||||||
|
exclude them. Do NOT read the `## Index` table: it drifts (entries land in the body, the
|
||||||
|
manual Index update lapses — measured 32-40% missing on a mature repo); headings cannot.
|
||||||
|
|
||||||
|
3. SELECT — IDs whose title bears on $REQUEST. Judge on titles (one dense line each), not
|
||||||
|
on bodies. Over-inclusion is SAFE: an entry that proves non-binding costs one bare ref
|
||||||
|
in OUTPUT, not a paragraph (see DISPOSITION) — so err toward including on a dense cluster.
|
||||||
|
|
||||||
|
4. PASS 2 — full-read ONLY the selected bodies (heading to next `##`) to recover
|
||||||
|
status / why / solution / alternatives. Unconditional for the selected set — see THE
|
||||||
|
INVARIANT for why there is no "skip if already in context" branch.
|
||||||
|
|
||||||
|
5. DISPOSE — emit RELATED MEMORY (OUTPUT). Every surfaced ID gets a verdict.
|
||||||
|
|
||||||
|
## OUTPUT — RELATED MEMORY (disposition, not a dump)
|
||||||
|
|
||||||
|
RELATED MEMORY (read-before):
|
||||||
|
IN FORCE — must constrain this work (detail each — they bite):
|
||||||
|
- BDR-026 — <title> — <how it constrains> [accepted]
|
||||||
|
- LRN-050 — <title> — <how it applies>
|
||||||
|
ALREADY SEEN — known cause/fix, don't re-derive (detail each):
|
||||||
|
- BLK-009 — <title> [upstream]
|
||||||
|
NON-BINDING — superseded / N-A, COUNTED not detailed:
|
||||||
|
- <c> surfaced, none binding — BDR-013, LRN-022, … (bare refs, one line)
|
||||||
|
SELECTION: scanned <N> headings / 4 registries —
|
||||||
|
surfaced <K> = in-force <a> + seen <b> + non-binding <c>.
|
||||||
|
|
||||||
|
- Disposition rule: DETAIL what binds (IN FORCE, ALREADY SEEN); COUNT what doesn't
|
||||||
|
(NON-BINDING) as one line + bare refs. The collective verdict still disposes each
|
||||||
|
non-binding ID — its bare ref under "none binding" IS its disposition — but a per-entry
|
||||||
|
paragraph on a non-binding match dilutes the in-force ones that bite. On a dense cluster
|
||||||
|
(K up to ~14) this is what keeps the 3 that matter from drowning under 11 that don't.
|
||||||
|
- Compact even for binding ones: ID + title + one-clause bearing. Bodies were read to
|
||||||
|
JUDGE; only the disposition persists — never paste bodies into the plan.
|
||||||
|
- a + b + c = K: every surfaced ID is accounted for. An unaccounted surfaced ID is the gap
|
||||||
|
this prevents.
|
||||||
|
- Nothing bears → `RELATED MEMORY: none of <N> entries bears on this task` (still proves
|
||||||
|
PASS 1 ran — LRN-048).
|
||||||
|
|
||||||
|
## THE INVARIANT — disposition, not reading
|
||||||
|
|
||||||
|
The guarantee is NOT "the agent read the memory" (an act, unverifiable after the fact).
|
||||||
|
It is "the plan disposed of every relevant prior entry" (a list, verifiable in OUTPUT).
|
||||||
|
LRN-048 one step further: the teeth are "did it STATE a verdict on each surfaced ID?",
|
||||||
|
not "did it look?".
|
||||||
|
|
||||||
|
So there is no "skip PASS 2 if already in context" branch. "Already in context" has no
|
||||||
|
deterministic oracle: self-judgment is the rejected behavioral guard (LRN-046); a session
|
||||||
|
marker records "was read", not "still present", so it false-skips after a compaction (and
|
||||||
|
is the marker cost BDR-033 priced); the agent cannot grep its own window. PASS 2 reads the
|
||||||
|
selected set unconditionally — cheap by construction — and the invariant bites on the
|
||||||
|
disposition, which holds whether a body was freshly read or recalled.
|
||||||
|
|
||||||
|
A decision WRITTEN earlier in the same conversation (ship-feature posts BDR-035, then a
|
||||||
|
bugfix runs) MUST still be surfaced and disposed as in-force: content sitting in context
|
||||||
|
is not the current flow having TREATED it as a constraint. Re-surfacing is the feature.
|
||||||
|
|
||||||
|
## HARD RULE — read-only
|
||||||
|
|
||||||
|
Touches nothing. No write, no Index update, no memory mutation. Symmetric to
|
||||||
|
capitalize-commit's surgical scope (there: stage ONLY memory; here: stage NOTHING). Index
|
||||||
|
backfill, if ever wanted, is `/prune-memory` passe D — never this snippet.
|
||||||
|
|
||||||
|
## ORDERING (orchestrators only)
|
||||||
|
|
||||||
|
`superpowers:brainstorming` / `writing-plans` are external skills — we cannot make them
|
||||||
|
read our registries. So this runs BEFORE them, pre-loading the disposition into the plan
|
||||||
|
they form. Mirror of capitalize-commit running BEFORE finishing-a-development-branch: there
|
||||||
|
the memory commit must precede integration; here the memory read must precede planning.
|
||||||
|
|
||||||
|
## NO-OP / IDEMPOTENT
|
||||||
|
|
||||||
|
Empty or absent registries → silent no-op (greenfield init-project; onboard, which CREATES
|
||||||
|
memory and has none prior). Pure read → safe to run twice; naturally idempotent.
|
||||||
|
|
||||||
|
## WHAT THIS DOES NOT DO
|
||||||
|
|
||||||
|
- Does NOT read the related CODE — the flow does that (feat STEP 0, bugfix STEP 2). Sole
|
||||||
|
exception: ship-feature, where the analyzer subagent this runs in reads code too (Gap A).
|
||||||
|
- Does NOT decide the plan — it primes it with a disposed list of constraints.
|
||||||
|
- Does NOT write or mutate memory — read-only; capitalize (write-after) is the other bookend.
|
||||||
|
- Does NOT depend on the `## Index` table — keys off `## <PREFIX>-` headings (drift-immune).
|
||||||
|
- Does NOT skip PASS 2 on an "already in context" guess — no oracle for it; the read is cheap.
|
||||||
@ -60,19 +60,64 @@ During implementation (STEP 4), when making decisions about fast-lib APIs:
|
|||||||
- Read the relevant `.ctx7-cache/<lib>.md` file before writing code.
|
- Read the relevant `.ctx7-cache/<lib>.md` file before writing code.
|
||||||
- This avoids repeated ctx7 calls and keeps docs available without context cost.
|
- This avoids repeated ctx7 calls and keeps docs available without context cost.
|
||||||
|
|
||||||
|
## STEP 0d — ANALYZE BEFORE PLAN (code + memory, read-before)
|
||||||
|
Dispatch the analyzer subagent (fresh context) on the request — it produces the
|
||||||
|
read-before digest the plan must not form without:
|
||||||
|
|
||||||
|
Agent(subagent_type="analyzer", description="ship-feature — read-before", prompt="""
|
||||||
|
Read-only analysis to PRIME a feature plan (NOT debug). REQUEST: <$ARGUMENTS>.
|
||||||
|
1. CODE — locate the zone the feature touches: grep/glob the request's nouns /
|
||||||
|
identifiers across the tree → candidate files (PASS 1), read them (PASS 2).
|
||||||
|
>50 candidates → scoped sweep per your EDGE CASES, list zones, don't read all.
|
||||||
|
Too vague to locate → report ambiguous zones, do NOT block.
|
||||||
|
2. MEMORY — run the scan per $HOME/.claude/lib/analyze-before-plan.md, emit
|
||||||
|
RELATED MEMORY (disposed).
|
||||||
|
Output your standard ANALYSIS + RELATED MEMORY. No solutions.""")
|
||||||
|
|
||||||
|
The returned digest (ANALYSIS + RELATED MEMORY) stays in the orchestrator's context — it
|
||||||
|
is FED to STEP 1 and STEP 2 and reconciled at STEP 3. Degradation: request too vague →
|
||||||
|
analyzer flags ambiguous zones, does not block (STEP 1 refines). `.claude/memory/` empty or
|
||||||
|
absent → analyzer omits RELATED MEMORY (no-op); the step still returns the code ANALYSIS.
|
||||||
|
Additive — distinct from STEP 5 ANALYZE (post-impl regression) and STEP 4b DEBUG.
|
||||||
|
|
||||||
## STEP 1 — BRAINSTORM
|
## STEP 1 — BRAINSTORM
|
||||||
Invoke `superpowers:brainstorming`. Refine request into validated design via Socratic questioning. Don't proceed until design approved.
|
Invoke `superpowers:brainstorming` — but FEED it the STEP 0d digest as binding context,
|
||||||
|
not the raw request alone:
|
||||||
|
"Feature request: <$ARGUMENTS>.
|
||||||
|
In-force constraints (must hold): <only the IN-FORCE + ALREADY-SEEN items from 0d's
|
||||||
|
RELATED MEMORY, detailed>.
|
||||||
|
Existing code that bears: <ANALYSIS CONTEXT / KEY COMPONENTS from 0d>.
|
||||||
|
Brainstorm WITHIN these — don't re-explore a direction an in-force BDR rejects or a
|
||||||
|
BLK already closed."
|
||||||
|
Inject ONLY what constrains: the NON-BINDING count does NOT enter the brainstorm input
|
||||||
|
(the injection inherits the OUTPUT filter — detail what binds, drop what doesn't).
|
||||||
|
Consumption = INPUT INJECTION (we can't modify the external skill; we control its input).
|
||||||
|
Refine request into validated design via Socratic questioning. Don't proceed until design approved.
|
||||||
|
|
||||||
## STEP 2 — PLAN
|
## STEP 2 — PLAN
|
||||||
Invoke `superpowers:writing-plans`. Break design into tasks (2-5 min each). Each task: exact file paths, full code, verification steps.
|
Invoke `superpowers:writing-plans` with the validated design AND the 0d digest: every task
|
||||||
|
must be consistent with the in-force constraints; where a task implements or affects one,
|
||||||
|
note the ID inline. Break design into tasks (2-5 min each). Each task: exact file paths, full code, verification steps.
|
||||||
|
|
||||||
## STEP 3 — VALIDATION GATE ★ MANDATORY STOP
|
## STEP 3 — VALIDATION GATE ★ MANDATORY STOP
|
||||||
```
|
```
|
||||||
SHIP FEATURE — VALIDATION GATE
|
SHIP FEATURE — VALIDATION GATE
|
||||||
FEATURE: <n> | TASKS: <count>
|
FEATURE: <n> | TASKS: <count>
|
||||||
<numbered task list>
|
<numbered task list>
|
||||||
|
|
||||||
|
RELATED MEMORY — disposition CLAIMED by this plan (review each):
|
||||||
|
- BDR-026 [in force] — plan honors it by: <how>
|
||||||
|
- LRN-050 [in force] — plan applies it by: <how>
|
||||||
|
- BLK-009 [already seen] — <how avoided / why N-A>
|
||||||
|
|
||||||
|
Review the claims above — flag any item the plan does NOT actually honor.
|
||||||
Approve and execute? (yes / request changes)
|
Approve and execute? (yes / request changes)
|
||||||
```
|
```
|
||||||
|
This block EXPOSES each in-force item with the plan's CLAIMED disposition, for human
|
||||||
|
review — it does NOT auto-detect conflicts. An agent blind to a conflict won't list it;
|
||||||
|
forcing a per-item claim is what gives the reviewer the surface to catch it. A display,
|
||||||
|
never a guarantee (same discipline as the memory-commit `✅<hash>`: show what's true, never
|
||||||
|
assert a check not performed). No RELATED MEMORY from 0d → omit the block.
|
||||||
Changes → back to STEP 2. Approved → continue.
|
Changes → back to STEP 2. Approved → continue.
|
||||||
|
|
||||||
## STEP 4 — IMPLEMENT
|
## STEP 4 — IMPLEMENT
|
||||||
@ -175,6 +220,8 @@ The pipeline must handle these without aborting silently:
|
|||||||
|---|---|
|
|---|---|
|
||||||
| STEP 0b — `CLAUDE.md` missing | STOP with the printed message ("Run `/onboard` first…"). Do not proceed. |
|
| STEP 0b — `CLAUDE.md` missing | STOP with the printed message ("Run `/onboard` first…"). Do not proceed. |
|
||||||
| STEP 0c — `ctx7` not installed but fast-libs detected | Skip pre-fetch silently. During STEP 4, log `📚 ctx7 cache miss for <lib>` and continue with vanilla model knowledge. |
|
| STEP 0c — `ctx7` not installed but fast-libs detected | Skip pre-fetch silently. During STEP 4, log `📚 ctx7 cache miss for <lib>` and continue with vanilla model knowledge. |
|
||||||
|
| STEP 0d — request too vague for analyzer to locate a code zone | analyzer reports ambiguous zones and does NOT block; STEP 1 brainstorm refines scope. The memory disposition is still produced. |
|
||||||
|
| STEP 0d — `.claude/memory/` absent (project not yet onboarded) | analyzer's guarded scan no-ops (the `[ -d ]` guard fires — a bare glob would error); proceed with the code ANALYSIS alone. STEP 7 creates registries later. |
|
||||||
| STEP 1 — brainstorming returns "design unclear" twice | Escalate: ask user "Switch to /init-project (greenfield-style design) or refine the feature request?" |
|
| STEP 1 — brainstorming returns "design unclear" twice | Escalate: ask user "Switch to /init-project (greenfield-style design) or refine the feature request?" |
|
||||||
| STEP 3 — user replies "request changes" | Loop back to STEP 2 with user's notes. Cap at 3 iterations; on the 3rd "request changes" without approval, ask "Pause and rescope this feature?" |
|
| STEP 3 — user replies "request changes" | Loop back to STEP 2 with user's notes. Cap at 3 iterations; on the 3rd "request changes" without approval, ask "Pause and rescope this feature?" |
|
||||||
| STEP 4 — subagent crashes (tool error, not test failure) | Treat as STEP 4b error path, present hypothesis-led gate. |
|
| STEP 4 — subagent crashes (tool error, not test failure) | Treat as STEP 4b error path, present hypothesis-led gate. |
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user