@hegemonart/get-design-done 1.57.1 → 1.57.3

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 (237) hide show
  1. package/.claude-plugin/marketplace.json +26 -41
  2. package/.claude-plugin/plugin.json +23 -48
  3. package/CHANGELOG.md +139 -0
  4. package/README.md +166 -511
  5. package/SKILL.md +4 -6
  6. package/agents/README.md +33 -36
  7. package/agents/a11y-mapper.md +3 -3
  8. package/agents/component-benchmark-harvester.md +6 -6
  9. package/agents/component-benchmark-synthesizer.md +3 -3
  10. package/agents/compose-executor.md +3 -3
  11. package/agents/cost-forecaster.md +2 -2
  12. package/agents/design-auditor.md +7 -7
  13. package/agents/design-authority-watcher.md +15 -15
  14. package/agents/design-context-builder.md +4 -4
  15. package/agents/design-context-checker-gate.md +1 -1
  16. package/agents/design-discussant.md +2 -2
  17. package/agents/design-doc-writer.md +1 -1
  18. package/agents/design-executor.md +2 -2
  19. package/agents/design-figma-writer.md +2 -2
  20. package/agents/design-fixer.md +7 -7
  21. package/agents/design-integration-checker-gate.md +1 -1
  22. package/agents/design-integration-checker.md +1 -1
  23. package/agents/design-paper-writer.md +3 -3
  24. package/agents/design-pencil-writer.md +1 -1
  25. package/agents/design-planner.md +21 -0
  26. package/agents/design-reflector.md +39 -39
  27. package/agents/design-research-synthesizer.md +1 -0
  28. package/agents/design-start-writer.md +1 -1
  29. package/agents/design-update-checker.md +5 -5
  30. package/agents/design-verifier-gate.md +1 -1
  31. package/agents/design-verifier.md +52 -48
  32. package/agents/ds-generator.md +2 -2
  33. package/agents/ds-migration-planner.md +4 -4
  34. package/agents/email-executor.md +9 -9
  35. package/agents/experiment-result-ingester.md +3 -3
  36. package/agents/flutter-executor.md +5 -5
  37. package/agents/gdd-graph-refresh.md +3 -3
  38. package/agents/gdd-intel-updater.md +2 -2
  39. package/agents/motion-mapper.md +2 -2
  40. package/agents/motion-verifier.md +4 -4
  41. package/agents/pdf-executor.md +8 -8
  42. package/agents/perf-analyzer.md +17 -17
  43. package/agents/pr-commenter.md +9 -9
  44. package/agents/prototype-gate.md +2 -2
  45. package/agents/quality-gate-runner.md +1 -1
  46. package/agents/rollout-coordinator.md +3 -3
  47. package/agents/swift-executor.md +4 -4
  48. package/agents/ticket-sync-agent.md +6 -6
  49. package/agents/user-research-synthesizer.md +2 -2
  50. package/connections/connections.md +44 -45
  51. package/connections/cursor.md +72 -0
  52. package/connections/preview.md +3 -3
  53. package/hooks/first-run-nudge.cjs +171 -0
  54. package/hooks/gdd-intel-trigger.js +243 -0
  55. package/hooks/gdd-mcp-circuit-breaker.js +62 -7
  56. package/hooks/gdd-precompact-snapshot.js +50 -29
  57. package/hooks/gdd-protected-paths.js +150 -18
  58. package/hooks/gdd-risk-gate.js +93 -1
  59. package/hooks/gdd-sessionstart-recap.js +59 -24
  60. package/hooks/hooks.json +13 -4
  61. package/hooks/inject-using-gdd.cjs +188 -0
  62. package/hooks/update-check.cjs +511 -0
  63. package/package.json +9 -3
  64. package/reference/STATE-TEMPLATE.md +10 -13
  65. package/reference/audit-scoring.md +1 -1
  66. package/reference/cache-tier-doctrine.md +46 -0
  67. package/reference/config-schema.md +9 -9
  68. package/reference/i18n.md +1 -1
  69. package/reference/intel-schema.md +37 -2
  70. package/reference/meta-rules.md +4 -4
  71. package/reference/model-tiers.md +2 -2
  72. package/reference/registry.json +101 -94
  73. package/reference/runtime-models.md +11 -1
  74. package/reference/shared-preamble.md +13 -14
  75. package/reference/skill-graph.md +22 -3
  76. package/scripts/bootstrap.cjs +373 -0
  77. package/scripts/injection-patterns.cjs +58 -0
  78. package/scripts/lib/apply-reflections/incubator-proposals.cjs +57 -26
  79. package/scripts/lib/install/converters/codex-plugin.cjs +5 -2
  80. package/scripts/lib/install/converters/cursor.cjs +20 -0
  81. package/scripts/lib/issue-reporter/report-flow.cjs +1 -1
  82. package/scripts/lib/manifest/skills.json +75 -28
  83. package/scripts/lib/state/query-surface.cjs +67 -9
  84. package/scripts/lib/state/state-store.cjs +68 -26
  85. package/scripts/lib/worktree-resolve.cjs +4 -16
  86. package/sdk/cli/commands/stage.ts +17 -0
  87. package/sdk/cli/index.js +14 -0
  88. package/skills/README.md +46 -0
  89. package/skills/bootstrap-ds/SKILL.md +1 -1
  90. package/skills/cache-manager/SKILL.md +3 -3
  91. package/skills/cache-manager/cache-policy.md +1 -1
  92. package/skills/compare/SKILL.md +1 -1
  93. package/skills/design/SKILL.md +19 -0
  94. package/skills/explore/SKILL.md +11 -0
  95. package/skills/figma-write/SKILL.md +13 -2
  96. package/skills/new-cycle/SKILL.md +1 -1
  97. package/skills/paper-write/SKILL.md +54 -0
  98. package/skills/peer-cli-customize/SKILL.md +0 -1
  99. package/skills/peers/SKILL.md +1 -1
  100. package/skills/pencil-write/SKILL.md +54 -0
  101. package/skills/reflect/procedures/capability-gap-scan.md +0 -1
  102. package/skills/report-issue/SKILL.md +2 -2
  103. package/skills/report-issue/report-issue-procedure.md +0 -1
  104. package/skills/router/SKILL.md +2 -2
  105. package/skills/synthesize/SKILL.md +1 -1
  106. package/skills/turn-closeout/SKILL.md +1 -1
  107. package/skills/verify/verify-procedure.md +10 -11
  108. package/skills/warm-cache/SKILL.md +1 -1
  109. package/dist/claude-code/.claude/skills/add-backlog/SKILL.md +0 -48
  110. package/dist/claude-code/.claude/skills/analyze-dependencies/SKILL.md +0 -95
  111. package/dist/claude-code/.claude/skills/apply-reflections/SKILL.md +0 -109
  112. package/dist/claude-code/.claude/skills/apply-reflections/apply-reflections-procedure.md +0 -170
  113. package/dist/claude-code/.claude/skills/audit/SKILL.md +0 -79
  114. package/dist/claude-code/.claude/skills/bandit-status/SKILL.md +0 -94
  115. package/dist/claude-code/.claude/skills/benchmark/SKILL.md +0 -65
  116. package/dist/claude-code/.claude/skills/bootstrap-ds/SKILL.md +0 -43
  117. package/dist/claude-code/.claude/skills/brief/SKILL.md +0 -145
  118. package/dist/claude-code/.claude/skills/budget/SKILL.md +0 -45
  119. package/dist/claude-code/.claude/skills/cache-manager/SKILL.md +0 -66
  120. package/dist/claude-code/.claude/skills/cache-manager/cache-policy.md +0 -126
  121. package/dist/claude-code/.claude/skills/check-update/SKILL.md +0 -98
  122. package/dist/claude-code/.claude/skills/compare/SKILL.md +0 -82
  123. package/dist/claude-code/.claude/skills/compare/compare-rubric.md +0 -171
  124. package/dist/claude-code/.claude/skills/complete-cycle/SKILL.md +0 -81
  125. package/dist/claude-code/.claude/skills/connections/SKILL.md +0 -71
  126. package/dist/claude-code/.claude/skills/connections/connections-onboarding.md +0 -608
  127. package/dist/claude-code/.claude/skills/context/SKILL.md +0 -137
  128. package/dist/claude-code/.claude/skills/continue/SKILL.md +0 -24
  129. package/dist/claude-code/.claude/skills/darkmode/SKILL.md +0 -76
  130. package/dist/claude-code/.claude/skills/darkmode/darkmode-audit-procedure.md +0 -258
  131. package/dist/claude-code/.claude/skills/debug/SKILL.md +0 -41
  132. package/dist/claude-code/.claude/skills/debug/debug-feedback-loops.md +0 -119
  133. package/dist/claude-code/.claude/skills/design/SKILL.md +0 -99
  134. package/dist/claude-code/.claude/skills/design/design-procedure.md +0 -304
  135. package/dist/claude-code/.claude/skills/discover/SKILL.md +0 -78
  136. package/dist/claude-code/.claude/skills/discover/discover-procedure.md +0 -222
  137. package/dist/claude-code/.claude/skills/discuss/SKILL.md +0 -96
  138. package/dist/claude-code/.claude/skills/do/SKILL.md +0 -45
  139. package/dist/claude-code/.claude/skills/explore/SKILL.md +0 -107
  140. package/dist/claude-code/.claude/skills/explore/explore-procedure.md +0 -267
  141. package/dist/claude-code/.claude/skills/export/SKILL.md +0 -30
  142. package/dist/claude-code/.claude/skills/extract-learnings/SKILL.md +0 -114
  143. package/dist/claude-code/.claude/skills/fast/SKILL.md +0 -91
  144. package/dist/claude-code/.claude/skills/figma-extract/SKILL.md +0 -64
  145. package/dist/claude-code/.claude/skills/figma-write/SKILL.md +0 -39
  146. package/dist/claude-code/.claude/skills/graphify/SKILL.md +0 -49
  147. package/dist/claude-code/.claude/skills/health/SKILL.md +0 -99
  148. package/dist/claude-code/.claude/skills/health/health-mcp-detection.md +0 -44
  149. package/dist/claude-code/.claude/skills/health/health-skill-length-report.md +0 -69
  150. package/dist/claude-code/.claude/skills/help/SKILL.md +0 -87
  151. package/dist/claude-code/.claude/skills/instinct/SKILL.md +0 -111
  152. package/dist/claude-code/.claude/skills/list-assumptions/SKILL.md +0 -61
  153. package/dist/claude-code/.claude/skills/list-pins/SKILL.md +0 -27
  154. package/dist/claude-code/.claude/skills/live/SKILL.md +0 -98
  155. package/dist/claude-code/.claude/skills/locale/SKILL.md +0 -51
  156. package/dist/claude-code/.claude/skills/map/SKILL.md +0 -89
  157. package/dist/claude-code/.claude/skills/migrate/SKILL.md +0 -70
  158. package/dist/claude-code/.claude/skills/migrate-context/SKILL.md +0 -123
  159. package/dist/claude-code/.claude/skills/new-addendum/SKILL.md +0 -81
  160. package/dist/claude-code/.claude/skills/new-cycle/SKILL.md +0 -37
  161. package/dist/claude-code/.claude/skills/new-cycle/milestone-completeness-rubric.md +0 -87
  162. package/dist/claude-code/.claude/skills/new-project/SKILL.md +0 -53
  163. package/dist/claude-code/.claude/skills/new-skill/SKILL.md +0 -90
  164. package/dist/claude-code/.claude/skills/next/SKILL.md +0 -68
  165. package/dist/claude-code/.claude/skills/note/SKILL.md +0 -48
  166. package/dist/claude-code/.claude/skills/openrouter-status/SKILL.md +0 -86
  167. package/dist/claude-code/.claude/skills/optimize/SKILL.md +0 -97
  168. package/dist/claude-code/.claude/skills/override/SKILL.md +0 -86
  169. package/dist/claude-code/.claude/skills/pause/SKILL.md +0 -77
  170. package/dist/claude-code/.claude/skills/peer-cli-add/SKILL.md +0 -88
  171. package/dist/claude-code/.claude/skills/peer-cli-add/peer-cli-protocol.md +0 -161
  172. package/dist/claude-code/.claude/skills/peer-cli-customize/SKILL.md +0 -90
  173. package/dist/claude-code/.claude/skills/peers/SKILL.md +0 -96
  174. package/dist/claude-code/.claude/skills/pin/SKILL.md +0 -37
  175. package/dist/claude-code/.claude/skills/plan/SKILL.md +0 -105
  176. package/dist/claude-code/.claude/skills/plan/plan-procedure.md +0 -278
  177. package/dist/claude-code/.claude/skills/plant-seed/SKILL.md +0 -48
  178. package/dist/claude-code/.claude/skills/pr-branch/SKILL.md +0 -32
  179. package/dist/claude-code/.claude/skills/progress/SKILL.md +0 -107
  180. package/dist/claude-code/.claude/skills/quality-gate/SKILL.md +0 -90
  181. package/dist/claude-code/.claude/skills/quality-gate/threat-modeling.md +0 -101
  182. package/dist/claude-code/.claude/skills/quick/SKILL.md +0 -44
  183. package/dist/claude-code/.claude/skills/reapply-patches/SKILL.md +0 -32
  184. package/dist/claude-code/.claude/skills/recall/SKILL.md +0 -75
  185. package/dist/claude-code/.claude/skills/reflect/SKILL.md +0 -85
  186. package/dist/claude-code/.claude/skills/reflect/procedures/capability-gap-scan.md +0 -120
  187. package/dist/claude-code/.claude/skills/report-issue/SKILL.md +0 -53
  188. package/dist/claude-code/.claude/skills/report-issue/report-issue-procedure.md +0 -120
  189. package/dist/claude-code/.claude/skills/resume/SKILL.md +0 -93
  190. package/dist/claude-code/.claude/skills/review-backlog/SKILL.md +0 -46
  191. package/dist/claude-code/.claude/skills/review-decisions/SKILL.md +0 -42
  192. package/dist/claude-code/.claude/skills/roi/SKILL.md +0 -54
  193. package/dist/claude-code/.claude/skills/rollout-status/SKILL.md +0 -35
  194. package/dist/claude-code/.claude/skills/router/SKILL.md +0 -89
  195. package/dist/claude-code/.claude/skills/router/capability-gap-emitter.md +0 -65
  196. package/dist/claude-code/.claude/skills/router/router-pick-emitter.md +0 -78
  197. package/dist/claude-code/.claude/skills/router/router-rules.md +0 -84
  198. package/dist/claude-code/.claude/skills/scan/SKILL.md +0 -92
  199. package/dist/claude-code/.claude/skills/scan/scan-procedure.md +0 -732
  200. package/dist/claude-code/.claude/skills/settings/SKILL.md +0 -87
  201. package/dist/claude-code/.claude/skills/ship/SKILL.md +0 -48
  202. package/dist/claude-code/.claude/skills/sketch/SKILL.md +0 -78
  203. package/dist/claude-code/.claude/skills/sketch-wrap-up/SKILL.md +0 -92
  204. package/dist/claude-code/.claude/skills/skill-manifest/SKILL.md +0 -79
  205. package/dist/claude-code/.claude/skills/spike/SKILL.md +0 -67
  206. package/dist/claude-code/.claude/skills/spike-wrap-up/SKILL.md +0 -86
  207. package/dist/claude-code/.claude/skills/start/SKILL.md +0 -67
  208. package/dist/claude-code/.claude/skills/start/start-procedure.md +0 -115
  209. package/dist/claude-code/.claude/skills/state/SKILL.md +0 -106
  210. package/dist/claude-code/.claude/skills/stats/SKILL.md +0 -51
  211. package/dist/claude-code/.claude/skills/style/SKILL.md +0 -71
  212. package/dist/claude-code/.claude/skills/style/style-doc-procedure.md +0 -150
  213. package/dist/claude-code/.claude/skills/synthesize/SKILL.md +0 -94
  214. package/dist/claude-code/.claude/skills/timeline/SKILL.md +0 -66
  215. package/dist/claude-code/.claude/skills/todo/SKILL.md +0 -64
  216. package/dist/claude-code/.claude/skills/turn-closeout/SKILL.md +0 -95
  217. package/dist/claude-code/.claude/skills/undo/SKILL.md +0 -31
  218. package/dist/claude-code/.claude/skills/unlock-decision/SKILL.md +0 -54
  219. package/dist/claude-code/.claude/skills/unpin/SKILL.md +0 -31
  220. package/dist/claude-code/.claude/skills/update/SKILL.md +0 -56
  221. package/dist/claude-code/.claude/skills/using-gdd/SKILL.md +0 -78
  222. package/dist/claude-code/.claude/skills/verify/SKILL.md +0 -113
  223. package/dist/claude-code/.claude/skills/verify/verify-procedure.md +0 -512
  224. package/dist/claude-code/.claude/skills/warm-cache/SKILL.md +0 -81
  225. package/dist/claude-code/.claude/skills/watch-authorities/SKILL.md +0 -82
  226. package/dist/claude-code/.claude/skills/zoom-out/SKILL.md +0 -26
  227. package/hooks/first-run-nudge.sh +0 -82
  228. package/hooks/inject-using-gdd.sh +0 -72
  229. package/hooks/run-hook.cmd +0 -35
  230. package/hooks/update-check.sh +0 -251
  231. package/scripts/lib/audit-aggregator/index.cjs +0 -219
  232. package/scripts/lib/hedge-ensemble.cjs +0 -217
  233. package/skills/discover/SKILL.md +0 -78
  234. package/skills/discover/discover-procedure.md +0 -222
  235. package/skills/new-cycle/milestone-completeness-rubric.md +0 -87
  236. package/skills/scan/SKILL.md +0 -92
  237. package/skills/scan/scan-procedure.md +0 -732
@@ -1,219 +0,0 @@
1
- /**
2
- * audit-aggregator/index.cjs — dedup + score + rank findings from N
3
- * audit-agents (Plan 23-04).
4
- *
5
- * Replaces the prompt-only "trust the agent's score" pattern with a
6
- * deterministic scoring + dedup function that downstream tooling
7
- * (`/gdd:audit`, `/gdd:reflect`) can rely on.
8
- *
9
- * Dedup key: `${lowercased(normalizePath(file))}::${line ?? 0}::${rule_id}`.
10
- * Survivor selection on collision:
11
- * 1. higher confidence wins
12
- * 2. tie → higher severity (P0 > P1 > P2 > P3)
13
- * 3. tie → lexicographically earliest agent
14
- * 4. tie → first-seen
15
- *
16
- * Score = severityWeight(severity) * confidence.
17
- *
18
- * No external deps. CommonJS to match the rest of scripts/lib/.
19
- */
20
-
21
- 'use strict';
22
-
23
- const SEVERITY_RANK = { P0: 4, P1: 3, P2: 2, P3: 1 };
24
- const DEFAULT_WEIGHTS = Object.freeze({ P0: 8, P1: 4, P2: 2, P3: 1 });
25
-
26
- /**
27
- * @typedef {Object} Finding
28
- * @property {string} file
29
- * @property {number} [line]
30
- * @property {string} rule_id
31
- * @property {'P0'|'P1'|'P2'|'P3'} severity
32
- * @property {string} summary
33
- * @property {string} [evidence]
34
- * @property {string} [agent]
35
- * @property {number} [confidence]
36
- * @property {string[]} [merged_from]
37
- */
38
-
39
- /**
40
- * @typedef {Object} AggregateResult
41
- * @property {Finding[]} findings
42
- * @property {Object<string, number>} byRule
43
- * @property {Object<string, number>} bySeverity
44
- * @property {Object<string, number>} byFile
45
- * @property {number} total
46
- * @property {number} duplicates
47
- */
48
-
49
- /**
50
- * @typedef {Object} AggregateOptions
51
- * @property {number} [topN]
52
- * @property {Object<string, number>} [severityWeights]
53
- * @property {(a: Finding, b: Finding) => Finding} [merge]
54
- */
55
-
56
- function normalizePath(p) {
57
- return String(p).replace(/\\/g, '/').toLowerCase();
58
- }
59
-
60
- let _confidenceWarningEmitted = false;
61
-
62
- function clampConfidence(c) {
63
- if (c === undefined || c === null) return 1;
64
- if (typeof c !== 'number' || Number.isNaN(c)) return 1;
65
- if (c < 0) {
66
- if (!_confidenceWarningEmitted) {
67
- process.emitWarning('audit-aggregator: confidence < 0 clamped to 0', 'AuditAggregator');
68
- _confidenceWarningEmitted = true;
69
- }
70
- return 0;
71
- }
72
- if (c > 1) {
73
- if (!_confidenceWarningEmitted) {
74
- process.emitWarning('audit-aggregator: confidence > 1 clamped to 1', 'AuditAggregator');
75
- _confidenceWarningEmitted = true;
76
- }
77
- return 1;
78
- }
79
- return c;
80
- }
81
-
82
- /**
83
- * Compute score for a finding.
84
- *
85
- * @param {Finding} f
86
- * @param {Object<string, number>} weights
87
- * @returns {number}
88
- */
89
- function score(f, weights) {
90
- const w = (weights && weights[f.severity]) ?? DEFAULT_WEIGHTS[f.severity] ?? 0;
91
- return w * clampConfidence(f.confidence);
92
- }
93
-
94
- function validateFinding(f, idx) {
95
- if (!f || typeof f !== 'object') {
96
- throw new TypeError(`audit-aggregator: input[${idx}] is not an object`);
97
- }
98
- if (typeof f.file !== 'string' || f.file.length === 0) {
99
- throw new TypeError(`audit-aggregator: input[${idx}].file is required (non-empty string)`);
100
- }
101
- if (typeof f.rule_id !== 'string' || f.rule_id.length === 0) {
102
- throw new TypeError(`audit-aggregator: input[${idx}].rule_id is required (non-empty string)`);
103
- }
104
- if (!(f.severity in SEVERITY_RANK)) {
105
- throw new TypeError(
106
- `audit-aggregator: input[${idx}].severity must be P0|P1|P2|P3 (got ${JSON.stringify(f.severity)})`,
107
- );
108
- }
109
- }
110
-
111
- function dedupKey(f) {
112
- return `${normalizePath(f.file)}::${f.line ?? 0}::${f.rule_id}`;
113
- }
114
-
115
- function defaultMerge(a, b) {
116
- // Higher confidence wins.
117
- const ca = clampConfidence(a.confidence);
118
- const cb = clampConfidence(b.confidence);
119
- if (ca !== cb) return ca > cb ? a : b;
120
- // Higher severity wins.
121
- const ra = SEVERITY_RANK[a.severity];
122
- const rb = SEVERITY_RANK[b.severity];
123
- if (ra !== rb) return ra > rb ? a : b;
124
- // Lexicographic agent.
125
- const aa = a.agent ?? '';
126
- const ab = b.agent ?? '';
127
- if (aa !== ab) return aa < ab ? a : b;
128
- // First-seen wins (a is by convention the existing entry).
129
- return a;
130
- }
131
-
132
- /**
133
- * Aggregate findings.
134
- *
135
- * @param {Finding[]} input
136
- * @param {AggregateOptions} [opts]
137
- * @returns {AggregateResult}
138
- */
139
- function aggregate(input, opts = {}) {
140
- if (!Array.isArray(input)) {
141
- throw new TypeError('audit-aggregator: input must be an array');
142
- }
143
- // Reset the once-per-call warning flag so a second call can warn again.
144
- _confidenceWarningEmitted = false;
145
- const merge = typeof opts.merge === 'function' ? opts.merge : defaultMerge;
146
- const weights = { ...DEFAULT_WEIGHTS, ...(opts.severityWeights || {}) };
147
-
148
- /** @type {Map<string, Finding>} */
149
- const byKey = new Map();
150
- let duplicates = 0;
151
- for (let i = 0; i < input.length; i++) {
152
- validateFinding(input[i], i);
153
- const f = { ...input[i] };
154
- const key = dedupKey(f);
155
- if (byKey.has(key)) {
156
- duplicates += 1;
157
- const existing = byKey.get(key);
158
- const winner = merge(existing, f);
159
- const loser = winner === existing ? f : existing;
160
- const mergedFrom = new Set(winner.merged_from || []);
161
- if (existing.agent && existing !== winner) mergedFrom.add(existing.agent);
162
- if (loser.agent && loser !== winner) mergedFrom.add(loser.agent);
163
- // Combine prior merged_from too.
164
- for (const a of (loser.merged_from || [])) mergedFrom.add(a);
165
- winner.merged_from = Array.from(mergedFrom);
166
- byKey.set(key, winner);
167
- } else {
168
- byKey.set(key, f);
169
- }
170
- }
171
-
172
- const findings = Array.from(byKey.values()).map((f) => ({ ...f, _score: score(f, weights) }));
173
- findings.sort((a, b) => {
174
- if (a._score !== b._score) return b._score - a._score;
175
- const ra = SEVERITY_RANK[a.severity];
176
- const rb = SEVERITY_RANK[b.severity];
177
- if (ra !== rb) return rb - ra;
178
- if (a.file !== b.file) return a.file < b.file ? -1 : 1;
179
- return (a.line ?? 0) - (b.line ?? 0);
180
- });
181
- // Strip the internal _score field before returning.
182
- for (const f of findings) delete f._score;
183
-
184
- const truncated = typeof opts.topN === 'number' && opts.topN >= 0
185
- ? findings.slice(0, opts.topN)
186
- : findings;
187
-
188
- /** @type {Record<string, number>} */
189
- const byRule = {};
190
- /** @type {Record<string, number>} */
191
- const bySeverity = { P0: 0, P1: 0, P2: 0, P3: 0 };
192
- /** @type {Record<string, number>} */
193
- const byFile = {};
194
- for (const f of truncated) {
195
- byRule[f.rule_id] = (byRule[f.rule_id] ?? 0) + 1;
196
- bySeverity[f.severity] += 1;
197
- const k = normalizePath(f.file);
198
- byFile[k] = (byFile[k] ?? 0) + 1;
199
- }
200
-
201
- return {
202
- findings: truncated,
203
- byRule,
204
- bySeverity,
205
- byFile,
206
- total: truncated.length,
207
- duplicates,
208
- };
209
- }
210
-
211
- module.exports = {
212
- aggregate,
213
- score,
214
- normalizePath,
215
- dedupKey,
216
- defaultMerge,
217
- DEFAULT_WEIGHTS,
218
- SEVERITY_RANK,
219
- };
@@ -1,217 +0,0 @@
1
- /**
2
- * hedge-ensemble.cjs — AdaNormalHedge weighted-majority over verifier
3
- * + checker agents (Plan 23.5-02).
4
- *
5
- * Parameter-free: no manual learning rate. Weights self-adapt via
6
- * the AdaNormalHedge regret-bound trick — η is recomputed each round
7
- * from cumulative loss variance, eliminating the typical "tune η or
8
- * suffer" tax.
9
- *
10
- * Weights persist at `.design/telemetry/hedge-weights.json` (atomic
11
- * .tmp + rename). Schema:
12
- * { schema_version: '1.0.0',
13
- * generated_at: ISO,
14
- * pools: { <poolId>: { agents: { <agentId>: {weight, cumLoss, cumLoss2, rounds} } } } }
15
- *
16
- * Reused by adaptive_mode = "hedge" or "full" — see Plan 23.5-04.
17
- */
18
-
19
- 'use strict';
20
-
21
- const fs = require('node:fs');
22
- const path = require('node:path');
23
-
24
- const DEFAULT_WEIGHTS_PATH = '.design/telemetry/hedge-weights.json';
25
- const SCHEMA_VERSION = '1.0.0';
26
- const DEFAULT_VOTE_THRESHOLD = 0.5;
27
-
28
- function resolvePath(opts = {}) {
29
- if (opts.weightsPath) {
30
- return path.isAbsolute(opts.weightsPath)
31
- ? opts.weightsPath
32
- : path.resolve(opts.baseDir ?? process.cwd(), opts.weightsPath);
33
- }
34
- return path.resolve(opts.baseDir ?? process.cwd(), DEFAULT_WEIGHTS_PATH);
35
- }
36
-
37
- /**
38
- * @returns {{schema_version: string, generated_at: string, pools: object}}
39
- */
40
- function loadWeights(opts = {}) {
41
- const p = resolvePath(opts);
42
- if (!fs.existsSync(p)) {
43
- return { schema_version: SCHEMA_VERSION, generated_at: new Date().toISOString(), pools: {} };
44
- }
45
- try {
46
- const data = JSON.parse(fs.readFileSync(p, 'utf8'));
47
- if (!data.pools || typeof data.pools !== 'object') data.pools = {};
48
- return data;
49
- } catch {
50
- return { schema_version: SCHEMA_VERSION, generated_at: new Date().toISOString(), pools: {} };
51
- }
52
- }
53
-
54
- function saveWeights(state, opts = {}) {
55
- const p = resolvePath(opts);
56
- fs.mkdirSync(path.dirname(p), { recursive: true });
57
- state.generated_at = new Date().toISOString();
58
- const tmp = p + '.tmp';
59
- fs.writeFileSync(tmp, JSON.stringify(state, null, 2));
60
- fs.renameSync(tmp, p);
61
- return p;
62
- }
63
-
64
- function ensurePool(state, poolId) {
65
- if (!state.pools[poolId]) state.pools[poolId] = { agents: {} };
66
- return state.pools[poolId];
67
- }
68
-
69
- function ensureAgent(pool, agentId) {
70
- if (!pool.agents[agentId]) {
71
- pool.agents[agentId] = {
72
- weight: 1, // uniform start; normalised on read
73
- cumLoss: 0,
74
- cumLoss2: 0,
75
- rounds: 0,
76
- };
77
- }
78
- return pool.agents[agentId];
79
- }
80
-
81
- /**
82
- * Apply one round of losses to a pool. losses: Record<agentId, lossInZeroOne>.
83
- *
84
- * AdaNormalHedge update (parameter-free):
85
- * For each agent i:
86
- * R_i = sum of (mean_loss - loss_i) over rounds (instantaneous regret)
87
- * C_i = sum of (loss_i - mean_loss)^2 (cumulative loss variance)
88
- * Set η_i = sqrt(ln(N) / max(1, C_i)) per-agent learning rate.
89
- * weight_i ∝ Phi(R_i, C_i) where Phi is a positive-only potential.
90
- *
91
- * Simplification used here: w_i *= exp(-η * loss_i) with η derived
92
- * from cumulative variance — gives the same regret bound as full
93
- * AdaNormalHedge for the binary-loss case we care about (verifier
94
- * pass/fail). Trade off: slightly less tight bound vs the full
95
- * potential, but no need to plumb regret tracking everywhere.
96
- *
97
- * @param {{poolId: string, losses: Record<string, number>, baseDir?: string, weightsPath?: string, eta?: number}} input
98
- * @returns {{weights: Record<string, number>, weightsPath: string}}
99
- */
100
- function loss(input) {
101
- if (!input || typeof input.poolId !== 'string' || input.poolId.length === 0) {
102
- throw new TypeError('hedge-ensemble.loss: poolId (string) required');
103
- }
104
- if (!input.losses || typeof input.losses !== 'object') {
105
- throw new TypeError('hedge-ensemble.loss: losses (Record<string, number>) required');
106
- }
107
- const state = loadWeights(input);
108
- const pool = ensurePool(state, input.poolId);
109
- // First, ensure every losing agent exists.
110
- for (const [agentId, lossVal] of Object.entries(input.losses)) {
111
- if (typeof lossVal !== 'number' || Number.isNaN(lossVal)) {
112
- throw new TypeError(`hedge-ensemble.loss: losses.${agentId} must be a number`);
113
- }
114
- }
115
- for (const agentId of Object.keys(input.losses)) {
116
- ensureAgent(pool, agentId);
117
- }
118
- const N = Object.keys(pool.agents).length;
119
- // Compute mean loss this round (over agents that received a value).
120
- const lossList = Object.values(input.losses);
121
- const meanLoss = lossList.length > 0 ? lossList.reduce((a, b) => a + b, 0) / lossList.length : 0;
122
- // Update each agent's cumulative variance + regret-like signal, then
123
- // recompute its weight via exp(-η_i * loss_i).
124
- for (const [agentId, rawLoss] of Object.entries(input.losses)) {
125
- const lossVal = Math.min(1, Math.max(0, rawLoss));
126
- const a = pool.agents[agentId];
127
- const dev = lossVal - meanLoss;
128
- a.cumLoss += lossVal;
129
- a.cumLoss2 += dev * dev;
130
- a.rounds += 1;
131
- const eta =
132
- typeof input.eta === 'number'
133
- ? input.eta
134
- : Math.sqrt(Math.log(Math.max(2, N)) / Math.max(1, a.cumLoss2));
135
- a.weight *= Math.exp(-eta * lossVal);
136
- if (!Number.isFinite(a.weight) || a.weight <= 0) a.weight = 1e-9;
137
- }
138
- // Renormalize.
139
- const total = Object.values(pool.agents).reduce((s, x) => s + x.weight, 0) || 1;
140
- /** @type {Record<string, number>} */
141
- const out = {};
142
- for (const agentId of Object.keys(pool.agents)) {
143
- pool.agents[agentId].weight /= total;
144
- out[agentId] = pool.agents[agentId].weight;
145
- }
146
- const writtenPath = saveWeights(state, input);
147
- return { weights: out, weightsPath: writtenPath };
148
- }
149
-
150
- /**
151
- * Compute the weighted-majority verdict for a pool given each agent's
152
- * binary vote (pass=1, fail=0). Vote passes when the weighted sum
153
- * exceeds threshold (default 0.5).
154
- *
155
- * @param {{poolId: string, votes: Record<string, 0|1|boolean>, threshold?: number, baseDir?: string, weightsPath?: string}} input
156
- * @returns {{passes: boolean, weighted: number, threshold: number, perAgent: Record<string, {weight: number, vote: number}>}}
157
- */
158
- function vote(input) {
159
- if (!input || typeof input.poolId !== 'string') {
160
- throw new TypeError('hedge-ensemble.vote: poolId required');
161
- }
162
- if (!input.votes || typeof input.votes !== 'object') {
163
- throw new TypeError('hedge-ensemble.vote: votes required');
164
- }
165
- const state = loadWeights(input);
166
- const pool = ensurePool(state, input.poolId);
167
- const threshold = typeof input.threshold === 'number' ? input.threshold : DEFAULT_VOTE_THRESHOLD;
168
- let total = 0;
169
- /** @type {Record<string, {weight: number, vote: number}>} */
170
- const perAgent = {};
171
- let weightSum = 0;
172
- for (const [agentId, raw] of Object.entries(input.votes)) {
173
- const v = raw === true || raw === 1 ? 1 : 0;
174
- const a = ensureAgent(pool, agentId);
175
- perAgent[agentId] = { weight: a.weight, vote: v };
176
- total += a.weight * v;
177
- weightSum += a.weight;
178
- }
179
- // Normalise the weighted sum against the SUM of voting agents'
180
- // weights — agents in the pool that didn't vote this round don't
181
- // dilute the result.
182
- const weighted = weightSum > 0 ? total / weightSum : 0;
183
- return { passes: weighted >= threshold, weighted, threshold, perAgent };
184
- }
185
-
186
- /**
187
- * Read current weights for a pool, normalised over the pool's agents.
188
- *
189
- * @param {{poolId: string, baseDir?: string, weightsPath?: string}} input
190
- * @returns {Record<string, number>}
191
- */
192
- function weights(input) {
193
- if (!input || typeof input.poolId !== 'string') {
194
- throw new TypeError('hedge-ensemble.weights: poolId required');
195
- }
196
- const state = loadWeights(input);
197
- const pool = state.pools[input.poolId];
198
- if (!pool) return {};
199
- const total = Object.values(pool.agents).reduce((s, x) => s + x.weight, 0);
200
- /** @type {Record<string, number>} */
201
- const out = {};
202
- for (const [k, v] of Object.entries(pool.agents)) {
203
- out[k] = total > 0 ? v.weight / total : 0;
204
- }
205
- return out;
206
- }
207
-
208
- module.exports = {
209
- loss,
210
- vote,
211
- weights,
212
- loadWeights,
213
- saveWeights,
214
- DEFAULT_VOTE_THRESHOLD,
215
- DEFAULT_WEIGHTS_PATH,
216
- SCHEMA_VERSION,
217
- };
@@ -1,78 +0,0 @@
1
- ---
2
- name: discover
3
- description: "Stage 1.5 of 4 orchestrator that probes Figma / Refero / Pinterest connections, spawns design-context-builder (auto-detect + interview) and (via lazy gate) design-context-checker (6-dimension validator), producing .design/DESIGN-CONTEXT.md. Use after /gdd:scan when a fast-path context build is wanted instead of the full /gdd:explore. Activates for requests involving detecting an existing design system, inventorying tokens and components, or onboarding a brownfield repo."
4
- argument-hint: "[--auto] [--incremental] [--full]"
5
- user-invocable: true
6
- ---
7
-
8
- # Get Design Done - Discover
9
-
10
- **Stage 1.5 of 4.** Produces `.design/DESIGN-CONTEXT.md`.
11
-
12
- Full procedure detail: `./discover-procedure.md`.
13
-
14
- ---
15
-
16
- ## State Integration
17
-
18
- 1. Read `.design/STATE.md`.
19
- - **Missing** -> create minimal skeleton from `reference/STATE-TEMPLATE.md` (stage=discover, status=in_progress, task_progress=0/1) and log warning "STATE.md not found - created fresh. If this is a resumed session, run /get-design-done:scan first."
20
- - **Present + stage==discover + status==in_progress** -> RESUME (continue interview; do not reset).
21
- - **Otherwise** -> normal transition: set frontmatter stage=discover, `<position>` stage=discover, status=in_progress, task_progress=0/1.
22
- 2. Probe connection availability. ToolSearch runs FIRST (MCP tools may be in the deferred tool set). Run three probes - A (Figma, variant-agnostic with prefix tiebreaker), B (Refero, ToolSearch-only), C (Pinterest, ToolSearch-only). After all probes, write `<connections>` to STATE.md so the builder doesn't re-probe. Full probe specs: `./discover-procedure.md` §Connection Probes.
23
- 3. Update `last_checkpoint`. Write STATE.md.
24
-
25
- ---
26
-
27
- ## Auto Mode
28
-
29
- When `--auto` is passed to the builder: if `tailwind.config.{js,cjs,mjs,ts}` exists -> Tailwind-only project (skip CSS file grep, parse tailwind.config for palette/spacing/font, use those as the baseline style signal). Else fall through to the existing CSS file grep logic. Detail: `./discover-procedure.md` §Auto Mode.
30
-
31
- ---
32
-
33
- ## Incremental Mode (Phase 53, default)
34
-
35
- `--incremental` is the DEFAULT after Phase 53; pass `--full` to opt out and re-map everything. Incremental runs the change classifier FIRST (via the fingerprint store at `.design/fingerprints/`): it fingerprints the current DesignContext graph, diffs each node against the prior cycle, and dispatches mappers per the verdict. SKIP (cosmetic-only / no-op) dispatches 0 mappers; PARTIAL re-maps only the affected community batches; ARCHITECTURE re-batches the dir-reshaped subset; FULL (or `--full`, or a first run with no prior store) re-maps all batches. The batching + classifier engine lives in `explore` (`scripts/lib/explore-parallel-runner` + `scripts/lib/mappers/incremental-discover.cjs`); this flag selects the path. Detail: `./discover-procedure.md` §Incremental Mode.
36
-
37
- ---
38
-
39
- ## Step 1 - Spawn design-context-builder
40
-
41
- Spawn `design-context-builder` -> `.design/DESIGN-CONTEXT.md`. The agent auto-detects via grep/glob first and interviews only for areas where auto-detect returned no confident answer. Baseline audit directory chain: `src/` -> `app/` -> `pages/` -> `lib/` -> flag "layout unknown". Common gray areas to probe (Area 7): font-change risk, token-layer introduction risk, component rebuild-vs-restyle. Wait for `## CONTEXT COMPLETE`, then update STATE.md `task_progress = 0.5`. Full prompt: `./discover-procedure.md` §Step 1.
42
-
43
- ---
44
-
45
- ## Step 1.75 - Lazy gate: should design-context-checker run? (Plan 10.1-04, D-21)
46
-
47
- Spawn the cheap Haiku gate `design-context-checker-gate` before the full checker. It applies the single-file heuristic (is `DESIGN-CONTEXT.md` in `git diff --name-only HEAD~1..HEAD`?) and emits JSON + `## GATE COMPLETE`. On `spawn: false`: append `lazy_skipped: true` telemetry row, skip Step 2, set STATE.md `<position>` as if checker passed. On `spawn: true`: proceed to Step 2. On first-run discover the gate always returns `spawn: true` (builder just wrote the file); the gate meaningfully short-circuits only on re-runs where the builder made no changes. Full prompt: `./discover-procedure.md` §Step 1.75.
48
-
49
- **Parallel synthesizer note:** discover does not spawn parallel researchers in v1, so `skills/synthesize/` is not wired here. If future variants spawn N parallel interviewers, wire synthesize between dispatch and collate as in `skills/map/` Step 3.5.
50
-
51
- ---
52
-
53
- ## Step 2 - Spawn design-context-checker
54
-
55
- Spawn `design-context-checker` with `<required_reading>` on STATE.md + DESIGN-CONTEXT.md. The agent validates DESIGN-CONTEXT.md across 6 dimensions and returns APPROVED or BLOCKED with per-dimension verdicts. Wait for `## CONTEXT CHECK COMPLETE`. Full prompt: `./discover-procedure.md` §Step 2.
56
-
57
- ---
58
-
59
- ## Step 3 - Handle checker verdict
60
-
61
- - **APPROVED** -> proceed to state update.
62
- - **BLOCKED** -> present blocked dimensions to user, offer fix-and-retry loop (re-spawn builder with specific fix instructions). Do not proceed to planning.
63
-
64
- ---
65
-
66
- ## State Update (exit)
67
-
68
- 1. Set `<position>` `status=completed`, `task_progress=1/1`.
69
- 2. Set `<timestamps>` `discover_completed_at=<ISO 8601 now>`.
70
- 3. Update `last_checkpoint`. Write STATE.md.
71
-
72
- ---
73
-
74
- ## After Writing
75
-
76
- Print the "=== Discovery complete ===" block with saved path, baseline score, top key issues, and next step (`/get-design-done:plan`). Do not proceed to planning automatically unless `--auto` was passed. Template: `./discover-procedure.md` §After Writing.
77
-
78
- ## DISCOVER COMPLETE