@hegemonart/get-design-done 1.57.0 → 1.57.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +26 -41
- package/.claude-plugin/plugin.json +23 -48
- package/CHANGELOG.md +119 -0
- package/README.md +166 -511
- package/SKILL.md +2 -0
- package/agents/README.md +33 -36
- package/agents/a11y-mapper.md +3 -3
- package/agents/component-benchmark-harvester.md +6 -6
- package/agents/component-benchmark-synthesizer.md +3 -3
- package/agents/compose-executor.md +3 -3
- package/agents/cost-forecaster.md +2 -2
- package/agents/design-auditor.md +7 -7
- package/agents/design-authority-watcher.md +15 -15
- package/agents/design-context-builder.md +4 -4
- package/agents/design-context-checker-gate.md +1 -1
- package/agents/design-discussant.md +2 -2
- package/agents/design-doc-writer.md +1 -1
- package/agents/design-executor.md +2 -2
- package/agents/design-figma-writer.md +2 -2
- package/agents/design-fixer.md +7 -7
- package/agents/design-integration-checker-gate.md +1 -1
- package/agents/design-integration-checker.md +1 -1
- package/agents/design-paper-writer.md +3 -3
- package/agents/design-pencil-writer.md +1 -1
- package/agents/design-planner.md +21 -0
- package/agents/design-reflector.md +39 -39
- package/agents/design-research-synthesizer.md +1 -0
- package/agents/design-start-writer.md +1 -1
- package/agents/design-update-checker.md +5 -5
- package/agents/design-verifier-gate.md +1 -1
- package/agents/design-verifier.md +52 -48
- package/agents/ds-generator.md +2 -2
- package/agents/ds-migration-planner.md +4 -4
- package/agents/email-executor.md +9 -9
- package/agents/experiment-result-ingester.md +3 -3
- package/agents/flutter-executor.md +5 -5
- package/agents/gdd-graph-refresh.md +3 -3
- package/agents/gdd-intel-updater.md +2 -2
- package/agents/motion-mapper.md +2 -2
- package/agents/motion-verifier.md +4 -4
- package/agents/pdf-executor.md +8 -8
- package/agents/perf-analyzer.md +17 -17
- package/agents/pr-commenter.md +9 -9
- package/agents/prototype-gate.md +2 -2
- package/agents/quality-gate-runner.md +1 -1
- package/agents/rollout-coordinator.md +3 -3
- package/agents/swift-executor.md +4 -4
- package/agents/ticket-sync-agent.md +6 -6
- package/agents/user-research-synthesizer.md +2 -2
- package/connections/connections.md +44 -45
- package/connections/cursor.md +73 -0
- package/connections/preview.md +3 -3
- package/dist/claude-code/.claude/skills/cache-manager/SKILL.md +3 -3
- package/dist/claude-code/.claude/skills/cache-manager/cache-policy.md +1 -1
- package/dist/claude-code/.claude/skills/design/SKILL.md +19 -0
- package/dist/claude-code/.claude/skills/explore/SKILL.md +11 -0
- package/dist/claude-code/.claude/skills/figma-write/SKILL.md +13 -2
- package/dist/claude-code/.claude/skills/paper-write/SKILL.md +54 -0
- package/dist/claude-code/.claude/skills/pencil-write/SKILL.md +54 -0
- package/dist/claude-code/.claude/skills/report-issue/SKILL.md +2 -2
- package/dist/claude-code/.claude/skills/router/SKILL.md +2 -2
- package/dist/claude-code/.claude/skills/verify/verify-procedure.md +10 -11
- package/dist/claude-code/.claude/skills/warm-cache/SKILL.md +1 -1
- package/hooks/budget-enforcer.ts +5 -4
- package/hooks/first-run-nudge.cjs +171 -0
- package/hooks/gdd-intel-trigger.js +243 -0
- package/hooks/gdd-mcp-circuit-breaker.js +62 -7
- package/hooks/gdd-precompact-snapshot.js +50 -29
- package/hooks/gdd-protected-paths.js +175 -20
- package/hooks/gdd-read-injection-scanner.ts +9 -1
- package/hooks/gdd-risk-gate.js +110 -8
- package/hooks/gdd-sessionstart-recap.js +59 -24
- package/hooks/hooks.json +13 -4
- package/hooks/inject-using-gdd.cjs +188 -0
- package/hooks/update-check.cjs +511 -0
- package/package.json +9 -2
- package/reference/STATE-TEMPLATE.md +10 -13
- package/reference/audit-scoring.md +1 -1
- package/reference/cache-tier-doctrine.md +46 -0
- package/reference/config-schema.md +9 -9
- package/reference/i18n.md +1 -1
- package/reference/intel-schema.md +37 -2
- package/reference/meta-rules.md +4 -4
- package/reference/model-tiers.md +2 -2
- package/reference/registry.json +101 -94
- package/reference/runtime-models.md +11 -1
- package/reference/shared-preamble.md +13 -14
- package/reference/skill-graph.md +24 -1
- package/scripts/bootstrap.cjs +373 -0
- package/scripts/injection-patterns.cjs +58 -0
- package/scripts/lib/apply-reflections/incubator-proposals.cjs +57 -26
- package/scripts/lib/design-search.cjs +20 -2
- package/scripts/lib/install/converters/codex-plugin.cjs +5 -2
- package/scripts/lib/install/converters/cursor.cjs +20 -0
- package/scripts/lib/issue-reporter/report-flow.cjs +1 -1
- package/scripts/lib/manifest/skills.json +80 -13
- package/scripts/lib/state/migrate-to-sqlite.cjs +23 -7
- package/scripts/lib/state/query-surface.cjs +86 -16
- package/scripts/lib/state/render-markdown.cjs +26 -14
- package/scripts/lib/state/state-store.cjs +141 -68
- package/sdk/cli/commands/stage.ts +17 -0
- package/sdk/cli/index.js +21 -1
- package/sdk/dashboard/data/_pkg-root.cjs +4 -4
- package/sdk/dashboard/data/risk-surface.cjs +54 -19
- package/sdk/dashboard/tui/index.cjs +28 -2
- package/sdk/mcp/gdd-state/server.js +7 -1
- package/sdk/state/index.ts +11 -1
- package/skills/cache-manager/SKILL.md +3 -3
- package/skills/cache-manager/cache-policy.md +1 -1
- package/skills/design/SKILL.md +19 -0
- package/skills/explore/SKILL.md +11 -0
- package/skills/figma-write/SKILL.md +13 -2
- package/skills/paper-write/SKILL.md +54 -0
- package/skills/pencil-write/SKILL.md +54 -0
- package/skills/report-issue/SKILL.md +2 -2
- package/skills/router/SKILL.md +2 -2
- package/skills/verify/verify-procedure.md +10 -11
- package/skills/warm-cache/SKILL.md +1 -1
- package/hooks/first-run-nudge.sh +0 -82
- package/hooks/inject-using-gdd.sh +0 -72
- package/hooks/update-check.sh +0 -251
- package/scripts/lib/audit-aggregator/index.cjs +0 -219
- package/scripts/lib/hedge-ensemble.cjs +0 -217
package/sdk/cli/index.js
CHANGED
|
@@ -4014,7 +4014,13 @@ function migrationActive(statePath) {
|
|
|
4014
4014
|
const backend = _loadBackend();
|
|
4015
4015
|
if (backend === null || backend.BACKEND !== "sqlite") return false;
|
|
4016
4016
|
const sqliteSibling = (0, import_node_path4.join)((0, import_node_path4.dirname)(statePath), "state.sqlite");
|
|
4017
|
-
|
|
4017
|
+
if (!(0, import_node_fs5.existsSync)(sqliteSibling)) return false;
|
|
4018
|
+
try {
|
|
4019
|
+
if ((0, import_node_fs5.statSync)(sqliteSibling).isDirectory()) return false;
|
|
4020
|
+
} catch {
|
|
4021
|
+
return false;
|
|
4022
|
+
}
|
|
4023
|
+
return true;
|
|
4018
4024
|
}
|
|
4019
4025
|
async function read(path) {
|
|
4020
4026
|
const raw = (0, import_node_fs5.readFileSync)(path, "utf8");
|
|
@@ -8247,6 +8253,14 @@ var VALID_STAGE_NAMES = /* @__PURE__ */ new Set([
|
|
|
8247
8253
|
"verify",
|
|
8248
8254
|
"discuss"
|
|
8249
8255
|
]);
|
|
8256
|
+
var TOP_LEVEL_COMMANDS_OFTEN_CONFUSED_FOR_STAGES = /* @__PURE__ */ new Set([
|
|
8257
|
+
"audit",
|
|
8258
|
+
"build",
|
|
8259
|
+
"dashboard",
|
|
8260
|
+
"init",
|
|
8261
|
+
"query",
|
|
8262
|
+
"run"
|
|
8263
|
+
]);
|
|
8250
8264
|
async function stageCommand(args, deps = {}) {
|
|
8251
8265
|
const stdout = deps.stdout ?? process.stdout;
|
|
8252
8266
|
const stderr = deps.stderr ?? process.stderr;
|
|
@@ -8265,6 +8279,12 @@ async function stageCommand(args, deps = {}) {
|
|
|
8265
8279
|
`gdd-sdk stage: "${stageName}" is not one of brief|explore|plan|design|verify|discuss
|
|
8266
8280
|
`
|
|
8267
8281
|
);
|
|
8282
|
+
if (TOP_LEVEL_COMMANDS_OFTEN_CONFUSED_FOR_STAGES.has(stageName)) {
|
|
8283
|
+
stderr.write(
|
|
8284
|
+
`gdd-sdk stage: did you mean \`gdd-sdk ${stageName}\`? "${stageName}" is a top-level subcommand, not a pipeline stage.
|
|
8285
|
+
`
|
|
8286
|
+
);
|
|
8287
|
+
}
|
|
8268
8288
|
return 3;
|
|
8269
8289
|
}
|
|
8270
8290
|
let flags;
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* resolve a cross-tree sibling via a fixed `__dirname`-relative `../../..`
|
|
7
7
|
* jump, because that breaks the moment a file is copied/moved or the layout
|
|
8
8
|
* shifts. Instead, walk UP from this file's directory until we find the GDD
|
|
9
|
-
* package.json (identified by `name === 'get-design-done'`), and
|
|
10
|
-
* in-repo siblings relative to that root.
|
|
9
|
+
* package.json (identified by `name === '@hegemonart/get-design-done'`), and
|
|
10
|
+
* resolve all in-repo siblings relative to that root.
|
|
11
11
|
*
|
|
12
12
|
* Even though these dashboard `.cjs` files are NOT esbuild-bundled (R8 — the
|
|
13
13
|
* bin trampoline runs them directly so the Phase 53 __dirname-rewrite trap
|
|
@@ -23,7 +23,7 @@ let _cachedRoot = null;
|
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Walk up from `startDir` looking for the GDD package root. The GDD root is
|
|
26
|
-
* the first ancestor whose package.json declares `name: "get-design-done"`;
|
|
26
|
+
* the first ancestor whose package.json declares `name: "@hegemonart/get-design-done"`;
|
|
27
27
|
* if no such marker is found (e.g. running from an unusual layout), fall back
|
|
28
28
|
* to the FIRST ancestor that has any package.json, then to `startDir`.
|
|
29
29
|
*
|
|
@@ -44,7 +44,7 @@ function findPackageRoot(startDir) {
|
|
|
44
44
|
}
|
|
45
45
|
if (pkg) {
|
|
46
46
|
if (firstWithPkg === null) firstWithPkg = dir;
|
|
47
|
-
if (pkg.name === 'get-design-done') return dir;
|
|
47
|
+
if (pkg.name === '@hegemonart/get-design-done') return dir;
|
|
48
48
|
}
|
|
49
49
|
const parent = path.dirname(dir);
|
|
50
50
|
if (parent === dir) break;
|
|
@@ -33,15 +33,20 @@
|
|
|
33
33
|
* (absent / unknown) -> default
|
|
34
34
|
*/
|
|
35
35
|
|
|
36
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* Canonical action -> color map. Keys are lowercase (matching the emitter's
|
|
38
|
+
* suggested_action values from events.schema.json: allow/review/
|
|
39
|
+
* require_confirmation/block). The display label is separate from the key so
|
|
40
|
+
* the map can do a single case-insensitive lookup.
|
|
41
|
+
*/
|
|
37
42
|
const ACTION_COLOR = Object.freeze({
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
43
|
+
allow: 'green',
|
|
44
|
+
review: 'yellow',
|
|
45
|
+
require_confirmation: 'orange',
|
|
46
|
+
block: 'red',
|
|
42
47
|
});
|
|
43
48
|
|
|
44
|
-
/** The set of recognized suggested-action values (Phase 56 vocabulary). */
|
|
49
|
+
/** The set of recognized suggested-action values (Phase 56 vocabulary, lowercase). */
|
|
45
50
|
const VALID_ACTIONS = Object.freeze(Object.keys(ACTION_COLOR));
|
|
46
51
|
|
|
47
52
|
/** The blank placeholder row emitted pre-56 (or for malformed/absent input). */
|
|
@@ -66,34 +71,64 @@ function finiteOrNull(v) {
|
|
|
66
71
|
}
|
|
67
72
|
|
|
68
73
|
/**
|
|
69
|
-
*
|
|
74
|
+
* Canonicalize a suggested_action to its lowercase snake_case key for lookup.
|
|
75
|
+
* Handles the emitter's lowercase values (allow/review/require_confirmation/block)
|
|
76
|
+
* AND legacy CamelCase (Allow/Review/RequireConfirmation/Block) - the CamelCase
|
|
77
|
+
* 'RequireConfirmation' lowercases to 'requireconfirmation' with no separator, so
|
|
78
|
+
* map that explicitly to 'require_confirmation'. Returns null for non-strings.
|
|
79
|
+
* @param {*} action
|
|
80
|
+
* @returns {string|null}
|
|
81
|
+
*/
|
|
82
|
+
function canonAction(action) {
|
|
83
|
+
if (typeof action !== 'string') return null;
|
|
84
|
+
let s = action.trim().toLowerCase().replace(/[\s-]+/g, '_');
|
|
85
|
+
if (s === 'requireconfirmation') s = 'require_confirmation';
|
|
86
|
+
return s;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Map a suggested_action to its display color. Case-insensitive so both
|
|
91
|
+
* 'allow' (emitter) and 'Allow' (legacy) resolve correctly. Unknown / absent -> 'default'.
|
|
70
92
|
* @param {*} action
|
|
71
93
|
* @returns {'green'|'yellow'|'orange'|'red'|'default'}
|
|
72
94
|
*/
|
|
73
95
|
function colorForAction(action) {
|
|
74
|
-
|
|
75
|
-
|
|
96
|
+
const canon = canonAction(action);
|
|
97
|
+
if (canon !== null && Object.prototype.hasOwnProperty.call(ACTION_COLOR, canon)) {
|
|
98
|
+
return ACTION_COLOR[canon];
|
|
76
99
|
}
|
|
77
100
|
return 'default';
|
|
78
101
|
}
|
|
79
102
|
|
|
80
103
|
/**
|
|
81
|
-
* Surface the risk fields on ONE event/finding.
|
|
82
|
-
*
|
|
83
|
-
*
|
|
104
|
+
* Surface the risk fields on ONE event/finding. Accepts either a raw
|
|
105
|
+
* risk_assessment envelope (with a `.payload` sub-object) OR a bare payload
|
|
106
|
+
* object. When `.payload` is present it is used as the source of risk fields;
|
|
107
|
+
* otherwise `item` itself is inspected (bare-payload / legacy path).
|
|
84
108
|
*
|
|
85
|
-
*
|
|
109
|
+
* Reads `risk_score`, `confidence`, `suggested_action` WHEN PRESENT; otherwise
|
|
110
|
+
* returns the blank placeholder. PURE; NEVER throws.
|
|
111
|
+
*
|
|
112
|
+
* @param {*} item an event envelope or bare payload (may be missing risk fields pre-56)
|
|
86
113
|
* @returns {{risk_score:number|null, confidence:number|null,
|
|
87
114
|
* suggested_action:string|null, color:string}}
|
|
88
115
|
*/
|
|
89
116
|
function surfaceRiskOne(item) {
|
|
90
117
|
if (!item || typeof item !== 'object') return blankRow();
|
|
91
118
|
|
|
92
|
-
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
const
|
|
96
|
-
|
|
119
|
+
// Normalize: if the caller passed a full event envelope (with .payload), use the payload.
|
|
120
|
+
const src = (item.payload && typeof item.payload === 'object') ? item.payload : item;
|
|
121
|
+
|
|
122
|
+
const risk_score = finiteOrNull(src.risk_score);
|
|
123
|
+
const confidence = finiteOrNull(src.confidence);
|
|
124
|
+
const rawAction = src.suggested_action;
|
|
125
|
+
const canon = canonAction(rawAction);
|
|
126
|
+
const recognized =
|
|
127
|
+
canon !== null && Object.prototype.hasOwnProperty.call(ACTION_COLOR, canon);
|
|
128
|
+
// Preserve the action VERBATIM when recognized: the emitter sends lowercase
|
|
129
|
+
// (allow/review/require_confirmation/block), legacy callers may send CamelCase,
|
|
130
|
+
// and either is echoed back unchanged. Unrecognized / absent -> null.
|
|
131
|
+
const suggested_action = recognized ? rawAction : null;
|
|
97
132
|
|
|
98
133
|
// Pre-56: when NONE of the risk fields are present, emit the blank placeholder
|
|
99
134
|
// verbatim (color 'default') so the column reads as "not yet scored".
|
|
@@ -105,7 +140,7 @@ function surfaceRiskOne(item) {
|
|
|
105
140
|
risk_score,
|
|
106
141
|
confidence,
|
|
107
142
|
suggested_action,
|
|
108
|
-
color:
|
|
143
|
+
color: recognized ? ACTION_COLOR[canon] : 'default',
|
|
109
144
|
};
|
|
110
145
|
}
|
|
111
146
|
|
|
@@ -37,6 +37,21 @@ const readline = require('node:readline');
|
|
|
37
37
|
|
|
38
38
|
const ansi = require('./ansi.cjs');
|
|
39
39
|
|
|
40
|
+
// Lazily require the risk-surface helper (same dep-free constraint as the data plane).
|
|
41
|
+
let _surfaceRisk = null;
|
|
42
|
+
function getSurfaceRisk() {
|
|
43
|
+
if (_surfaceRisk === null) {
|
|
44
|
+
try {
|
|
45
|
+
({ surfaceRisk: _surfaceRisk } = require('../data/risk-surface.cjs'));
|
|
46
|
+
} catch {
|
|
47
|
+
// If the module is unavailable for any reason, fall back to a no-op that returns
|
|
48
|
+
// blank placeholder rows so the column still renders cleanly.
|
|
49
|
+
_surfaceRisk = () => ({ risk_score: null, confidence: null, suggested_action: null, color: 'default' });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return _surfaceRisk;
|
|
53
|
+
}
|
|
54
|
+
|
|
40
55
|
// Lazily require the data plane so `renderFrame` (the pure path) can be imported + unit-tested
|
|
41
56
|
// without paying for the data module's transitive requires. `run` resolves it on demand.
|
|
42
57
|
let _loadDashboardModel = null;
|
|
@@ -351,11 +366,22 @@ function bodyFindings(model, inner, scroll) {
|
|
|
351
366
|
if (tail.length === 0) {
|
|
352
367
|
lines.push(' ' + ansi.color('no events', { dim: true }));
|
|
353
368
|
} else {
|
|
369
|
+
const surfaceRisk = getSurfaceRisk();
|
|
354
370
|
for (const ev of tail) {
|
|
355
371
|
const name = (ev && (ev.event || ev.type || ev.kind)) || 'event';
|
|
356
|
-
//
|
|
372
|
+
// Phase-56+: surface risk/confidence from risk_assessment events.
|
|
373
|
+
// For pre-56 events that lack risk fields, surfaceRiskOne returns the blank placeholder.
|
|
374
|
+
const surfaced = (ev && ev.type === 'risk_assessment')
|
|
375
|
+
? surfaceRisk(ev)
|
|
376
|
+
: { risk_score: null, confidence: null, suggested_action: null, color: 'default' };
|
|
377
|
+
const riskText = surfaced.risk_score !== null
|
|
378
|
+
? ansi.color(surfaced.risk_score.toFixed(2), { fg: surfaced.color !== 'default' ? surfaced.color : undefined })
|
|
379
|
+
: ansi.color('·', { dim: true });
|
|
380
|
+
const confText = surfaced.confidence !== null
|
|
381
|
+
? String(surfaced.confidence.toFixed(2))
|
|
382
|
+
: ansi.color('·', { dim: true });
|
|
357
383
|
lines.push(ansi.columns(
|
|
358
|
-
[String(name),
|
|
384
|
+
[String(name), riskText, confText],
|
|
359
385
|
[Math.max(8, inner - 14), 5, 5],
|
|
360
386
|
));
|
|
361
387
|
}
|
|
@@ -1776,7 +1776,13 @@ function migrationActive(statePath) {
|
|
|
1776
1776
|
const backend = _loadBackend();
|
|
1777
1777
|
if (backend === null || backend.BACKEND !== "sqlite") return false;
|
|
1778
1778
|
const sqliteSibling = (0, import_node_path.join)((0, import_node_path.dirname)(statePath), "state.sqlite");
|
|
1779
|
-
|
|
1779
|
+
if (!(0, import_node_fs2.existsSync)(sqliteSibling)) return false;
|
|
1780
|
+
try {
|
|
1781
|
+
if ((0, import_node_fs2.statSync)(sqliteSibling).isDirectory()) return false;
|
|
1782
|
+
} catch {
|
|
1783
|
+
return false;
|
|
1784
|
+
}
|
|
1785
|
+
return true;
|
|
1780
1786
|
}
|
|
1781
1787
|
async function read(path2) {
|
|
1782
1788
|
const raw = (0, import_node_fs2.readFileSync)(path2, "utf8");
|
package/sdk/state/index.ts
CHANGED
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
renameSync,
|
|
34
34
|
unlinkSync,
|
|
35
35
|
existsSync,
|
|
36
|
+
statSync,
|
|
36
37
|
} from 'node:fs';
|
|
37
38
|
import { dirname, join, resolve } from 'node:path';
|
|
38
39
|
import { pathToFileURL } from 'node:url';
|
|
@@ -176,7 +177,16 @@ function migrationActive(statePath: string): boolean {
|
|
|
176
177
|
const backend = _loadBackend();
|
|
177
178
|
if (backend === null || backend.BACKEND !== 'sqlite') return false;
|
|
178
179
|
const sqliteSibling = join(dirname(statePath), 'state.sqlite');
|
|
179
|
-
|
|
180
|
+
if (!existsSync(sqliteSibling)) return false;
|
|
181
|
+
// BUG-07: a DIRECTORY named state.sqlite would cause existsSync to return true,
|
|
182
|
+
// and then every mutate() would throw when trying to open it as a database.
|
|
183
|
+
// Guard: if the path is a directory, treat migration as inactive.
|
|
184
|
+
try {
|
|
185
|
+
if (statSync(sqliteSibling).isDirectory()) return false;
|
|
186
|
+
} catch {
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
return true;
|
|
180
190
|
}
|
|
181
191
|
|
|
182
192
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gdd-cache-manager
|
|
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.
|
|
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.ts before every Agent spawn."
|
|
4
4
|
user-invocable: false
|
|
5
5
|
tools: Read, Bash, Write
|
|
6
6
|
disable-model-invocation: true
|
|
@@ -38,11 +38,11 @@ You are the deterministic cache-key computer and cache-manifest writer for the o
|
|
|
38
38
|
|
|
39
39
|
## Deterministic Input-Hash Algorithm
|
|
40
40
|
|
|
41
|
-
The canonical reference implementation (single source of truth; `hooks/budget-enforcer.
|
|
41
|
+
The canonical reference implementation (single source of truth; `hooks/budget-enforcer.ts` 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.
|
|
42
42
|
|
|
43
43
|
## Integration Points
|
|
44
44
|
|
|
45
|
-
- **`hooks/budget-enforcer.
|
|
45
|
+
- **`hooks/budget-enforcer.ts`** (Plan 10.1-01) reads the manifest on every Agent spawn. The hook already calls `cacheLookup(agent, inputHash)` against `.design/cache-manifest.json`. This skill is the authority on how `inputHash` is computed so the hook and any orchestrator agree byte-for-byte.
|
|
46
46
|
- **Orchestrators** (e.g., `skills/map/`, `skills/discover/`, `skills/plan/`) invoke Phase 1 (compute-key) + Phase 4 (write-result-on-completion) around each Agent spawn they launch. Phase 2 + Phase 3 are executed by the hook.
|
|
47
47
|
- **Warm-cache command** (`skills/warm-cache/SKILL.md`, Task 02) does not touch Layer B - it only primes Anthropic's 5-min prompt cache (Layer A). Do not confuse the two.
|
|
48
48
|
|
|
@@ -21,7 +21,7 @@ The two layers (D-08):
|
|
|
21
21
|
|
|
22
22
|
## Deterministic Input-Hash Algorithm (Layer B)
|
|
23
23
|
|
|
24
|
-
The canonical reference implementation (the single source of truth; `hooks/budget-enforcer.
|
|
24
|
+
The canonical reference implementation (the single source of truth; `hooks/budget-enforcer.ts` imports the same primitive via a shared helper):
|
|
25
25
|
|
|
26
26
|
```js
|
|
27
27
|
// Deterministic cache-key primitive (reference implementation)
|
package/skills/design/SKILL.md
CHANGED
|
@@ -79,6 +79,25 @@ Print the `=== Design stage complete ===` summary (tasks complete/total, deviati
|
|
|
79
79
|
|
|
80
80
|
After all tasks finish, if STATE.md `<connections>` has `figma: available`, offer the user the figma-write opt-in prompt (modes: annotate / tokenize / mappings, with optional `--dry-run`). Spawn `design-figma-writer` with the selected mode on "yes"; skip silently on "no". NEVER auto-run without confirmation. Full prompt + dispatch logic: `./design-procedure.md` §Figma Write Dispatch.
|
|
81
81
|
|
|
82
|
+
## Component Generator Dispatch
|
|
83
|
+
|
|
84
|
+
If the DESIGN-PLAN has a `task_type: component` task without a matching `src/components/*.tsx`, OR the brief / DESIGN-CONTEXT.md explicitly asks for a new component, AND STATE.md `<connections>` shows a generator connection (`21st-dev: available`, `magic-patterns: available`, `plasmic: available`, `builder-io: available`, or `v0-dev: available`); offer the component-generator opt-in.
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
Task("design-component-generator", """
|
|
88
|
+
mode: <21st|magic-patterns|plasmic|builder-io|v0-dev>
|
|
89
|
+
component_spec: <DESIGN-PLAN task summary + DESIGN-CONTEXT acceptance criteria>
|
|
90
|
+
required_reading:
|
|
91
|
+
- .design/STATE.md
|
|
92
|
+
- .design/DESIGN-PLAN.md
|
|
93
|
+
- .design/DESIGN-CONTEXT.md
|
|
94
|
+
""")
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Sequential (the agent is `parallel-safe: never`). Wait for the agent's `## design-component-generator complete.` marker. Skip silently when no generator connection is available OR no component task is pending. Auto-mode bypasses the prompt; otherwise prompt "Generate component via [tool]? (y/n)" and only spawn on "y".
|
|
98
|
+
|
|
99
|
+
The dispatch fires AFTER `design-executor` completes the hand-coded plan tasks. The agent's output (component file path + tokens used + provenance) is appended to `.design/DESIGN-SUMMARY.md` as a single `## Generated Components` section so verify can audit it.
|
|
100
|
+
|
|
82
101
|
<HARD-GATE>
|
|
83
102
|
Do NOT transition to verify (or invoke `/gdd:verify`) until `.design/DESIGN-SUMMARY.md` is committed. If this project uses a custom `.design` location, read the artifact path from `.design/STATE.md` rather than assuming the default.
|
|
84
103
|
</HARD-GATE>
|
package/skills/explore/SKILL.md
CHANGED
|
@@ -61,6 +61,16 @@ Run the canonical scan grep/glob inventory (POSIX ERE, preserving PLAT-01/02): c
|
|
|
61
61
|
- **Project-local skills**: read `./.claude/skills/design-*-conventions.md` -> include in DESIGN-CONTEXT.md `<project_conventions>` (these override defaults).
|
|
62
62
|
- **Global skills**: `~/.claude/gdd/global-skills/*.md` (other than README) -> prepend to `<project_conventions>` under `<global_conventions>` sub-block. Project-local D-XX wins on conflict.
|
|
63
63
|
|
|
64
|
+
## Step 2.6 - Graph review (gate then reviewer)
|
|
65
|
+
|
|
66
|
+
Runs only when Step 2's mapper batch + synthesizer produced `.design/context-graph.json`. Skip the whole step if the file is absent (pre-Phase-52 project, or `--skip-scan`).
|
|
67
|
+
|
|
68
|
+
1. **Gate first (cheap Haiku check).** Spawn `design-context-reviewer-gate` via `Task()` with the classifier signal from Step 2's incremental batching pass: `change_pct` (fingerprint classifier `pct`), `classifier_action` (`SKIP` / `PARTIAL_UPDATE` / `ARCHITECTURE_UPDATE` / `FULL_UPDATE`), and `graph_path: ".design/context-graph.json"`. Gate emits a single-line `{spawn, rationale}` JSON decision then `## GATE COMPLETE`.
|
|
69
|
+
2. **If `spawn: false`**: record `mcp__gdd_state__set_status: "explore_graph_review_skipped"`, log the gate `rationale` (e.g., "project change 3% < 5% threshold"), set telemetry `lazy_skipped: true`. Done - proceed to Step 3.
|
|
70
|
+
3. **If `spawn: true`**: spawn `design-context-reviewer` via `Task()` with `<required_reading>` pointing at `.design/STATE.md`, `.design/context-graph.json`, `reference/design-context-schema.md`, `reference/design-context-tag-vocab.md`. The reviewer runs `scripts/validate-design-context.cjs --json` as the deterministic floor (checks 1/2/3/5) then layers the semantic checks (4/6/7/8/9) and returns the 9-check verdict inline (`APPROVED` or `REJECT`).
|
|
71
|
+
4. **Capture verdict (read-only contract).** The reviewer does NOT write `.design/DESIGN-CONTEXT-REVIEW.md` - it is `reads-only: true, writes: []`. WARN findings surface through `scripts/lib/health-mirror#getHealthChecks` as `status: 'warn'`; a hard-reject maps to `status: 'fail'`. Record the overall verdict via `mcp__gdd_state__set_status: "explore_graph_review_approved"` (or `"_rejected"`).
|
|
72
|
+
5. **On REJECT**: record `mcp__gdd_state__add_blocker` with the reviewer's blocking-issues list verbatim. Do not advance to Step 3 until the synthesizer or the implicated mapper is re-run. On `APPROVED` (with or without WARNs): proceed.
|
|
73
|
+
|
|
64
74
|
---
|
|
65
75
|
|
|
66
76
|
## Step 3 - Design interview (unless `--skip-interview`)
|
|
@@ -80,6 +90,7 @@ Full interview protocol + JSON line schema: `./explore-procedure.md` §Step 3.
|
|
|
80
90
|
## Step 4 - Close out explore
|
|
81
91
|
|
|
82
92
|
- If the synthesizer / mapper batch ran in Step 2: `mcp__gdd_state__update_progress` with `task_progress: "<done>/<total>"`, `status: "explore_mappers_done"`.
|
|
93
|
+
- If Step 2.6 ran the graph review: ensure the verdict status is recorded (`explore_graph_review_approved` / `_rejected` / `_skipped`); on `_rejected` do NOT checkpoint until re-run.
|
|
83
94
|
- `mcp__gdd_state__checkpoint` - bumps `last_checkpoint`.
|
|
84
95
|
- Stage advance to `plan` happens at the next stage's entry (plan owns its own `transition_stage`); do not edit frontmatter directly.
|
|
85
96
|
|
|
@@ -34,6 +34,17 @@ Read `.design/STATE.md` and `.design/DESIGN-CONTEXT.md` before dispatching the a
|
|
|
34
34
|
|
|
35
35
|
## Dispatch
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
```
|
|
38
|
+
Task("design-figma-writer", """
|
|
39
|
+
mode: <annotate|tokenize|mappings>
|
|
40
|
+
dry_run: <true|false>
|
|
41
|
+
confirm_shared: <true|false>
|
|
42
|
+
required_reading:
|
|
43
|
+
- .design/STATE.md
|
|
44
|
+
- .design/DESIGN-CONTEXT.md
|
|
45
|
+
""")
|
|
46
|
+
```
|
|
38
47
|
|
|
39
|
-
Pass
|
|
48
|
+
Pass `mode` from the first positional argument; `dry_run` from `--dry-run`;
|
|
49
|
+
`confirm_shared` from `--confirm-shared`. Wait for the agent's completion
|
|
50
|
+
marker before returning.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gdd-paper-write
|
|
3
|
+
description: "Push design decisions from `.design/DESIGN-CONTEXT.md` into the active paper.design canvas by dispatching the `design-paper-writer` agent in one of three modes (annotate / tokenize / roundtrip). Use when the user has completed a design pipeline cycle and wants the decisions reflected in their paper.design canvas. Operates proposal->confirm with `--dry-run`."
|
|
4
|
+
argument-hint: "<annotate|tokenize|roundtrip> [--dry-run]"
|
|
5
|
+
user-invocable: true
|
|
6
|
+
tools: Read, Write, Bash, Grep, Glob
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# gdd-paper-write
|
|
10
|
+
|
|
11
|
+
Dispatches the `design-paper-writer` agent to write design decisions back to the active paper.design canvas. The shared probe pattern (ToolSearch → live call → STATE.md write) and connection handshake are documented at `../../reference/shared-preamble.md#connection-handshake-summary` and `../../connections/paper-design.md`.
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
/get-design-done paper-write <mode> [--dry-run]
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Modes:
|
|
20
|
+
- `annotate` - add design decision comments to canvas nodes
|
|
21
|
+
- `tokenize` - sync CSS token values to paper.design node styles
|
|
22
|
+
- `roundtrip` - write implementation status back as text/HTML layers
|
|
23
|
+
|
|
24
|
+
Flags:
|
|
25
|
+
- `--dry-run` - emit the proposal without executing any paper.design writes
|
|
26
|
+
|
|
27
|
+
paper.design has no team-library concept, so there is no `--confirm-shared` flag. Every write still requires an explicit `yes` confirmation (unless `--dry-run` is set).
|
|
28
|
+
|
|
29
|
+
## Prerequisites
|
|
30
|
+
|
|
31
|
+
1. paper.design MCP registered. Install: `claude mcp add paper-design --transport http https://mcp.paper.design/sse` then restart the session. See `../../connections/paper-design.md` for the full probe pattern and budget rules.
|
|
32
|
+
2. `.design/DESIGN-CONTEXT.md` exists (run `discover` first)
|
|
33
|
+
3. `.design/STATE.md` `<connections>` shows `paper-design: available`. If `not_configured` or `unavailable`, the agent will STOP with a diagnostic.
|
|
34
|
+
|
|
35
|
+
Budget: the agent tracks `budget_used` in STATE.md `<connections>` and warns when usage reaches 90/100 on the free tier.
|
|
36
|
+
|
|
37
|
+
## Required Reading
|
|
38
|
+
|
|
39
|
+
Read `.design/STATE.md` and `.design/DESIGN-CONTEXT.md` before dispatching the agent.
|
|
40
|
+
|
|
41
|
+
## Dispatch
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
Task("design-paper-writer", """
|
|
45
|
+
mode: <annotate|tokenize|roundtrip>
|
|
46
|
+
dry_run: <true|false>
|
|
47
|
+
required_reading:
|
|
48
|
+
- .design/STATE.md
|
|
49
|
+
- .design/DESIGN-CONTEXT.md
|
|
50
|
+
""")
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Pass `mode` from the first positional argument; `dry_run` from `--dry-run`.
|
|
54
|
+
Wait for the agent's completion marker before returning.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gdd-pencil-write
|
|
3
|
+
description: "Update local `.pen` source files with design decisions from `.design/DESIGN-CONTEXT.md` by dispatching the `design-pencil-writer` agent in one of two modes (annotate / roundtrip). Use when the user has completed a design pipeline cycle and wants the decisions reflected in their `.pen` files. Operates proposal->confirm with `--dry-run`."
|
|
4
|
+
argument-hint: "<annotate|roundtrip> [--dry-run]"
|
|
5
|
+
user-invocable: true
|
|
6
|
+
tools: Read, Write, Bash, Grep, Glob
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# gdd-pencil-write
|
|
10
|
+
|
|
11
|
+
Dispatches the `design-pencil-writer` agent to write design decisions back to `.pen` spec files. Unlike Figma/paper.design, pencil.dev keeps `.pen` YAML specs as the project's git-tracked source of truth; no MCP is required and every write is committed atomically. The probe pattern (file-based, no ToolSearch) and integration contract are documented at `../../connections/pencil-dev.md`.
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
/get-design-done pencil-write <mode> [--dry-run]
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Modes:
|
|
20
|
+
- `annotate` - append DESIGN-DEBT findings as comments to the relevant `.pen` files
|
|
21
|
+
- `roundtrip` - update `.pen` spec frontmatter (design-tokens, state) from verified implementation
|
|
22
|
+
|
|
23
|
+
There is no `tokenize` mode; `.pen` files are source-of-truth specs, not derived artifacts.
|
|
24
|
+
|
|
25
|
+
Flags:
|
|
26
|
+
- `--dry-run` - emit the proposal without writing or committing any `.pen` changes
|
|
27
|
+
|
|
28
|
+
## Prerequisites
|
|
29
|
+
|
|
30
|
+
1. pencil.dev workspace detected; one or more `.pen` files in `cwd` (no MCP install required):
|
|
31
|
+
```bash
|
|
32
|
+
find . -name "*.pen" -not -path "*/node_modules/*" | head -5
|
|
33
|
+
```
|
|
34
|
+
2. `.design/DESIGN-CONTEXT.md` exists (run `discover` first). For `annotate` mode, `.design/DESIGN-DEBT.md` is also required. For `roundtrip` mode, `.design/DESIGN-VERIFICATION.md` is also required.
|
|
35
|
+
3. `.design/STATE.md` `<connections>` shows `pencil-dev: available`. If `not_configured`, no `.pen` files were found at probe time; re-run `discover` or `connections` after adding `.pen` specs.
|
|
36
|
+
|
|
37
|
+
## Required Reading
|
|
38
|
+
|
|
39
|
+
Read `.design/STATE.md` and `.design/DESIGN-CONTEXT.md` before dispatching the agent.
|
|
40
|
+
|
|
41
|
+
## Dispatch
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
Task("design-pencil-writer", """
|
|
45
|
+
mode: <annotate|roundtrip>
|
|
46
|
+
dry_run: <true|false>
|
|
47
|
+
required_reading:
|
|
48
|
+
- .design/STATE.md
|
|
49
|
+
- .design/DESIGN-CONTEXT.md
|
|
50
|
+
""")
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Pass `mode` from the first positional argument; `dry_run` from `--dry-run`.
|
|
54
|
+
Wait for the agent's completion marker before returning.
|
|
@@ -15,7 +15,7 @@ If invoked without an error context (the user just typed `/gdd:report-issue` col
|
|
|
15
15
|
|
|
16
16
|
## Steps
|
|
17
17
|
|
|
18
|
-
0. **Kill-switch** (D-08). Call `isDisabled()` from `scripts/lib/issue-reporter/kill-switch.cjs` FIRST. Either env (`GDD_DISABLE_ISSUE_REPORTER=1`) OR config (`.design/config.json` with `{ "issue_reporter": false }`) makes the command unavailable. Surface the disable line via `getDisableReason()` ('env' wins when both set) and stop. No draft, no triage, no payload.
|
|
18
|
+
0. **Kill-switch** (D-08). Call `isDisabled()` from `scripts/lib/issue-reporter/kill-switch.cjs` FIRST. Either env (`GDD_DISABLE_ISSUE_REPORTER=1`) OR config (`.design/config.json` with `{ "issue_reporter": false }`) makes the command unavailable. Surface the disable line via `getDisableReason()` ('env' wins when both set) and stop. No draft, no triage, no payload. `/gdd:health` mirrors the same line for at-a-glance verification.
|
|
19
19
|
1. **Triage**. Call `matchKnownFailure(errorContext)` from `scripts/lib/issue-reporter/triage-matcher.cjs` (Plan 30-03). If `matched === true` and `--force-report` is NOT set: print the suggested diagnosis + remedy, stop. Do NOT write a draft. (D-07)
|
|
20
20
|
2. **Assemble**. Call `assemble(commandName, errorContext, trajectoryRef?, capabilityGapEvent?)` from `scripts/lib/issue-reporter/payload-assembly.cjs` (Plan 30-02). This layers Phase 22 redact → Phase 30 pseudonymize, computes the fingerprint, and renders bilingual disclaimer + sections.
|
|
21
21
|
3. **Draft**. Call `writeDraft({title, body, fingerprint})` from `scripts/lib/issue-reporter/draft-writer.cjs`. Print the absolute path: `Draft written to .design/issue-drafts/<timestamp>-<fp8>.md`. The file persists across decline - the user keeps their work either way. (D-04)
|
|
@@ -48,6 +48,6 @@ Available on `/gdd:report-issue`. Overrides the triage gate (Step 1) but does NO
|
|
|
48
48
|
- **No `EDITOR` set.** The path is printed; open it in whatever editor you prefer, save, then return to the consent prompt.
|
|
49
49
|
- **Triage matched something irrelevant.** Pass `--force-report` to bypass the gate. Consent is still required.
|
|
50
50
|
- **`gh` not installed (D-10).** After consent, the payload is copied to your clipboard and an issue-template URL is printed. Paste into the URL to file manually. Install `gh` later and the existing draft can be re-submitted.
|
|
51
|
-
- **Command unavailable / disabled (D-08).** Run
|
|
51
|
+
- **Command unavailable / disabled (D-08).** Run `/gdd:health`. The `issue reporter:` line shows the active disable surface - either `disabled by env (GDD_DISABLE_ISSUE_REPORTER=1)` or `disabled by config (.design/config.json: issue_reporter=false)`. Unset the env var or flip the config key to re-enable.
|
|
52
52
|
|
|
53
53
|
See [report-issue-procedure.md](./report-issue-procedure.md) for the full procedure with rationale per decision (D-02, D-03, D-04, D-05, D-07, D-11).
|
package/skills/router/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gdd-router
|
|
3
|
-
description: "Routes a /gdd command to fast|quick|full path + S|M|L|XL complexity_class and returns {path, complexity_class, model_tier_overrides, resolved_models, estimated_cost_usd, cache_hits}. Deterministic - no model call. Invoked once at command entry before any Agent spawn. Read by hooks/budget-enforcer.
|
|
3
|
+
description: "Routes a /gdd command to fast|quick|full path + S|M|L|XL complexity_class and returns {path, complexity_class, model_tier_overrides, resolved_models, estimated_cost_usd, cache_hits}. Deterministic - no model call. Invoked once at command entry before any Agent spawn. Read by hooks/budget-enforcer.ts."
|
|
4
4
|
argument-hint: "<intent-string> [<target-artifacts-csv>]"
|
|
5
5
|
tools: Read, Bash, Grep
|
|
6
6
|
---
|
|
@@ -9,7 +9,7 @@ tools: Read, Bash, Grep
|
|
|
9
9
|
|
|
10
10
|
## Role
|
|
11
11
|
|
|
12
|
-
You are a deterministic routing skill. You do not spawn agents. You read `.design/budget.json`, `reference/model-prices.md`, `.design/cache-manifest.json` (if present), and the agent frontmatter list, then emit a single JSON object describing the planned spawn graph. The budget-enforcer hook (`hooks/budget-enforcer.
|
|
12
|
+
You are a deterministic routing skill. You do not spawn agents. You read `.design/budget.json`, `reference/model-prices.md`, `.design/cache-manifest.json` (if present), and the agent frontmatter list, then emit a single JSON object describing the planned spawn graph. The budget-enforcer hook (`hooks/budget-enforcer.ts`) consumes your output on every `Agent` tool call.
|
|
13
13
|
|
|
14
14
|
## Invocation Contract
|
|
15
15
|
|
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
name: verify-procedure
|
|
3
3
|
type: meta-rules
|
|
4
4
|
version: 1.0.0
|
|
5
|
-
phase: 28.5
|
|
6
5
|
tags: [verify, procedure, extracted, pipeline-stage, gap-loop, must-have, quality-gate]
|
|
7
6
|
last_updated: 2026-05-18
|
|
8
7
|
---
|
|
9
8
|
|
|
10
|
-
Source: extracted from `skills/verify/SKILL.md`
|
|
9
|
+
Source: extracted from `skills/verify/SKILL.md` to keep the SKILL focused on the essential workflow.
|
|
11
10
|
The skill's essential workflow stays in `../skills/verify/SKILL.md`; this file holds the
|
|
12
11
|
detail the agent reaches for when executing a specific step (state integration, quality-gate
|
|
13
12
|
decision tree, agent spawn protocols, gap-response loop, must-have flipping).
|
|
@@ -28,9 +27,9 @@ methodology, agent prompts, and gap-loop semantics.
|
|
|
28
27
|
1. `mcp__gdd_state__transition_stage` with `to: "verify"`.
|
|
29
28
|
2. `mcp__gdd_state__get` → snapshot `state`. Read `state.must_haves` - this is the verification checklist; each M-XX starts at `status: pending` and will be flipped to `pass` or `fail` as verification concludes.
|
|
30
29
|
|
|
31
|
-
#### Step 2.5 - Quality-gate gate
|
|
30
|
+
#### Step 2.5 - Quality-gate gate
|
|
32
31
|
|
|
33
|
-
Before resume detection, inspect `state.quality_gate` from the same snapshot. The
|
|
32
|
+
Before resume detection, inspect `state.quality_gate` from the same snapshot. The quality-gate skill (see `skills/quality-gate/SKILL.md`) writes a single `<run/>` element capturing the most recent run; this step is the verify-side consumer of that result. Three branches, evaluated in order:
|
|
34
33
|
|
|
35
34
|
- **`state.quality_gate?.run?.status === "fail"`** → Refuse to advance. The fix loop in `quality-gate/SKILL.md` Step 4 reached `max_iters` without converging, and the verify stage MUST NOT paper over it. Print a blocker reason that includes the iteration count and the `commands_run` field from the run, then call:
|
|
36
35
|
|
|
@@ -43,9 +42,9 @@ Before resume detection, inspect `state.quality_gate` from the same snapshot. Th
|
|
|
43
42
|
|
|
44
43
|
Exit immediately with the failure surface visible to the user. Do NOT call `mcp__gdd_state__update_progress` to open the verify stage; the gate refused entry, so the stage was never opened.
|
|
45
44
|
|
|
46
|
-
- **`state.quality_gate?.run?.status === "timeout"` OR `=== "skipped"`** → Print a one-line warning naming the status and the `commands_run` value, then continue normally.
|
|
45
|
+
- **`state.quality_gate?.run?.status === "timeout"` OR `=== "skipped"`** → Print a one-line warning naming the status and the `commands_run` value, then continue normally. These are signals, not walls: a slow test suite must not hostage the pipeline, and a project with no detectable quality commands must not block verify entry. The warning surfaces the degraded state without halting.
|
|
47
46
|
|
|
48
|
-
- **`state.quality_gate?.run?.status === "pass"` OR `state.quality_gate === null`** → Continue silently. `pass` is the happy path; `null` means the gate has never been run for this cycle (the user skipped
|
|
47
|
+
- **`state.quality_gate?.run?.status === "pass"` OR `state.quality_gate === null`** → Continue silently. `pass` is the happy path; `null` means the gate has never been run for this cycle (the user skipped the quality-gate stage entirely, which is permitted - verify only *checks* the gate result, never *runs* the gate itself).
|
|
49
48
|
|
|
50
49
|
This step is a pure read against the snapshot already loaded in Step 2 - no extra MCP call is required.
|
|
51
50
|
|
|
@@ -93,7 +92,7 @@ Step P2 — Live tool call:
|
|
|
93
92
|
Record the preview probe result via `mcp__gdd_state__probe_connections` (batched with the storybook and chromatic probes below — one call per stage, see "Batched connections write" at the end of this section).
|
|
94
93
|
```
|
|
95
94
|
|
|
96
|
-
When `preview: available`, the design-verifier agent runs
|
|
95
|
+
When `preview: available`, the design-verifier agent runs Stage 4B - Screenshot Evidence to resolve `? VISUAL` heuristic flags with real screenshot evidence. See `agents/design-verifier.md` Stage 4B for the screenshot evidence loop.
|
|
97
96
|
|
|
98
97
|
### Probe Storybook connection
|
|
99
98
|
|
|
@@ -202,7 +201,7 @@ Initialize iteration counter to 0 (used for fix loop limit in Step 3).
|
|
|
202
201
|
|
|
203
202
|
Three agents run in sequence. Each waits for its completion marker before the next is spawned.
|
|
204
203
|
|
|
205
|
-
**Note on lazy gates
|
|
204
|
+
**Note on lazy gates:** Each full checker is preceded by a cheap Haiku gate that reads the diff and may return `{spawn: false}` to short-circuit. When gated out, `lazy_skipped: true` is appended to `.design/telemetry/costs.jsonl`. Gates: `design-verifier-gate` (before 1b), `design-integration-checker-gate` (before 1c). `design-context-checker-gate` is wired into `skills/discover/SKILL.md` Step 1.75.
|
|
206
205
|
|
|
207
206
|
### 1a. Run design-auditor first (retrospective 7-pillar audit)
|
|
208
207
|
|
|
@@ -274,9 +273,9 @@ Task("design-verifier", """
|
|
|
274
273
|
You are the design-verifier agent. Run the 5-phase verification against completed design work.
|
|
275
274
|
|
|
276
275
|
DESIGN-AUDIT.md (above) contains a retrospective 7-pillar qualitative audit from design-auditor.
|
|
277
|
-
Read it as supplementary signal — incorporate the priority fix list into your
|
|
276
|
+
Read it as supplementary signal — incorporate the priority fix list into your Stage 5 gap analysis
|
|
278
277
|
where relevant. The auditor's 1-4 scores complement your 0-10 category scores; they do not
|
|
279
|
-
replace your
|
|
278
|
+
replace your Stage 1 category scoring.
|
|
280
279
|
|
|
281
280
|
Context:
|
|
282
281
|
auto_mode: <true|false>
|
|
@@ -432,7 +431,7 @@ Task("design-fixer", """
|
|
|
432
431
|
@.design/DESIGN-CONTEXT.md
|
|
433
432
|
</required_reading>
|
|
434
433
|
|
|
435
|
-
Fix all BLOCKER and MAJOR gaps from ##
|
|
434
|
+
Fix all BLOCKER and MAJOR gaps from ## Stage 5 - Gaps in DESIGN-VERIFICATION.md.
|
|
436
435
|
For each gap: apply the targeted fix to the file/location in the gap's Location field.
|
|
437
436
|
After each fix, make an atomic commit: fix(design-gap-GNN): [gap title].
|
|
438
437
|
|
|
@@ -62,7 +62,7 @@ Full + filtered command-output examples live in `./../cache-manager/cache-policy
|
|
|
62
62
|
|
|
63
63
|
- **Pre-sprint**: `/gdd:warm-cache` is the recommended first line of a `/gdd:discover`, `/gdd:plan`, or `/gdd:verify` sprint. Users type it before the real command, or an orchestrator-level wrapper runs it automatically if `agent-metrics.json` (Plan 10.1-05) indicates the last sprint was > 5 min ago.
|
|
64
64
|
- **`reference/shared-preamble.md`** (authored in Plan 10.1-04) is the essential file for this command - agents import it first per D-17, which makes the first N tokens of every agent's rendered system prompt identical, which is what Anthropic's prompt cache keys on.
|
|
65
|
-
- **No interaction with `hooks/budget-enforcer.
|
|
65
|
+
- **No interaction with `hooks/budget-enforcer.ts`** - the hook is a PreToolUse gate; warm-cache runs as an ordinary Agent tool call itself and is subject to the hook (each no-op Haiku ping is budgeted and logged like any other spawn). This is intentional: warm-cache's own telemetry rows in `.design/telemetry/costs.jsonl` are the evidence that cache priming happened.
|
|
66
66
|
|
|
67
67
|
## Cost Model
|
|
68
68
|
|