@hegemonart/get-design-done 1.31.0 → 1.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +75 -0
- package/NOTICE +262 -0
- package/README.md +13 -1
- package/SKILL.md +4 -0
- package/agents/design-authority-watcher.md +1 -1
- package/agents/perf-analyzer.md +2 -2
- package/bin/gdd-mcp +78 -0
- package/bin/gdd-sdk +34 -24
- package/bin/gdd-state-mcp +78 -0
- package/{README.de.md → docs/i18n/README.de.md} +1 -1
- package/{README.fr.md → docs/i18n/README.fr.md} +1 -1
- package/{README.it.md → docs/i18n/README.it.md} +1 -1
- package/{README.ja.md → docs/i18n/README.ja.md} +1 -1
- package/{README.ko.md → docs/i18n/README.ko.md} +1 -1
- package/{README.zh-CN.md → docs/i18n/README.zh-CN.md} +1 -1
- package/hooks/_hook-emit.js +1 -1
- package/hooks/budget-enforcer.ts +5 -5
- package/hooks/context-exhaustion.ts +2 -2
- package/hooks/gdd-precompact-snapshot.js +3 -3
- package/hooks/gdd-read-injection-scanner.ts +2 -2
- package/hooks/gdd-sessionstart-recap.js +1 -1
- package/hooks/gdd-turn-closeout.js +1 -1
- package/hooks/hooks.json +9 -0
- package/hooks/inject-using-gdd.sh +72 -0
- package/hooks/run-hook.cmd +35 -0
- package/package.json +20 -9
- package/recipes/.gitkeep +0 -0
- package/reference/schemas/events.schema.json +63 -1
- package/reference/schemas/recipe.schema.json +33 -0
- package/scripts/cli/gdd-events.mjs +5 -5
- package/scripts/lib/cache/gdd-cache-manager.cjs +1 -1
- package/scripts/lib/cli/index.ts +22 -160
- package/scripts/lib/connection-probe/index.cjs +1 -1
- package/scripts/lib/discuss-parallel-runner/aggregator.ts +1 -1
- package/scripts/lib/discuss-parallel-runner/index.ts +1 -1
- package/scripts/lib/error-classifier.cjs +24 -227
- package/scripts/lib/event-stream/index.ts +25 -193
- package/scripts/lib/gdd-errors/index.ts +24 -213
- package/scripts/lib/gdd-state/index.ts +23 -161
- package/scripts/lib/health-mirror/index.cjs +79 -1
- package/scripts/lib/iteration-budget.cjs +23 -199
- package/scripts/lib/jittered-backoff.cjs +24 -107
- package/scripts/lib/lockfile.cjs +23 -195
- package/scripts/lib/logger/index.ts +1 -1
- package/scripts/lib/parallelism-engine/concurrency-tuner.cjs +1 -1
- package/scripts/lib/perf-analyzer/index.cjs +1 -1
- package/scripts/lib/pipeline-runner/index.ts +4 -4
- package/scripts/lib/pipeline-runner/state-machine.ts +1 -1
- package/scripts/lib/prompt-dedup/index.cjs +1 -1
- package/scripts/lib/rate-guard.cjs +2 -2
- package/scripts/lib/recipe-loader.cjs +142 -0
- package/scripts/lib/session-runner/errors.ts +3 -3
- package/scripts/lib/session-runner/index.ts +3 -3
- package/scripts/lib/session-runner/transcript.ts +1 -1
- package/scripts/lib/tool-scoping/index.ts +1 -1
- package/scripts/mcp-servers/gdd-mcp/server.ts +29 -311
- package/scripts/mcp-servers/gdd-state/server.ts +28 -282
- package/sdk/README.md +45 -0
- package/{scripts/lib → sdk}/cli/commands/audit.ts +3 -3
- package/{scripts/lib → sdk}/cli/commands/init.ts +3 -3
- package/{scripts/lib → sdk}/cli/commands/query.ts +4 -4
- package/{scripts/lib → sdk}/cli/commands/run.ts +5 -5
- package/{scripts/lib → sdk}/cli/commands/stage.ts +5 -5
- package/sdk/cli/index.js +8091 -0
- package/sdk/cli/index.ts +172 -0
- package/{scripts/lib → sdk}/cli/parse-args.ts +2 -2
- package/{scripts/lib/gdd-errors → sdk/errors}/classification.ts +1 -1
- package/sdk/errors/index.ts +218 -0
- package/{scripts/lib → sdk}/event-stream/emitter.ts +1 -1
- package/sdk/event-stream/index.ts +197 -0
- package/{scripts/lib → sdk}/event-stream/reader.ts +1 -1
- package/{scripts/lib → sdk}/event-stream/types.ts +2 -2
- package/{scripts/lib → sdk}/event-stream/writer.ts +1 -1
- package/sdk/index.ts +19 -0
- package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/README.md +3 -3
- package/sdk/mcp/gdd-mcp/server.js +1966 -0
- package/sdk/mcp/gdd-mcp/server.ts +325 -0
- package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_cycle_recap.ts +3 -3
- package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_decisions_list.ts +2 -2
- package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_events_tail.ts +3 -3
- package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_health.ts +2 -2
- package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_intel_get.ts +2 -2
- package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_learnings_digest.ts +2 -2
- package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_phase_current.ts +2 -2
- package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_phases_list.ts +2 -2
- package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_plans_list.ts +2 -2
- package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_reflections_latest.ts +2 -2
- package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_status.ts +3 -3
- package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_telemetry_query.ts +3 -3
- package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/index.ts +2 -2
- package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/shared.ts +3 -3
- package/sdk/mcp/gdd-state/server.js +2790 -0
- package/sdk/mcp/gdd-state/server.ts +294 -0
- package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/add_blocker.ts +3 -3
- package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/add_decision.ts +3 -3
- package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/add_must_have.ts +3 -3
- package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/checkpoint.ts +2 -2
- package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/frontmatter_update.ts +2 -2
- package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/get.ts +3 -3
- package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/index.ts +1 -1
- package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/probe_connections.ts +3 -3
- package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/resolve_blocker.ts +3 -3
- package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/set_status.ts +2 -2
- package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/shared.ts +8 -8
- package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/transition_stage.ts +4 -4
- package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/update_progress.ts +2 -2
- package/sdk/primitives/error-classifier.cjs +232 -0
- package/sdk/primitives/iteration-budget.cjs +205 -0
- package/sdk/primitives/jittered-backoff.cjs +112 -0
- package/sdk/primitives/lockfile.cjs +201 -0
- package/{scripts/lib/gdd-state → sdk/state}/gates.ts +1 -1
- package/sdk/state/index.ts +167 -0
- package/{scripts/lib/gdd-state → sdk/state}/lockfile.ts +1 -1
- package/{scripts/lib/gdd-state → sdk/state}/mutator.ts +1 -1
- package/{scripts/lib/gdd-state → sdk/state}/parser.ts +1 -1
- package/{scripts/lib/gdd-state → sdk/state}/types.ts +4 -4
- package/skills/audit/SKILL.md +13 -0
- package/skills/brief/SKILL.md +25 -0
- package/skills/design/SKILL.md +17 -0
- package/skills/discuss/SKILL.md +13 -0
- package/skills/explore/SKILL.md +17 -0
- package/skills/health/SKILL.md +6 -0
- package/skills/plan/SKILL.md +25 -0
- package/skills/quality-gate/SKILL.md +2 -2
- package/skills/router/SKILL.md +4 -0
- package/skills/router/router-pick-emitter.md +78 -0
- package/skills/using-gdd/SKILL.md +78 -0
- package/skills/verify/SKILL.md +17 -0
- package/scripts/aggregate-agent-metrics.ts +0 -282
- package/scripts/bootstrap-manifest.txt +0 -3
- package/scripts/bootstrap.sh +0 -80
- package/scripts/build-distribution-bundles.cjs +0 -549
- package/scripts/build-intel.cjs +0 -486
- package/scripts/codegen-schema-types.ts +0 -149
- package/scripts/detect-stale-refs.cjs +0 -107
- package/scripts/e2e/run-headless.ts +0 -514
- package/scripts/extract-changelog-section.cjs +0 -58
- package/scripts/gsd-cleanup-incubator.cjs +0 -367
- package/scripts/injection-patterns.cjs +0 -58
- package/scripts/lint-agentskills-spec.cjs +0 -457
- package/scripts/release-smoke-test.cjs +0 -200
- package/scripts/rollback-release.sh +0 -42
- package/scripts/run-injection-scanner-ci.cjs +0 -83
- package/scripts/tests/test-authority-rejected-kinds.sh +0 -58
- package/scripts/tests/test-authority-watcher-diff.sh +0 -113
- package/scripts/tests/test-motion-provenance.sh +0 -64
- package/scripts/validate-frontmatter.ts +0 -409
- package/scripts/validate-incubator-scope.cjs +0 -133
- package/scripts/validate-schemas.ts +0 -401
- package/scripts/validate-skill-length.cjs +0 -283
- package/scripts/verify-version-sync.cjs +0 -30
- /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_cycle_recap.schema.json +0 -0
- /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_decisions_list.schema.json +0 -0
- /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_events_tail.schema.json +0 -0
- /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_health.schema.json +0 -0
- /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_intel_get.schema.json +0 -0
- /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_learnings_digest.schema.json +0 -0
- /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_phase_current.schema.json +0 -0
- /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_phases_list.schema.json +0 -0
- /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_plans_list.schema.json +0 -0
- /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_reflections_latest.schema.json +0 -0
- /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_status.schema.json +0 -0
- /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_telemetry_query.schema.json +0 -0
- /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/add_blocker.schema.json +0 -0
- /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/add_decision.schema.json +0 -0
- /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/add_must_have.schema.json +0 -0
- /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/checkpoint.schema.json +0 -0
- /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/frontmatter_update.schema.json +0 -0
- /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/get.schema.json +0 -0
- /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/probe_connections.schema.json +0 -0
- /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/resolve_blocker.schema.json +0 -0
- /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/set_status.schema.json +0 -0
- /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/transition_stage.schema.json +0 -0
- /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/update_progress.schema.json +0 -0
- /package/{scripts/lib → sdk/primitives}/error-classifier.d.cts +0 -0
- /package/{scripts/lib → sdk/primitives}/iteration-budget.d.cts +0 -0
- /package/{scripts/lib → sdk/primitives}/jittered-backoff.d.cts +0 -0
- /package/{scripts/lib → sdk/primitives}/lockfile.d.cts +0 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// bin/gdd-state-mcp — Plan 31-5-05 (SDK-03, D-08); dual-mode since Plan 31-5-9.5 (D-16).
|
|
3
|
+
//
|
|
4
|
+
// DUAL-MODE CJS trampoline for the `gdd-state` MCP server. Resolves the server
|
|
5
|
+
// entry and re-launches it under `node`, forwarding argv + exit code/signal.
|
|
6
|
+
// Two modes:
|
|
7
|
+
//
|
|
8
|
+
// • COMPILED (installed / packed): if the esbuild-bundled sibling
|
|
9
|
+
// `sdk/mcp/gdd-state/server.js` exists, spawn `node <js>` with NO flag.
|
|
10
|
+
// This is the path a user gets from `npm i` — the entry lives under
|
|
11
|
+
// node_modules where Node refuses --experimental-strip-types on `.ts`
|
|
12
|
+
// (ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING). `prepack` compiles the .js
|
|
13
|
+
// before every pack/publish (see scripts/build-sdk-bins.cjs).
|
|
14
|
+
// • SOURCE (in-repo dev): otherwise spawn
|
|
15
|
+
// `node --experimental-strip-types sdk/mcp/gdd-state/server.ts` — raw TS, no
|
|
16
|
+
// build step, exactly as before this plan.
|
|
17
|
+
//
|
|
18
|
+
// Why a trampoline at all:
|
|
19
|
+
// POSIX shebangs can use `#!/usr/bin/env -S node --experimental-strip-types`,
|
|
20
|
+
// but Windows cmd.exe does not honor shebangs and npm's auto-generated .cmd
|
|
21
|
+
// shim invokes plain `node bin/gdd-state-mcp` with no way to inject the flag.
|
|
22
|
+
// Mirrors the proven bin/gdd-sdk trampoline pattern.
|
|
23
|
+
|
|
24
|
+
'use strict';
|
|
25
|
+
|
|
26
|
+
const { spawn } = require('node:child_process');
|
|
27
|
+
const fs = require('node:fs');
|
|
28
|
+
const path = require('node:path');
|
|
29
|
+
|
|
30
|
+
// Sibling compiled JS (preferred) and the TS source (dev fallback).
|
|
31
|
+
const compiled = path.resolve(
|
|
32
|
+
__dirname,
|
|
33
|
+
'..',
|
|
34
|
+
'sdk',
|
|
35
|
+
'mcp',
|
|
36
|
+
'gdd-state',
|
|
37
|
+
'server.js',
|
|
38
|
+
);
|
|
39
|
+
const source = path.resolve(
|
|
40
|
+
__dirname,
|
|
41
|
+
'..',
|
|
42
|
+
'sdk',
|
|
43
|
+
'mcp',
|
|
44
|
+
'gdd-state',
|
|
45
|
+
'server.ts',
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
const useCompiled = fs.existsSync(compiled);
|
|
49
|
+
const entry = useCompiled ? compiled : source;
|
|
50
|
+
const nodeArgs = useCompiled
|
|
51
|
+
? [entry, ...process.argv.slice(2)]
|
|
52
|
+
: ['--experimental-strip-types', entry, ...process.argv.slice(2)];
|
|
53
|
+
|
|
54
|
+
const child = spawn(process.execPath, nodeArgs, {
|
|
55
|
+
stdio: 'inherit',
|
|
56
|
+
shell: false,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
child.on('exit', (code, signal) => {
|
|
60
|
+
if (signal) {
|
|
61
|
+
// Re-raise the signal to ourselves so the parent shell sees the same
|
|
62
|
+
// termination mode (e.g., Ctrl+C propagates as SIGINT exit).
|
|
63
|
+
try {
|
|
64
|
+
process.kill(process.pid, signal);
|
|
65
|
+
} catch {
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
process.exit(typeof code === 'number' ? code : 0);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
child.on('error', (err) => {
|
|
74
|
+
// Failure to spawn node itself — extremely rare; surface to stderr.
|
|
75
|
+
// eslint-disable-next-line no-console
|
|
76
|
+
console.error('gdd-state-mcp: failed to launch MCP server entry:', err.message);
|
|
77
|
+
process.exit(3);
|
|
78
|
+
});
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# GET DESIGN DONE
|
|
4
4
|
|
|
5
|
-
[English](README.md) · [简体中文](README.zh-CN.md) · [日本語](README.ja.md) · [한국어](README.ko.md) · [Français](README.fr.md) · [Italiano](README.it.md) · **Deutsch**
|
|
5
|
+
[English](../../README.md) · [简体中文](README.zh-CN.md) · [日本語](README.ja.md) · [한국어](README.ko.md) · [Français](README.fr.md) · [Italiano](README.it.md) · **Deutsch**
|
|
6
6
|
|
|
7
7
|
**Eine Design-Quality-Pipeline für AI-Coding-Agenten: Brief → Explore → Plan → Implementierung → Verifikation.**
|
|
8
8
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# GET DESIGN DONE
|
|
4
4
|
|
|
5
|
-
[English](README.md) · [简体中文](README.zh-CN.md) · [日本語](README.ja.md) · [한국어](README.ko.md) · **Français** · [Italiano](README.it.md) · [Deutsch](README.de.md)
|
|
5
|
+
[English](../../README.md) · [简体中文](README.zh-CN.md) · [日本語](README.ja.md) · [한국어](README.ko.md) · **Français** · [Italiano](README.it.md) · [Deutsch](README.de.md)
|
|
6
6
|
|
|
7
7
|
**Un pipeline de qualité design pour agents de code IA : brief → exploration → plan → implémentation → vérification.**
|
|
8
8
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# GET DESIGN DONE
|
|
4
4
|
|
|
5
|
-
[English](README.md) · [简体中文](README.zh-CN.md) · [日本語](README.ja.md) · [한국어](README.ko.md) · [Français](README.fr.md) · **Italiano** · [Deutsch](README.de.md)
|
|
5
|
+
[English](../../README.md) · [简体中文](README.zh-CN.md) · [日本語](README.ja.md) · [한국어](README.ko.md) · [Français](README.fr.md) · **Italiano** · [Deutsch](README.de.md)
|
|
6
6
|
|
|
7
7
|
**Una pipeline di qualità del design per agenti di coding IA: brief → esplorazione → piano → implementazione → verifica.**
|
|
8
8
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# GET DESIGN DONE
|
|
4
4
|
|
|
5
|
-
[English](README.md) · [简体中文](README.zh-CN.md) · **日本語** · [한국어](README.ko.md) · [Français](README.fr.md) · [Italiano](README.it.md) · [Deutsch](README.de.md)
|
|
5
|
+
[English](../../README.md) · [简体中文](README.zh-CN.md) · **日本語** · [한국어](README.ko.md) · [Français](README.fr.md) · [Italiano](README.it.md) · [Deutsch](README.de.md)
|
|
6
6
|
|
|
7
7
|
**AI コーディングエージェントのためのデザイン品質パイプライン: ブリーフ → 探索 → 計画 → 実装 → 検証。**
|
|
8
8
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# GET DESIGN DONE
|
|
4
4
|
|
|
5
|
-
[English](README.md) · [简体中文](README.zh-CN.md) · [日本語](README.ja.md) · **한국어** · [Français](README.fr.md) · [Italiano](README.it.md) · [Deutsch](README.de.md)
|
|
5
|
+
[English](../../README.md) · [简体中文](README.zh-CN.md) · [日本語](README.ja.md) · **한국어** · [Français](README.fr.md) · [Italiano](README.it.md) · [Deutsch](README.de.md)
|
|
6
6
|
|
|
7
7
|
**AI 코딩 에이전트를 위한 디자인 품질 파이프라인: 브리프 → 탐색 → 계획 → 구현 → 검증.**
|
|
8
8
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# GET DESIGN DONE
|
|
4
4
|
|
|
5
|
-
[English](README.md) · **简体中文** · [日本語](README.ja.md) · [한국어](README.ko.md) · [Français](README.fr.md) · [Italiano](README.it.md) · [Deutsch](README.de.md)
|
|
5
|
+
[English](../../README.md) · **简体中文** · [日本語](README.ja.md) · [한국어](README.ko.md) · [Français](README.fr.md) · [Italiano](README.it.md) · [Deutsch](README.de.md)
|
|
6
6
|
|
|
7
7
|
**面向 AI 编码智能体的设计质量流水线:简报 → 探索 → 规划 → 实现 → 验证。**
|
|
8
8
|
|
package/hooks/_hook-emit.js
CHANGED
|
@@ -45,7 +45,7 @@ function getAppendEvent() {
|
|
|
45
45
|
// require()'ing — if Node refuses to parse `.ts`, we silently fall
|
|
46
46
|
// back to no-op.
|
|
47
47
|
// eslint-disable-next-line node/no-missing-require, global-require
|
|
48
|
-
cachedAppendEvent = require('../
|
|
48
|
+
cachedAppendEvent = require('../sdk/event-stream/index.ts').appendEvent;
|
|
49
49
|
return cachedAppendEvent;
|
|
50
50
|
} catch {
|
|
51
51
|
cachedAppendEvent = null;
|
package/hooks/budget-enforcer.ts
CHANGED
|
@@ -44,8 +44,8 @@ import { spawn } from 'node:child_process';
|
|
|
44
44
|
import { createInterface } from 'node:readline';
|
|
45
45
|
import { createRequire } from 'node:module';
|
|
46
46
|
|
|
47
|
-
import { appendEvent } from '../
|
|
48
|
-
import type { HookFiredEvent } from '../
|
|
47
|
+
import { appendEvent } from '../sdk/event-stream/index.ts';
|
|
48
|
+
import type { HookFiredEvent } from '../sdk/event-stream/index.ts';
|
|
49
49
|
// Consume the generated BudgetSchema so this hook participates in the
|
|
50
50
|
// Plan 20-00 codegen graph. We treat parsed JSON as BudgetSchema after
|
|
51
51
|
// the structural merge with defaults — the schema permits every field
|
|
@@ -71,7 +71,7 @@ function resolveHookPath(): string {
|
|
|
71
71
|
}
|
|
72
72
|
const nodeRequire = createRequire(resolveHookPath());
|
|
73
73
|
const rateGuard = nodeRequire('../scripts/lib/rate-guard.cjs') as typeof import('../scripts/lib/rate-guard.cjs');
|
|
74
|
-
const iterationBudget = nodeRequire('../
|
|
74
|
+
const iterationBudget = nodeRequire('../sdk/primitives/iteration-budget.cjs') as typeof import('../sdk/primitives/iteration-budget.cjs');
|
|
75
75
|
// Plan 26-05: shared cost-computation backend for the resolved_models
|
|
76
76
|
// consumer path. Pure module — takes (model_id, runtime, token_counts) →
|
|
77
77
|
// cost_usd by reading per-runtime price tables under reference/prices/.
|
|
@@ -612,9 +612,9 @@ export function writeTelemetry(partial: TelemetryRowPartial): void {
|
|
|
612
612
|
|
|
613
613
|
/**
|
|
614
614
|
* Emit one hook.fired event per hook decision. Uses the pre-registered
|
|
615
|
-
* HookFiredEvent subtype from
|
|
615
|
+
* HookFiredEvent subtype from sdk/event-stream/types.ts and
|
|
616
616
|
* stamps sessionId from the process PID + boot time — same scheme as
|
|
617
|
-
*
|
|
617
|
+
* sdk/mcp/gdd-state/tools/shared.ts but inlined here so the
|
|
618
618
|
* hook stays dependency-light.
|
|
619
619
|
*/
|
|
620
620
|
let CACHED_SESSION_ID: string | null = null;
|
|
@@ -28,8 +28,8 @@ import {
|
|
|
28
28
|
import { dirname, join } from 'node:path';
|
|
29
29
|
import { createInterface } from 'node:readline';
|
|
30
30
|
|
|
31
|
-
import { appendEvent } from '../
|
|
32
|
-
import type { HookFiredEvent } from '../
|
|
31
|
+
import { appendEvent } from '../sdk/event-stream/index.ts';
|
|
32
|
+
import type { HookFiredEvent } from '../sdk/event-stream/index.ts';
|
|
33
33
|
|
|
34
34
|
// ── Types ───────────────────────────────────────────────────────────────────
|
|
35
35
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* writes an atomic snapshot of STATE.md sections + last-N event-chain
|
|
7
7
|
* entries + last-N decisions to `.design/snapshots/<ts>.json`.
|
|
8
8
|
*
|
|
9
|
-
* Phase 27.6 D-08: atomic .tmp + rename via
|
|
9
|
+
* Phase 27.6 D-08: atomic .tmp + rename via sdk/primitives/lockfile.cjs.
|
|
10
10
|
* - Lockfile serializes concurrent PreCompact writers.
|
|
11
11
|
* - .tmp + rename guarantees no partial file ever appears at target path
|
|
12
12
|
* (a SIGKILL between writeFileSync and renameSync leaves an orphan
|
|
@@ -52,7 +52,7 @@ function detectHarness() {
|
|
|
52
52
|
|
|
53
53
|
function getAppendEvent() {
|
|
54
54
|
try {
|
|
55
|
-
const m = require('../
|
|
55
|
+
const m = require('../sdk/event-stream');
|
|
56
56
|
if (m && typeof m.appendEvent === 'function') return m.appendEvent;
|
|
57
57
|
} catch {
|
|
58
58
|
/* swallow — event-stream is optional infrastructure */
|
|
@@ -224,7 +224,7 @@ async function main() {
|
|
|
224
224
|
// PreCompact writers; the second writer either waits or fails-silent.
|
|
225
225
|
let release = null;
|
|
226
226
|
try {
|
|
227
|
-
const lockfile = require('../
|
|
227
|
+
const lockfile = require('../sdk/primitives/lockfile.cjs');
|
|
228
228
|
release = await lockfile.acquire(snapshotPath, {
|
|
229
229
|
staleMs: 60_000,
|
|
230
230
|
maxWaitMs: 10_000,
|
|
@@ -29,8 +29,8 @@ import { createRequire } from 'node:module';
|
|
|
29
29
|
import { createInterface } from 'node:readline';
|
|
30
30
|
import { dirname, isAbsolute, join, resolve } from 'node:path';
|
|
31
31
|
|
|
32
|
-
import { appendEvent } from '../
|
|
33
|
-
import type { HookFiredEvent } from '../
|
|
32
|
+
import { appendEvent } from '../sdk/event-stream/index.ts';
|
|
33
|
+
import type { HookFiredEvent } from '../sdk/event-stream/index.ts';
|
|
34
34
|
|
|
35
35
|
// ── require-bridge to the shared .cjs pattern file ──────────────────────────
|
|
36
36
|
|
|
@@ -45,7 +45,7 @@ function detectHarness() {
|
|
|
45
45
|
|
|
46
46
|
function getAppendEvent() {
|
|
47
47
|
try {
|
|
48
|
-
const m = require('../
|
|
48
|
+
const m = require('../sdk/event-stream');
|
|
49
49
|
if (m && typeof m.appendEvent === 'function') return m.appendEvent;
|
|
50
50
|
} catch {
|
|
51
51
|
/* swallow — event-stream is optional infrastructure */
|
|
@@ -49,7 +49,7 @@ const TAIL_BYTES = 8_192; // last 8 KiB is plenty for one event line (<<64KiB ca
|
|
|
49
49
|
* Lightweight parse of the `<position>` block in STATE.md. Returns the fields
|
|
50
50
|
* we care about, or null if the block isn't present / well-formed.
|
|
51
51
|
*
|
|
52
|
-
* We intentionally avoid the full parser at
|
|
52
|
+
* We intentionally avoid the full parser at sdk/state/parser.ts
|
|
53
53
|
* because (a) it requires TS execution and (b) its overhead would blow the
|
|
54
54
|
* 10ms budget. The position block is k=v lines so a regex pass is fine.
|
|
55
55
|
*/
|
package/hooks/hooks.json
CHANGED
|
@@ -32,6 +32,15 @@
|
|
|
32
32
|
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/gdd-sessionstart-recap.js\""
|
|
33
33
|
}
|
|
34
34
|
]
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"matcher": "startup|clear|compact",
|
|
38
|
+
"hooks": [
|
|
39
|
+
{
|
|
40
|
+
"type": "command",
|
|
41
|
+
"command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/inject-using-gdd.sh\""
|
|
42
|
+
}
|
|
43
|
+
]
|
|
35
44
|
}
|
|
36
45
|
],
|
|
37
46
|
"PreToolUse": [
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# hooks/inject-using-gdd.sh — SessionStart per-harness context injector (D-07).
|
|
3
|
+
#
|
|
4
|
+
# The forcing function GDD lacked: on every session start / /clear / compact this
|
|
5
|
+
# reads skills/using-gdd/SKILL.md (the bootstrap discipline contract) and emits it
|
|
6
|
+
# as the host harness's SessionStart "additionalContext" shape so the agent is
|
|
7
|
+
# primed with the 1%-rule + red-flags + skill-priority before it acts.
|
|
8
|
+
#
|
|
9
|
+
# Ported MECHANISM (not content) from obra/superpowers (MIT): one polyglot script,
|
|
10
|
+
# env-var branch, pure-bash escape_for_json (no jq/python dependency). See NOTICE.
|
|
11
|
+
#
|
|
12
|
+
# Three emitted shapes (ONE JSON object on stdout, nothing else):
|
|
13
|
+
# Cursor (CURSOR_PLUGIN_ROOT set) -> {"additional_context": "<escaped>"}
|
|
14
|
+
# Claude Code (CLAUDE_PLUGIN_ROOT set, no Cursor)
|
|
15
|
+
# -> {"hookSpecificOutput":
|
|
16
|
+
# {"hookEventName":"SessionStart",
|
|
17
|
+
# "additionalContext":"<escaped>"}}
|
|
18
|
+
# SDK-standard (neither; e.g. COPILOT_CLI) -> {"additionalContext": "<escaped>"}
|
|
19
|
+
#
|
|
20
|
+
# Branch order: check Cursor BEFORE Claude Code — a Cursor session may also export
|
|
21
|
+
# CLAUDE_PLUGIN_ROOT, and Cursor's own var must win.
|
|
22
|
+
#
|
|
23
|
+
# NO-CASCADE (D-06): this script is wired ONLY under the SessionStart hook event in
|
|
24
|
+
# hooks/hooks.json. Subagent spawns do not fire SessionStart, so the inject cannot
|
|
25
|
+
# cascade into a subagent's context. (Structural guarantee; behavioral proof = P33.)
|
|
26
|
+
|
|
27
|
+
set -u
|
|
28
|
+
|
|
29
|
+
# --- Resolve the plugin root so we can locate skills/using-gdd/SKILL.md ---------
|
|
30
|
+
# Prefer the harness-provided roots; fall back to this script's parent dir so the
|
|
31
|
+
# emitter is runnable straight from hooks/ in tests and in bare shells.
|
|
32
|
+
SELF_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
33
|
+
ROOT="${CURSOR_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-${SELF_DIR}/..}}"
|
|
34
|
+
ROOT="${ROOT//\\//}" # normalize Windows backslashes to forward slashes
|
|
35
|
+
SKILL="${ROOT}/skills/using-gdd/SKILL.md"
|
|
36
|
+
|
|
37
|
+
# Defensive: if the skill file is missing we must STILL emit a syntactically valid
|
|
38
|
+
# JSON object (an empty additionalContext) so the SessionStart pipeline never
|
|
39
|
+
# breaks on a partial install. Never crash the session start.
|
|
40
|
+
if [[ -r "${SKILL}" ]]; then
|
|
41
|
+
CONTENT="$(cat "${SKILL}")"
|
|
42
|
+
else
|
|
43
|
+
CONTENT=""
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
# --- escape_for_json (superpowers pattern; pure bash param-substitution) --------
|
|
47
|
+
# Order matters: backslash FIRST (so escapes we add next aren't re-escaped), then
|
|
48
|
+
# double-quote, then the control chars newline / tab / carriage-return. Emits the
|
|
49
|
+
# value WITH surrounding double-quotes so callers can splice it directly.
|
|
50
|
+
escape_for_json() {
|
|
51
|
+
local s="$1"
|
|
52
|
+
s="${s//\\/\\\\}" # \ -> \\
|
|
53
|
+
s="${s//\"/\\\"}" # " -> \"
|
|
54
|
+
s="${s//$'\t'/\\t}" # tab -> \t
|
|
55
|
+
s="${s//$'\r'/\\r}" # CR -> \r
|
|
56
|
+
s="${s//$'\n'/\\n}" # LF -> \n (do last: newlines are the record separator)
|
|
57
|
+
printf '"%s"' "$s"
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
ESCAPED="$(escape_for_json "${CONTENT}")"
|
|
61
|
+
|
|
62
|
+
# --- Branch on harness env vars and emit the matching single JSON object --------
|
|
63
|
+
if [[ -n "${CURSOR_PLUGIN_ROOT:-}" ]]; then
|
|
64
|
+
# Cursor: top-level additional_context.
|
|
65
|
+
printf '{"additional_context": %s}\n' "${ESCAPED}"
|
|
66
|
+
elif [[ -n "${CLAUDE_PLUGIN_ROOT:-}" ]]; then
|
|
67
|
+
# Claude Code: hookSpecificOutput envelope (mirrors hooks/gdd-decision-injector.js).
|
|
68
|
+
printf '{"hookSpecificOutput": {"hookEventName": "SessionStart", "additionalContext": %s}}\n' "${ESCAPED}"
|
|
69
|
+
else
|
|
70
|
+
# SDK-standard (COPILOT_CLI or none): top-level additionalContext.
|
|
71
|
+
printf '{"additionalContext": %s}\n' "${ESCAPED}"
|
|
72
|
+
fi
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
@echo off
|
|
2
|
+
REM hooks/run-hook.cmd — Windows polyglot wrapper that invokes a GDD .sh hook
|
|
3
|
+
REM through bash.
|
|
4
|
+
REM
|
|
5
|
+
REM Workaround for Claude Code's Windows auto-bash bug: CC can mis-handle a
|
|
6
|
+
REM SessionStart `command` that points directly at a `.sh` file on Windows
|
|
7
|
+
REM shells. This .cmd shim locates bash and runs the script explicitly, so the
|
|
8
|
+
REM SessionStart inject (hooks/inject-using-gdd.sh) fires on Windows too.
|
|
9
|
+
REM
|
|
10
|
+
REM Usage: run-hook.cmd <script-name.sh> [args...]
|
|
11
|
+
REM Default (no arg): inject-using-gdd.sh — the SessionStart using-gdd injector.
|
|
12
|
+
REM The host harness's env (CLAUDE_PLUGIN_ROOT / CURSOR_PLUGIN_ROOT / COPILOT_CLI)
|
|
13
|
+
REM is inherited by bash and drives the emitter's per-harness branch.
|
|
14
|
+
setlocal
|
|
15
|
+
|
|
16
|
+
REM Script to run, relative to this .cmd's own directory (%~dp0 ends with a backslash).
|
|
17
|
+
set "HOOK_SCRIPT=%~1"
|
|
18
|
+
if "%HOOK_SCRIPT%"=="" set "HOOK_SCRIPT=inject-using-gdd.sh"
|
|
19
|
+
if not "%~1"=="" shift
|
|
20
|
+
|
|
21
|
+
set "HOOK_PATH=%~dp0%HOOK_SCRIPT%"
|
|
22
|
+
|
|
23
|
+
REM Prefer bash on PATH; fall back to a typical Git-for-Windows install location.
|
|
24
|
+
where bash >nul 2>nul
|
|
25
|
+
if %ERRORLEVEL%==0 (
|
|
26
|
+
bash "%HOOK_PATH%" %*
|
|
27
|
+
) else if exist "%ProgramFiles%\Git\bin\bash.exe" (
|
|
28
|
+
"%ProgramFiles%\Git\bin\bash.exe" "%HOOK_PATH%" %*
|
|
29
|
+
) else (
|
|
30
|
+
REM No bash available: emit a valid empty SDK-shape JSON object so the
|
|
31
|
+
REM SessionStart pipeline still receives parseable output and never breaks.
|
|
32
|
+
echo {"additionalContext": ""}
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
endlocal
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hegemonart/get-design-done",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.32.0",
|
|
4
4
|
"description": "A design-quality pipeline for AI coding agents: brief, plan, implement, and verify UI work against your design system.",
|
|
5
5
|
"author": "Hegemon",
|
|
6
6
|
"homepage": "https://github.com/hegemonart/get-design-done",
|
|
@@ -17,21 +17,28 @@
|
|
|
17
17
|
"agents/",
|
|
18
18
|
"skills/",
|
|
19
19
|
"hooks/",
|
|
20
|
-
"scripts/",
|
|
21
20
|
"connections/",
|
|
22
21
|
"reference/",
|
|
23
22
|
"bin/",
|
|
23
|
+
"sdk/",
|
|
24
|
+
"recipes/",
|
|
25
|
+
"docs/i18n/",
|
|
26
|
+
"scripts/lib/",
|
|
27
|
+
"scripts/mcp-servers/",
|
|
28
|
+
"scripts/cli/",
|
|
29
|
+
"scripts/install.cjs",
|
|
24
30
|
"SKILL.md",
|
|
25
31
|
"README.md",
|
|
26
32
|
"CHANGELOG.md",
|
|
27
|
-
"LICENSE"
|
|
33
|
+
"LICENSE",
|
|
34
|
+
"NOTICE"
|
|
28
35
|
],
|
|
29
36
|
"bin": {
|
|
30
37
|
"gdd-events": "./scripts/cli/gdd-events.mjs",
|
|
31
38
|
"gdd-graph": "./bin/gdd-graph",
|
|
32
|
-
"gdd-mcp": "./
|
|
39
|
+
"gdd-mcp": "./bin/gdd-mcp",
|
|
33
40
|
"gdd-sdk": "./bin/gdd-sdk",
|
|
34
|
-
"gdd-state-mcp": "./
|
|
41
|
+
"gdd-state-mcp": "./bin/gdd-state-mcp",
|
|
35
42
|
"get-design-done": "./scripts/install.cjs"
|
|
36
43
|
},
|
|
37
44
|
"publishConfig": {
|
|
@@ -40,26 +47,30 @@
|
|
|
40
47
|
},
|
|
41
48
|
"scripts": {
|
|
42
49
|
"build:bundles": "node scripts/build-distribution-bundles.cjs",
|
|
43
|
-
"
|
|
50
|
+
"build:sdk": "node scripts/build-sdk-bins.cjs",
|
|
51
|
+
"prepack": "npm run build:sdk",
|
|
52
|
+
"postpack": "node scripts/build-sdk-bins.cjs --clean",
|
|
53
|
+
"test": "node --test --experimental-strip-types \"test/suite/**/*.test.cjs\" \"test/suite/**/*.test.ts\"",
|
|
44
54
|
"typecheck": "tsc --noEmit",
|
|
45
55
|
"codegen:schemas": "node --experimental-strip-types scripts/codegen-schema-types.ts",
|
|
46
|
-
"lint:md": "npx --yes markdownlint-cli2 \"**/*.md\" \"#node_modules\" \"#.planning\" \"#.claude\" \"#test
|
|
56
|
+
"lint:md": "npx --yes markdownlint-cli2 \"**/*.md\" \"#node_modules\" \"#.planning\" \"#.claude\" \"#test/fixtures/baselines\"",
|
|
47
57
|
"lint:links": "npx --yes lychee --no-progress --accept 200,206,403,429 \"**/*.md\" || true",
|
|
48
58
|
"lint:agentskills": "node scripts/lint-agentskills-spec.cjs",
|
|
49
59
|
"validate:schemas": "node --experimental-strip-types scripts/validate-schemas.ts",
|
|
50
60
|
"validate:frontmatter": "node --experimental-strip-types scripts/validate-frontmatter.ts agents/",
|
|
51
61
|
"detect:stale-refs": "node scripts/detect-stale-refs.cjs",
|
|
52
62
|
"scan:injection": "node scripts/run-injection-scanner-ci.cjs",
|
|
53
|
-
"test:size-budget": "node --test
|
|
63
|
+
"test:size-budget": "node --test test/suite/agent-size-budget.test.cjs",
|
|
54
64
|
"release:extract-changelog": "node scripts/extract-changelog-section.cjs",
|
|
55
65
|
"verify:version-sync": "node scripts/verify-version-sync.cjs",
|
|
56
66
|
"typecheck:session-runner": "tsc --noEmit",
|
|
57
|
-
"gdd-sdk": "node --experimental-strip-types
|
|
67
|
+
"gdd-sdk": "node --experimental-strip-types sdk/cli/index.ts"
|
|
58
68
|
},
|
|
59
69
|
"devDependencies": {
|
|
60
70
|
"@types/node": "^25.6.0",
|
|
61
71
|
"ajv-cli": "^5.0.0",
|
|
62
72
|
"ajv-formats": "^3.0.1",
|
|
73
|
+
"esbuild": "^0.25.12",
|
|
63
74
|
"json-schema-to-typescript": "^15.0.0",
|
|
64
75
|
"typescript": "^6.0.3"
|
|
65
76
|
},
|
package/recipes/.gitkeep
ADDED
|
File without changes
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"type": {
|
|
11
11
|
"type": "string",
|
|
12
12
|
"minLength": 1,
|
|
13
|
-
"description": "Free-form event type identifier. Pre-registered seeds: state.mutation, state.transition, stage.entered, stage.exited, hook.fired, error, capability_gap."
|
|
13
|
+
"description": "Free-form event type identifier. Pre-registered seeds: state.mutation, state.transition, stage.entered, stage.exited, hook.fired, error, capability_gap, kfm-candidate, router_pick."
|
|
14
14
|
},
|
|
15
15
|
"timestamp": {
|
|
16
16
|
"type": "string",
|
|
@@ -181,6 +181,57 @@
|
|
|
181
181
|
}
|
|
182
182
|
},
|
|
183
183
|
"description": "Phase 30.5-03 D-06 kfm-candidate payload — 7 fields, additionalProperties: false. Validated when the envelope's type === 'kfm-candidate' via the allOf[1] conditional."
|
|
184
|
+
},
|
|
185
|
+
"RouterPickPayload": {
|
|
186
|
+
"type": "object",
|
|
187
|
+
"additionalProperties": false,
|
|
188
|
+
"required": [
|
|
189
|
+
"event_id",
|
|
190
|
+
"source",
|
|
191
|
+
"picked_skill",
|
|
192
|
+
"context_hash",
|
|
193
|
+
"rank",
|
|
194
|
+
"alternatives",
|
|
195
|
+
"ts"
|
|
196
|
+
],
|
|
197
|
+
"properties": {
|
|
198
|
+
"event_id": {
|
|
199
|
+
"type": "string",
|
|
200
|
+
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
|
|
201
|
+
"description": "UUIDv4 identifying this router_pick event. Stable across emit + read cycles."
|
|
202
|
+
},
|
|
203
|
+
"source": {
|
|
204
|
+
"type": "string",
|
|
205
|
+
"const": "router",
|
|
206
|
+
"description": "Phase 32-08 D-02 — the router_pick event class is emitted EXCLUSIVELY by the gdd-router skill at its resolved-pick point. No other producer is authorised."
|
|
207
|
+
},
|
|
208
|
+
"picked_skill": {
|
|
209
|
+
"type": "string",
|
|
210
|
+
"minLength": 1,
|
|
211
|
+
"description": "The skill or agent the router auto-picked for this intent. Phase 33 baselines per-skill auto-pick rates from this field (pick-rate regression)."
|
|
212
|
+
},
|
|
213
|
+
"context_hash": {
|
|
214
|
+
"type": "string",
|
|
215
|
+
"minLength": 1,
|
|
216
|
+
"description": "sha256 of the intent/context that drove the pick — NEVER the raw prompt (no PII, mirrors CapabilityGapPayload.context_hash discipline). Used by Phase 33 aggregation to cluster picks for the same context."
|
|
217
|
+
},
|
|
218
|
+
"rank": {
|
|
219
|
+
"type": "integer",
|
|
220
|
+
"minimum": 0,
|
|
221
|
+
"description": "Rank of the picked_skill among the candidates considered (0 = top pick). Lets Phase 33 distinguish confident top picks from close calls."
|
|
222
|
+
},
|
|
223
|
+
"alternatives": {
|
|
224
|
+
"type": "array",
|
|
225
|
+
"items": { "type": "string" },
|
|
226
|
+
"description": "Other candidate skill/agent names the router considered (names only — no scores, no prompt text). May be empty when the router had a single match. Surfaces which skills the router weighs but does not reach for."
|
|
227
|
+
},
|
|
228
|
+
"ts": {
|
|
229
|
+
"type": "string",
|
|
230
|
+
"format": "date-time",
|
|
231
|
+
"description": "ISO-8601 timestamp of the pick emission."
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
"description": "Phase 32-08 D-02 router_pick payload — 7 fields, additionalProperties: false, NO PII (context_hash only). Records which skill the router auto-picked per intent — the instrument that surfaces under-reached skills. Validated when the envelope's type === 'router_pick' via the allOf[2] conditional."
|
|
184
235
|
}
|
|
185
236
|
},
|
|
186
237
|
"allOf": [
|
|
@@ -205,6 +256,17 @@
|
|
|
205
256
|
"payload": { "$ref": "#/definitions/KfmCandidatePayload" }
|
|
206
257
|
}
|
|
207
258
|
}
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
"if": {
|
|
262
|
+
"properties": { "type": { "const": "router_pick" } },
|
|
263
|
+
"required": ["type"]
|
|
264
|
+
},
|
|
265
|
+
"then": {
|
|
266
|
+
"properties": {
|
|
267
|
+
"payload": { "$ref": "#/definitions/RouterPickPayload" }
|
|
268
|
+
}
|
|
269
|
+
}
|
|
208
270
|
}
|
|
209
271
|
]
|
|
210
272
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://raw.githubusercontent.com/hegemonart/get-design-done/main/reference/schemas/recipe.schema.json",
|
|
4
|
+
"title": "Recipe",
|
|
5
|
+
"description": "Shape of a declarative recipe loaded from recipes/<name>.json by scripts/lib/recipe-loader.cjs (Plan 31-5-03, RECIPE-01 / SC#14). The recipes/ directory ships EMPTY of recipes and is populated downstream by Phase 32 (skill-trigger recipes), Phase 33.6 (per-provider), Phase 26 (per-runtime/per-model), and Phase 23.5 (bandit-arm shape). This is a minimal, forward-compatible envelope: a recipe MUST carry name/version/steps; additionalProperties:true lets the populating phases extend the envelope without breaking the loader contract. Modelled on Storybloq's src/autonomous/recipes/ loader.ts pattern.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": true,
|
|
8
|
+
"required": ["name", "version", "steps"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"name": {
|
|
11
|
+
"type": "string",
|
|
12
|
+
"minLength": 1,
|
|
13
|
+
"description": "The recipe identifier. Matches the filename stem (recipes/<name>.json)."
|
|
14
|
+
},
|
|
15
|
+
"version": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"minLength": 1,
|
|
18
|
+
"description": "Recipe/schema version string for forward-compatibility. Lets the loader and downstream phases reason about envelope evolution."
|
|
19
|
+
},
|
|
20
|
+
"steps": {
|
|
21
|
+
"type": "array",
|
|
22
|
+
"description": "The ordered recipe body. Item shape is kept permissive for now — each step is an object carrying at least a `kind` OR an `id` string. Downstream phases (32/33.6/26/23.5) tighten the step contract per their domain.",
|
|
23
|
+
"items": {
|
|
24
|
+
"type": "object",
|
|
25
|
+
"additionalProperties": true,
|
|
26
|
+
"anyOf": [
|
|
27
|
+
{ "required": ["kind"], "properties": { "kind": { "type": "string", "minLength": 1 } } },
|
|
28
|
+
{ "required": ["id"], "properties": { "id": { "type": "string", "minLength": 1 } } }
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -138,7 +138,7 @@ export function compileFilter(terms) {
|
|
|
138
138
|
|
|
139
139
|
async function cmdTail(parsed) {
|
|
140
140
|
const path = resolvePath(parsed.flags.path);
|
|
141
|
-
const { readEvents } = await import('
|
|
141
|
+
const { readEvents } = await import('../../sdk/event-stream/reader.ts');
|
|
142
142
|
if (!parsed.flags.follow) {
|
|
143
143
|
for await (const ev of readEvents({ path })) {
|
|
144
144
|
stdout.write(JSON.stringify(ev) + '\n');
|
|
@@ -188,7 +188,7 @@ async function cmdGrep(parsed) {
|
|
|
188
188
|
return 2;
|
|
189
189
|
}
|
|
190
190
|
const predicate = compileFilter(terms);
|
|
191
|
-
const { readEvents } = await import('
|
|
191
|
+
const { readEvents } = await import('../../sdk/event-stream/reader.ts');
|
|
192
192
|
for await (const ev of readEvents({ path, predicate })) {
|
|
193
193
|
stdout.write(JSON.stringify(ev) + '\n');
|
|
194
194
|
}
|
|
@@ -197,7 +197,7 @@ async function cmdGrep(parsed) {
|
|
|
197
197
|
|
|
198
198
|
async function cmdCat(parsed) {
|
|
199
199
|
const path = resolvePath(parsed.flags.path);
|
|
200
|
-
const { readEvents } = await import('
|
|
200
|
+
const { readEvents } = await import('../../sdk/event-stream/reader.ts');
|
|
201
201
|
for await (const ev of readEvents({ path })) {
|
|
202
202
|
const ts = ev.timestamp ?? '?';
|
|
203
203
|
const tp = ev.type ?? '?';
|
|
@@ -207,7 +207,7 @@ async function cmdCat(parsed) {
|
|
|
207
207
|
}
|
|
208
208
|
|
|
209
209
|
async function cmdListTypes() {
|
|
210
|
-
const { KNOWN_EVENT_TYPES } = await import('
|
|
210
|
+
const { KNOWN_EVENT_TYPES } = await import('../../sdk/event-stream/types.ts');
|
|
211
211
|
for (const t of KNOWN_EVENT_TYPES) stdout.write(t + '\n');
|
|
212
212
|
return 0;
|
|
213
213
|
}
|
|
@@ -236,7 +236,7 @@ async function cmdServe(parsed) {
|
|
|
236
236
|
// Bridge live bus → ws transport. The transport is CommonJS and cannot
|
|
237
237
|
// require .ts directly, so we import the bus here and pass subscribeAll
|
|
238
238
|
// as a callback factory.
|
|
239
|
-
const { subscribeAll } = await import('
|
|
239
|
+
const { subscribeAll } = await import('../../sdk/event-stream/index.ts');
|
|
240
240
|
const subscribe = (handler) => subscribeAll(handler);
|
|
241
241
|
const handle = await mod.startServer({ port, token, tailFrom, subscribe });
|
|
242
242
|
stderr.write(`gdd-events: WebSocket listening on :${port} (auth required)\n`);
|
|
@@ -83,7 +83,7 @@ function clamp01(n) {
|
|
|
83
83
|
function getAppendEvent() {
|
|
84
84
|
try {
|
|
85
85
|
// Resolved relative to this file: `scripts/lib/cache/` → `../event-stream`.
|
|
86
|
-
const m = require('
|
|
86
|
+
const m = require('../../../sdk/event-stream');
|
|
87
87
|
if (m && typeof m.appendEvent === 'function') return m.appendEvent;
|
|
88
88
|
} catch {
|
|
89
89
|
// Swallow — fall through to the no-op below. The event is
|