@hegemonart/get-design-done 1.28.0 → 1.28.6

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 (98) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +134 -0
  4. package/SKILL.md +1 -1
  5. package/hooks/gdd-decision-injector.js +149 -3
  6. package/package.json +1 -1
  7. package/reference/adr-format.md +96 -0
  8. package/reference/architecture-vocabulary.md +102 -0
  9. package/reference/context-md-format.md +106 -0
  10. package/reference/heuristics.md +84 -0
  11. package/reference/registry.json +29 -1
  12. package/reference/registry.schema.json +1 -1
  13. package/reference/shared-preamble.md +78 -6
  14. package/reference/skill-authoring-contract.md +159 -0
  15. package/scripts/validate-skill-length.cjs +283 -0
  16. package/skills/add-backlog/SKILL.md +1 -0
  17. package/skills/analyze-dependencies/SKILL.md +33 -122
  18. package/skills/apply-reflections/SKILL.md +1 -40
  19. package/skills/apply-reflections/apply-reflections-procedure.md +68 -0
  20. package/skills/audit/SKILL.md +3 -1
  21. package/skills/bandit-status/SKILL.md +31 -66
  22. package/skills/benchmark/SKILL.md +15 -55
  23. package/skills/brief/SKILL.md +12 -1
  24. package/skills/cache-manager/SKILL.md +3 -57
  25. package/skills/cache-manager/cache-policy.md +126 -0
  26. package/skills/check-update/SKILL.md +38 -75
  27. package/skills/compare/SKILL.md +29 -269
  28. package/skills/compare/compare-rubric.md +171 -0
  29. package/skills/complete-cycle/SKILL.md +1 -1
  30. package/skills/connections/SKILL.md +21 -427
  31. package/skills/connections/connections-onboarding.md +417 -0
  32. package/skills/continue/SKILL.md +1 -0
  33. package/skills/darkmode/SKILL.md +32 -287
  34. package/skills/darkmode/darkmode-audit-procedure.md +258 -0
  35. package/skills/debug/SKILL.md +11 -8
  36. package/skills/debug/debug-feedback-loops.md +119 -0
  37. package/skills/design/SKILL.md +27 -245
  38. package/skills/design/design-procedure.md +304 -0
  39. package/skills/discover/SKILL.md +26 -133
  40. package/skills/discover/discover-procedure.md +204 -0
  41. package/skills/discuss/SKILL.md +18 -2
  42. package/skills/explore/SKILL.md +40 -205
  43. package/skills/explore/explore-procedure.md +267 -0
  44. package/skills/fast/SKILL.md +1 -0
  45. package/skills/figma-write/SKILL.md +2 -2
  46. package/skills/health/SKILL.md +11 -33
  47. package/skills/health/health-mcp-detection.md +44 -0
  48. package/skills/health/health-skill-length-report.md +69 -0
  49. package/skills/help/SKILL.md +1 -0
  50. package/skills/list-assumptions/SKILL.md +1 -0
  51. package/skills/map/SKILL.md +8 -31
  52. package/skills/new-cycle/SKILL.md +3 -1
  53. package/skills/new-cycle/milestone-completeness-rubric.md +87 -0
  54. package/skills/next/SKILL.md +1 -0
  55. package/skills/note/SKILL.md +1 -0
  56. package/skills/optimize/SKILL.md +21 -44
  57. package/skills/pause/SKILL.md +1 -0
  58. package/skills/peer-cli-add/SKILL.md +26 -108
  59. package/skills/peer-cli-add/peer-cli-protocol.md +161 -0
  60. package/skills/peer-cli-customize/SKILL.md +22 -42
  61. package/skills/peers/SKILL.md +33 -57
  62. package/skills/plan/SKILL.md +33 -220
  63. package/skills/plan/plan-procedure.md +278 -0
  64. package/skills/plant-seed/SKILL.md +1 -0
  65. package/skills/pr-branch/SKILL.md +1 -0
  66. package/skills/progress/SKILL.md +1 -7
  67. package/skills/quality-gate/SKILL.md +34 -166
  68. package/skills/quality-gate/threat-modeling.md +101 -0
  69. package/skills/quick/SKILL.md +1 -0
  70. package/skills/reapply-patches/SKILL.md +1 -0
  71. package/skills/recall/SKILL.md +1 -0
  72. package/skills/resume/SKILL.md +1 -0
  73. package/skills/review-backlog/SKILL.md +1 -0
  74. package/skills/router/SKILL.md +3 -59
  75. package/skills/router/router-rules.md +84 -0
  76. package/skills/scan/SKILL.md +36 -675
  77. package/skills/scan/scan-procedure.md +731 -0
  78. package/skills/settings/SKILL.md +1 -0
  79. package/skills/ship/SKILL.md +1 -0
  80. package/skills/sketch/SKILL.md +1 -1
  81. package/skills/sketch-wrap-up/SKILL.md +13 -54
  82. package/skills/spike/SKILL.md +1 -1
  83. package/skills/spike-wrap-up/SKILL.md +12 -46
  84. package/skills/start/SKILL.md +13 -112
  85. package/skills/start/start-procedure.md +115 -0
  86. package/skills/stats/SKILL.md +1 -0
  87. package/skills/style/SKILL.md +18 -140
  88. package/skills/style/style-doc-procedure.md +150 -0
  89. package/skills/synthesize/SKILL.md +1 -0
  90. package/skills/timeline/SKILL.md +1 -0
  91. package/skills/todo/SKILL.md +1 -0
  92. package/skills/turn-closeout/SKILL.md +36 -56
  93. package/skills/undo/SKILL.md +1 -0
  94. package/skills/update/SKILL.md +1 -0
  95. package/skills/verify/SKILL.md +42 -457
  96. package/skills/verify/verify-procedure.md +512 -0
  97. package/skills/warm-cache/SKILL.md +3 -35
  98. package/skills/zoom-out/SKILL.md +26 -0
@@ -9,88 +9,69 @@ tools: Read, Bash
9
9
 
10
10
  ## Role
11
11
 
12
- You are a deterministic, read-only diagnostic skill. You do not spawn agents and do not modify the bandit posterior. You read `.design/telemetry/posterior.json` (the path declared by `scripts/lib/bandit-router.cjs`'s `DEFAULT_POSTERIOR_PATH` constant), aggregate per-`(agent, bin, delegate, tier)` arm state, and emit a single Markdown table summarizing the posterior. The user runs this when they want to inspect bandit decisions without touching the posterior.
13
-
14
- Strictly read-only per Phase 27.5 D-11. To reset the posterior, use `/gdd:bandit-reset` from Phase 23.5.
12
+ You are a deterministic, read-only diagnostic skill. You do not spawn agents and do not modify the posterior. You read `.design/telemetry/posterior.json` (path declared by `scripts/lib/bandit-router.cjs`'s `DEFAULT_POSTERIOR_PATH`), aggregate per-`(agent, bin, delegate, tier)` arm state, and emit a single Markdown table. Read-only per Phase 27.5 D-11 to reset, use `/gdd:bandit-reset` (Phase 23.5). See `./reference/bandit-integration.md` for setup, interpretation, and convergence guidance.
15
13
 
16
14
  ## Invocation Contract
17
15
 
18
- - **Input**: none. The skill takes no arguments.
19
- - **Output**: a Markdown bandit-status table to stdout. No JSON wrapper. The table is the entire output.
16
+ - **Input**: none.
17
+ - **Output**: a Markdown bandit-status table to stdout. The table is the entire output.
20
18
 
21
19
  ## Procedure
22
20
 
23
21
  ### 1. Locate the posterior file
24
22
 
25
- Read `.design/telemetry/posterior.json`. If the file does not exist:
26
-
27
- - Emit the empty-state message:
28
-
29
- ```
30
- ## Bandit Posterior Snapshot
31
-
32
- No posterior data yet — run a few pipeline cycles with `adaptive_mode: full` first.
33
-
34
- No posterior data found at `.design/telemetry/posterior.json`.
23
+ Read `.design/telemetry/posterior.json`. Missing emit empty-state message:
35
24
 
36
- Possible reasons:
37
- - `adaptive_mode` is `static` or `hedge` (bandit is silent — see `.design/budget.json` `adaptive_mode` setting).
38
- - No spawns have fired since Phase 27.5 wiring landed.
39
- - Posterior was cleared via `/gdd:bandit-reset`.
25
+ ```
26
+ ## Bandit Posterior Snapshot
40
27
 
41
- See `reference/bandit-integration.md` for setup guidance.
42
- ```
28
+ No posterior data yet — run a few pipeline cycles with `adaptive_mode: full` first.
43
29
 
44
- - Skip to Section 4 (Record).
30
+ No posterior data found at `.design/telemetry/posterior.json`.
45
31
 
46
- ### 2. Parse the posterior
47
-
48
- Parse the file as JSON. If parsing fails (truncated/corrupted file), emit:
32
+ Possible reasons:
33
+ - `adaptive_mode` is `static` or `hedge` (bandit silent — see `.design/budget.json`).
34
+ - No spawns have fired since Phase 27.5 wiring landed.
35
+ - Posterior was cleared via `/gdd:bandit-reset`.
49
36
 
37
+ See `reference/bandit-integration.md` for setup guidance.
50
38
  ```
51
- ## Bandit Posterior Snapshot
52
39
 
53
- Posterior file at `.design/telemetry/posterior.json` exists but is unparseable (truncated or corrupted).
40
+ Skip to Section 4 (Record). Parse failure (truncated/corrupted) → emit `Posterior file exists but is unparseable. Run /gdd:bandit-reset to start fresh, or restore from a backup.`
54
41
 
55
- Run `/gdd:bandit-reset` to start fresh, or restore from a backup.
56
- ```
42
+ ### 2. Parse the posterior
57
43
 
58
- The posterior schema is:
44
+ Schema:
59
45
 
60
46
  ```json
61
47
  {
62
48
  "schema_version": "1.0.0",
63
- "generated_at": "<ISO timestamp>",
64
- "arms": [
65
- { "agent": "...", "bin": "...", "tier": "...", "delegate": "...", "alpha": N, "beta": N, "last_used": "...", "count": N }
66
- ]
49
+ "generated_at": "<ISO>",
50
+ "arms": [{ "agent": "...", "bin": "...", "tier": "...", "delegate": "...", "alpha": N, "beta": N, "last_used": "...", "count": N }]
67
51
  }
68
52
  ```
69
53
 
70
- The `delegate` field is optional — when absent, the arm is the Phase 23.5 legacy slice (equivalent to `delegate: 'none'`). The status output renders `delegate: '-'` for legacy arms to distinguish them visually from explicit `'none'` arms.
54
+ The `delegate` field is optional — absent = Phase 23.5 legacy slice (rendered as `-` in the table).
71
55
 
72
56
  ### 3. Render the table
73
57
 
74
- Compute per arm:
75
-
76
- - `mean = alpha / (alpha + beta)` (rounded to 3 decimals)
77
- - `stddev = sqrt(alpha * beta / ((alpha + beta)^2 * (alpha + beta + 1)))` (rounded to 3 decimals)
58
+ Compute per arm: `mean = alpha / (alpha + beta)` (3 decimals), `stddev = sqrt(alpha*beta / ((alpha+beta)^2 * (alpha+beta+1)))` (3 decimals).
78
59
 
79
- Sort arms by `(agent ascending, bin ascending, delegate ascending where '-' sorts first, tier ascending where opus < sonnet < haiku is the canonical tier ordering, last_used descending tiebreaker)`. Group rows by agent for readability.
60
+ Sort by `(agent ASC, bin ASC, delegate ASC where '-' first, tier ASC opus<sonnet<haiku, last_used DESC)`. Group by agent for readability.
80
61
 
81
62
  Emit:
82
63
 
83
64
  ```
84
65
  ## Bandit Posterior Snapshot
85
66
 
86
- Per-(agent, bin, delegate, tier) posterior state. Read-only — to reset the posterior, use `/gdd:bandit-reset` (Phase 23.5).
67
+ Per-(agent, bin, delegate, tier) posterior state. Read-only — to reset use `/gdd:bandit-reset` (Phase 23.5).
87
68
 
88
69
  Posterior file: `.design/telemetry/posterior.json` (last updated: <generated_at>)
89
70
  Total arms: <count>
90
71
 
91
- | Agent | Bin | Delegate | Tier | Alpha | Beta | Mean | Stddev | Count | Last Used |
92
- |-----------------|--------|----------|--------|-------|-------|-------|--------|-------|----------------------|
93
- | <agent> | <bin> | <deleg> | <tier> | <a> | <b> | <m> | <s> | <c> | <last_used or '-'> |
72
+ | Agent | Bin | Delegate | Tier | Alpha | Beta | Mean | Stddev | Count | Last Used |
73
+ |-------|-----|----------|------|-------|------|------|--------|-------|-----------|
74
+ | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
94
75
 
95
76
  > Mean = alpha / (alpha + beta). Stddev = sqrt(alpha*beta / ((alpha+beta)^2 * (alpha+beta+1))).
96
77
  > Delegate '-' = Phase 23.5 legacy slice (equivalent to 'none').
@@ -98,32 +79,16 @@ Total arms: <count>
98
79
  > Read-only — use `/gdd:bandit-reset` to clear posterior state.
99
80
  ```
100
81
 
101
- Format numbers to fixed precision: alpha/beta to 2 decimals, mean/stddev to 3 decimals, count as integer, last_used truncated to the minute precision (`YYYY-MM-DDTHH:MM`).
82
+ Precision: alpha/beta 2 decimals; mean/stddev 3 decimals; count integer; `last_used` truncated to minute (`YYYY-MM-DDTHH:MM`); null `last_used` renders `-`.
102
83
 
103
- When `last_used` is null (arm exists but never selected possible if the arm was created by `ensureArm` without a subsequent `pull`), render `-` in the Last Used column.
104
-
105
- After the table, surface a brief best-arm summary per `(agent, bin)` slice — for each unique `(agent, bin)` pair, identify the arm with the highest `mean` (tie-broken by `count` descending) and display it as the "best-arm" recommendation. This helps the operator answer "why did the bandit pick tier X?" at a glance.
84
+ After the table, surface a per-`(agent, bin)` best-arm summary: for each unique pair, identify highest-mean arm (tie-broken by `count` DESC) answers "why did the bandit pick tier X?" at a glance.
106
85
 
107
86
  ### 4. Record
108
87
 
109
- After execution, append one JSONL line to `.design/skill-records.jsonl`:
110
-
111
- ```json
112
- {"skill": "gdd-bandit-status", "ts": "<ISO timestamp>", "arms_seen": <count>, "posterior_present": <bool>}
113
- ```
114
-
115
- The skill writes ONLY to `.design/skill-records.jsonl` for telemetry purposes. It never touches `.design/telemetry/posterior.json`.
88
+ Append one JSONL line to `.design/skill-records.jsonl`: `{"skill":"gdd-bandit-status","ts":"<ISO>","arms_seen":<count>,"posterior_present":<bool>}`. Skill writes ONLY to skill-records.jsonl (telemetry); never touches the posterior.
116
89
 
117
90
  ## Cross-references
118
91
 
119
- - `scripts/lib/bandit-router.cjs` (Phase 23.5) posterior shape, `DEFAULT_POSTERIOR_PATH` constant, `loadPosterior()` helper.
120
- - `scripts/lib/bandit-router/integration.cjs` (Phase 27.5-01) — production-integration shim.
121
- - `hooks/budget-enforcer.ts` (Phase 27.5-02) bandit consultation site.
122
- - `scripts/lib/session-runner/index.ts` (Phase 27.5-03) — outcome recording site.
123
- - `scripts/lib/bandit-arbitrage.cjs` (Phase 27.5-04) — automated stale-frontmatter analysis.
124
- - `reference/bandit-integration.md` (Phase 27.5-06) — operator guide.
125
- - `/gdd:bandit-reset` (Phase 23.5) — the ONLY surface that mutates the posterior.
126
-
127
- ## Record
128
-
129
- See Section 4 above.
92
+ - `./reference/bandit-integration.md` — operator guide; interpretation patterns.
93
+ - `scripts/lib/bandit-router.cjs` (Phase 23.5) — posterior shape, `DEFAULT_POSTERIOR_PATH`, `loadPosterior()`.
94
+ - `scripts/lib/bandit-router/integration.cjs` (27.5-01), `hooks/budget-enforcer.ts` (27.5-02), `scripts/lib/session-runner/index.ts` (27.5-03), `scripts/lib/bandit-arbitrage.cjs` (27.5-04), `/gdd:bandit-reset` (Phase 23.5) — only surface that mutates the posterior.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: gdd-benchmark
3
- description: Harvest and synthesize per-component design benchmarks from 18 design systems. Produces canonical specs at reference/components/<name>.md.
3
+ description: "Harvest and synthesize per-component design benchmarks from 18 design systems and produce canonical component specs at `reference/components/<name>.md`. Use when adding a new component spec, running a benchmark wave, listing corpus coverage, or refreshing a spec after a design-system version bump."
4
4
  argument-hint: "<component> | --wave <N> | --list | --refresh <component>"
5
5
  tools: Read, Write, Bash, Grep, Glob, Task, WebFetch
6
6
  ---
@@ -8,7 +8,9 @@ tools: Read, Write, Bash, Grep, Glob, Task, WebFetch
8
8
  # /gdd:benchmark
9
9
 
10
10
  Harvest per-component design knowledge from 18 design systems and synthesize canonical
11
- specs at `reference/components/<name>.md`.
11
+ specs at `reference/components/<name>.md`. The 18-source corpus + fallback chain lives in
12
+ `../../connections/design-corpora.md`. Per-skill output discipline + completion-marker
13
+ conventions are at `../../reference/shared-preamble.md#output-contract-reminders`.
12
14
 
13
15
  ## Invocation Modes
14
16
 
@@ -21,49 +23,17 @@ specs at `reference/components/<name>.md`.
21
23
 
22
24
  ## Single-Component Flow (`/gdd:benchmark <component>`)
23
25
 
24
- 1. **Check if spec exists** — `Glob("reference/components/<component>.md")`.
25
- If found and `--refresh` was not passed, confirm before overwriting.
26
-
27
- 2. **Harvest** — spawn `component-benchmark-harvester` with:
28
- ```
29
- Task("component-benchmark-harvester", """
30
- <required_reading>
31
- @connections/design-corpora.md
32
- </required_reading>
33
-
34
- Harvest design-system excerpts for component: <component>
35
- Emit raw harvest to: .planning/benchmarks/raw/<component>.md
36
- Consume any relevant content from: .planning/research/impeccable-salvage/
37
-
38
- Acceptance: .planning/benchmarks/raw/<component>.md exists with ≥4 source sections.
39
- """)
40
- ```
41
-
42
- 3. **Synthesize** — spawn `component-benchmark-synthesizer` with:
43
- ```
44
- Task("component-benchmark-synthesizer", """
45
- <required_reading>
46
- @.planning/benchmarks/raw/<component>.md
47
- @reference/components/TEMPLATE.md
48
- @reference/anti-patterns.md
49
- </required_reading>
50
-
51
- Synthesize the raw harvest into a canonical spec.
52
- Output: reference/components/<component>.md
53
- Update: reference/components/README.md (add entry in correct category)
54
-
55
- Acceptance: spec exists, ≤350 lines, cites ≥4 systems, has TEMPLATE.md sections,
56
- WAI-ARIA keyboard contract present, failing-example block present.
57
- """)
58
- ```
26
+ 1. **Check if spec exists** — `Glob("reference/components/<component>.md")`. If found and `--refresh` was not passed, confirm before overwriting.
27
+
28
+ 2. **Harvest** — spawn `component-benchmark-harvester` with required-reading `@connections/design-corpora.md`, target component, raw-output path `.planning/benchmarks/raw/<component>.md`, and a salvage hint to `.planning/research/impeccable-salvage/`. Acceptance: raw harvest exists with ≥4 source sections.
29
+
30
+ 3. **Synthesize** — spawn `component-benchmark-synthesizer` with required-reading `@.planning/benchmarks/raw/<component>.md`, `@reference/components/TEMPLATE.md`, `@reference/anti-patterns.md`. Output: `reference/components/<component>.md`. Also update `reference/components/README.md` (add entry in correct category). Acceptance: spec ≤350 lines, cites ≥4 systems, follows `TEMPLATE.md` sections, has a WAI-ARIA keyboard contract + a failing-example block.
59
31
 
60
32
  4. **Report** — print spec path, line count, systems cited.
61
33
 
62
34
  ## Wave Mode (`/gdd:benchmark --wave <N>`)
63
35
 
64
- Read the wave definition from `reference/components/README.md` and run each component
65
- in the wave sequentially (not parallel — each harvest is network-bound and the raw files
66
- are large).
36
+ Read the wave definition from `reference/components/README.md` and run each component sequentially (not parallel — each harvest is network-bound and the raw files are large).
67
37
 
68
38
  | Wave | Components |
69
39
  |------|-----------|
@@ -74,27 +44,15 @@ Print progress per component: `[N/total] harvesting <component>…`
74
44
 
75
45
  ## List Mode (`/gdd:benchmark --list`)
76
46
 
77
- Read `reference/components/README.md` and diff against `reference/components/*.md` files.
78
- Print a table:
79
-
80
- ```
81
- Component Status Wave Lines
82
- button ✓ 1 248
83
- input ✓ 1 312
84
- select-combobox ✓ 1 295
85
- ...
86
- toast pending 3 —
87
- ```
47
+ Read `reference/components/README.md` and diff against `reference/components/*.md` files. Print a table with columns: Component, Status, Wave, Lines.
88
48
 
89
49
  ## Refresh Mode (`/gdd:benchmark --refresh <component>`)
90
50
 
91
- Same as single-component flow but skips the "already exists" guard. Use when a design
92
- system ships a breaking update to a component's spec.
51
+ Same as single-component flow but skips the "already exists" guard. Use when a design system ships a breaking update to a component's spec.
93
52
 
94
53
  ## Source List
95
54
 
96
- `connections/design-corpora.md` — 18 design systems with canonical URLs, licensing, and
97
- fallback chain (canonical → archive.org → Refero MCP → Pinterest MCP).
55
+ `../../connections/design-corpora.md` — 18 design systems with canonical URLs, licensing, and fallback chain (canonical → archive.org → Refero MCP → Pinterest MCP).
98
56
 
99
57
  ## Output Artifacts
100
58
 
@@ -103,3 +61,5 @@ fallback chain (canonical → archive.org → Refero MCP → Pinterest MCP).
103
61
  | `.planning/benchmarks/raw/<component>.md` | Raw multi-source harvest (input only) |
104
62
  | `reference/components/<component>.md` | Canonical spec (distributed with plugin) |
105
63
  | `reference/components/README.md` | Corpus index (updated by synthesizer) |
64
+
65
+ ## BENCHMARK COMPLETE
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: gdd-brief
3
- description: "Design intake captures problem statement, audience, constraints, success metrics, and scope into .design/BRIEF.md (Stage 1 of 5)"
3
+ description: "Stage 1 of 5 design intake that captures problem statement, audience, constraints, success metrics, and scope into .design/BRIEF.md, and bootstraps .design/STATE.md if missing. Use when starting a new design cycle and before /gdd:explore."
4
4
  argument-hint: "[--re-brief to redo intake on existing project]"
5
5
  tools: Read, Write, AskUserQuestion, mcp__gdd_state__frontmatter_update, mcp__gdd_state__set_status, mcp__gdd_state__update_progress, mcp__gdd_state__get
6
6
  ---
@@ -72,6 +72,17 @@ With `.design/STATE.md` seeded from the template:
72
72
 
73
73
  Do NOT call `mcp__gdd_state__transition_stage` from brief — explore calls it on entry, keeping the transition atomic with the stage that owns the new state.
74
74
 
75
+ ## Step 6 — Inline glossary (CONTEXT.md) + ADR pointer
76
+
77
+ When a fuzzy phrase is resolved or a new domain concept is named during the briefing
78
+ interview: write to `./CONTEXT.md` IMMEDIATELY per `./../../reference/context-md-format.md`
79
+ (H2 heading + body; lazy-create on first term; no batching). Glossary entries compound
80
+ across cycles — token savings + naming consistency.
81
+
82
+ Project-shaping decisions surfaced in briefing can be promoted to an ADR — see
83
+ `./../../reference/adr-format.md` for the 3-criteria gate (hard-to-reverse AND
84
+ surprising-without-context AND real-tradeoff). Routine choices stay in STATE.md.
85
+
75
86
  ## After Writing
76
87
 
77
88
  ```
@@ -3,6 +3,7 @@ name: gdd-cache-manager
3
3
  description: "Maintains .design/cache-manifest.json for Layer B explicit cache per D-08. Computes deterministic SHA-256 input-hash from (agent-path + sorted-input-file-paths + input-content-hashes). On spawn: lookup key → return cached blob if within TTL, else miss. On completion: write result + TTL. Consulted by hooks/budget-enforcer.js before every Agent spawn."
4
4
  user-invocable: false
5
5
  tools: Read, Bash, Write
6
+ disable-model-invocation: true
6
7
  ---
7
8
 
8
9
  # gdd-cache-manager
@@ -37,60 +38,7 @@ You are the deterministic cache-key computer and cache-manifest writer for the o
37
38
 
38
39
  ## Deterministic Input-Hash Algorithm
39
40
 
40
- The canonical reference implementation (the single source of truth; `hooks/budget-enforcer.js` will import the same primitive via a shared helper in Plan 10.1-05 when telemetry lands):
41
-
42
- ```js
43
- // Deterministic cache-key primitive (reference implementation)
44
- // hash = SHA-256(
45
- // agent_path + "\n" +
46
- // sorted(input_file_paths).join("\n") + "\n" +
47
- // sorted(input_file_paths)
48
- // .map(p => sha256(readFileSync(p, "utf8")))
49
- // .join("\n")
50
- // )
51
- const crypto = require('crypto');
52
- const fs = require('fs');
53
-
54
- function sha256Hex(s) {
55
- return crypto.createHash('sha256').update(s, 'utf8').digest('hex');
56
- }
57
-
58
- function computeInputHash(agentPath, inputFilePaths) {
59
- const sortedPaths = [...inputFilePaths].sort();
60
- const contentHashes = sortedPaths.map(p => {
61
- try { return sha256Hex(fs.readFileSync(p, 'utf8')); }
62
- catch { return 'MISSING'; }
63
- });
64
- const canonical = [
65
- agentPath,
66
- sortedPaths.join('\n'),
67
- contentHashes.join('\n')
68
- ].join('\n');
69
- return sha256Hex(canonical);
70
- }
71
- ```
72
-
73
- Notes for maintainers:
74
-
75
- - **Sorted-unique paths** — ordering must be stable; caller is expected to de-duplicate. If the same path appears twice the hash still matches as long as caller pre-dedupes before invoking.
76
- - **Missing file** — the string `MISSING` is used in place of the content hash so a missing dependency doesn't silently collide with an empty file (empty file's SHA-256 is `e3b0c44...`). Missing-file hashes naturally miss on the next read because the real file has a different content hash.
77
- - **Agent-path** — agents changing their own body (role, tools, output contract) invalidate all their cache entries automatically because the agent file's content is not hashed; but the `agent_path` string is concatenated. Upgrading agents between versions naturally busts the cache only when the path changes. Plan 10.1-04 (shared preamble extraction) is expected to slightly adjust agent bodies — consumers should treat the first post-10.1 run as a full cache miss, which is the intended behavior.
78
-
79
- ## Manifest Shape
80
-
81
- See `reference/config-schema.md` §.design/cache-manifest.json Schema (Phase 10.1) for the authoritative schema. Keyed object, flat SHA-256 hex keys. Example:
82
-
83
- ```json
84
- {
85
- "a3f1e...": {
86
- "agent": "design-verifier",
87
- "result": "<base64-or-path>",
88
- "written_at": "2026-04-18T12:00:00Z",
89
- "ttl_seconds": 3600,
90
- "expires_at": "2026-04-18T13:00:00Z"
91
- }
92
- }
93
- ```
41
+ The canonical reference implementation (single source of truth; `hooks/budget-enforcer.js` imports the same primitive via a shared helper) lives in `./cache-policy.md#deterministic-input-hash-algorithm-layer-b` it documents the JS implementation, the maintainer notes (sorted-unique paths, MISSING-file sentinel, agent-path bust behavior), the manifest shape, and TTL semantics in one place. Conform to the algorithm exactly so the hook and any orchestrator agree byte-for-byte.
94
42
 
95
43
  ## Integration Points
96
44
 
@@ -115,6 +63,4 @@ Per D-09:
115
63
 
116
64
  ## TTL Semantics
117
65
 
118
- - Default `ttl_seconds` = `.design/budget.json.cache_ttl_seconds` = 3600s (1 hour) per D-10.
119
- - `expires_at` is computed at write time and stored; readers do not recompute.
120
- - Lazy cleanup: stale entries are not actively deleted on read (overhead for no benefit in normal operation). A separate reaper is optional and out of v1 scope.
66
+ Default `ttl_seconds` = `.design/budget.json.cache_ttl_seconds` = 3600s (1 hour) per D-10. `expires_at` is computed at write time and stored; readers do not recompute. Stale entries are lazily cleaned on read (no eager reaper in v1). Full TTL discussion: `./cache-policy.md#ttl-semantics-layer-b`.
@@ -0,0 +1,126 @@
1
+ ---
2
+ name: cache-policy
3
+ type: heuristic
4
+ version: 1.0.0
5
+ phase: 28.5
6
+ tags: [cache, layer-a, layer-b, sha-256, ttl, warm-cache, cache-manager, anthropic-prompt-cache]
7
+ last_updated: 2026-05-18
8
+ ---
9
+
10
+ # Cache Policy (Layer A + Layer B)
11
+
12
+ Extracted from `skills/cache-manager/SKILL.md` and `skills/warm-cache/SKILL.md` per Phase 28.5
13
+ D-10 (extract-then-link, never delete content). The two skills keep their orchestration
14
+ contracts and step-by-step flows; the deeper algorithmic and operational detail moves here
15
+ so the SKILLs stay under the 100-line cap.
16
+
17
+ The two layers (D-08):
18
+
19
+ - **Layer A** — Anthropic's 5-min prompt cache (owned by `warm-cache`). Keyed on shared-preamble-first prompt prefix. No project-local state.
20
+ - **Layer B** — explicit `.design/cache-manifest.json` (owned by `gdd-cache-manager`). Keyed on deterministic SHA-256 of `(agent-path, sorted-input-file-paths, input-content-hashes)`. Per-repo state.
21
+
22
+ ## Deterministic Input-Hash Algorithm (Layer B)
23
+
24
+ The canonical reference implementation (the single source of truth; `hooks/budget-enforcer.js` imports the same primitive via a shared helper):
25
+
26
+ ```js
27
+ // Deterministic cache-key primitive (reference implementation)
28
+ // hash = SHA-256(
29
+ // agent_path + "\n" +
30
+ // sorted(input_file_paths).join("\n") + "\n" +
31
+ // sorted(input_file_paths)
32
+ // .map(p => sha256(readFileSync(p, "utf8")))
33
+ // .join("\n")
34
+ // )
35
+ const crypto = require('crypto');
36
+ const fs = require('fs');
37
+
38
+ function sha256Hex(s) {
39
+ return crypto.createHash('sha256').update(s, 'utf8').digest('hex');
40
+ }
41
+
42
+ function computeInputHash(agentPath, inputFilePaths) {
43
+ const sortedPaths = [...inputFilePaths].sort();
44
+ const contentHashes = sortedPaths.map(p => {
45
+ try { return sha256Hex(fs.readFileSync(p, 'utf8')); }
46
+ catch { return 'MISSING'; }
47
+ });
48
+ const canonical = [
49
+ agentPath,
50
+ sortedPaths.join('\n'),
51
+ contentHashes.join('\n')
52
+ ].join('\n');
53
+ return sha256Hex(canonical);
54
+ }
55
+ ```
56
+
57
+ Notes for maintainers:
58
+
59
+ - **Sorted-unique paths** — ordering must be stable; caller is expected to de-duplicate. If the same path appears twice the hash still matches as long as caller pre-dedupes before invoking.
60
+ - **Missing file** — the string `MISSING` is used in place of the content hash so a missing dependency doesn't silently collide with an empty file (empty file's SHA-256 is `e3b0c44...`). Missing-file hashes naturally miss on the next read because the real file has a different content hash.
61
+ - **Agent-path** — agents changing their own body (role, tools, output contract) invalidate all their cache entries automatically because the agent file's content is not hashed; but the `agent_path` string is concatenated. Upgrading agents between versions naturally busts the cache only when the path changes. Plan 10.1-04 (shared preamble extraction) is expected to slightly adjust agent bodies — consumers should treat the first post-10.1 run as a full cache miss, which is the intended behavior.
62
+
63
+ ## Manifest Shape (Layer B)
64
+
65
+ See `./config-schema.md` §.design/cache-manifest.json Schema (Phase 10.1) for the authoritative schema. Keyed object, flat SHA-256 hex keys. Example:
66
+
67
+ ```json
68
+ {
69
+ "a3f1e...": {
70
+ "agent": "design-verifier",
71
+ "result": "<base64-or-path>",
72
+ "written_at": "2026-04-18T12:00:00Z",
73
+ "ttl_seconds": 3600,
74
+ "expires_at": "2026-04-18T13:00:00Z"
75
+ }
76
+ }
77
+ ```
78
+
79
+ ## TTL Semantics (Layer B)
80
+
81
+ - Default `ttl_seconds` = `.design/budget.json.cache_ttl_seconds` = 3600s (1 hour) per D-10.
82
+ - `expires_at` is computed at write time and stored; readers do not recompute.
83
+ - Lazy cleanup: stale entries are not actively deleted on read (overhead for no benefit in normal operation). A separate reaper is optional and out of v1 scope.
84
+
85
+ ## Concrete Warm-Cache Command Examples (Layer A)
86
+
87
+ Full invocation:
88
+
89
+ ```
90
+ $ /gdd:warm-cache
91
+
92
+ Warming Anthropic prompt cache for 14 agents (5 min TTL)...
93
+ [1/14] design-verifier ... ok (0.3s)
94
+ [2/14] design-planner ... ok (0.3s)
95
+ [3/14] design-integration-checker ... ok (0.3s)
96
+ ...
97
+ [14/14] design-reflector ... ok (0.3s)
98
+
99
+ ## Warm-cache complete
100
+ - Agents warmed: 14
101
+ - Skipped (no shared preamble import): 3 (agents/README.md not an agent; 2 agents not yet migrated to shared preamble)
102
+ - Duration: 4.2s
103
+ - Next 5 min: repeated spawns of these agents pay cached_input_per_1m rate
104
+ ```
105
+
106
+ Filtered invocation:
107
+
108
+ ```
109
+ $ /gdd:warm-cache --agents design-verifier,design-planner
110
+
111
+ Warming Anthropic prompt cache for 2 agents (filtered from 14)...
112
+ [1/2] design-verifier ... ok (0.3s)
113
+ [2/2] design-planner ... ok (0.3s)
114
+
115
+ ## Warm-cache complete
116
+ - Agents warmed: 2
117
+ - Filtered out by --agents: 12
118
+ - Duration: 0.7s
119
+ ```
120
+
121
+ ## Cost Model (Layer A)
122
+
123
+ - Each no-op Haiku ping: ~50 input tokens (shared preamble + "No-op warm: acknowledge..." system+user) + ~5 output tokens ("ok").
124
+ - At Haiku rates (`./model-prices.md`): `(50 / 1e6) * 1.00 + (5 / 1e6) * 5.00 = $0.00005 + $0.000025 = $0.000075` per agent.
125
+ - 14 agents × $0.000075 = **$0.00105** total for a full warm-cache invocation.
126
+ - Payback: a single subsequent Opus spawn with 40k cached input tokens saves `(40000/1e6) * (15.00 - 1.50) = $0.54`. Warm-cache pays for itself ~500× over on the first repeated planner spawn.