@hegemonart/get-design-done 1.31.0 → 1.31.5
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 +44 -0
- package/NOTICE +224 -0
- package/README.md +1 -1
- 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/package.json +20 -9
- package/recipes/.gitkeep +0 -0
- 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/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 +1924 -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/quality-gate/SKILL.md +2 -2
- 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
|
@@ -1,282 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* aggregate-agent-metrics.ts — Incremental per-agent aggregator.
|
|
4
|
-
*
|
|
5
|
-
* Reads: .design/telemetry/costs.jsonl (append-only ledger from
|
|
6
|
-
* hooks/budget-enforcer.js)
|
|
7
|
-
* agents/{agent}.md (frontmatter source for default-tier, parallel-safe,
|
|
8
|
-
* reads-only, typical-duration-seconds)
|
|
9
|
-
* Writes: .design/agent-metrics.json (atomic overwrite via tmp-file + rename)
|
|
10
|
-
* .design/telemetry/phase-totals.json (same, WR-02)
|
|
11
|
-
*
|
|
12
|
-
* Invoked:
|
|
13
|
-
* 1. Detached child of hooks/budget-enforcer.js after every telemetry write.
|
|
14
|
-
* 2. Directly by /gdd:optimize skill as an explicit refresh step.
|
|
15
|
-
* 3. Manually: `node --experimental-strip-types scripts/aggregate-agent-metrics.ts`
|
|
16
|
-
* 4. With `--help` to print usage (used by the Plan 20-00 smoke check).
|
|
17
|
-
*
|
|
18
|
-
* OPT-09 contract: fields must match Phase 11 reflector's expectations.
|
|
19
|
-
*
|
|
20
|
-
* Converted from scripts/aggregate-agent-metrics.js in Plan 20-00 (Tier-1).
|
|
21
|
-
* Behavior preserved verbatim.
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
import {
|
|
25
|
-
existsSync,
|
|
26
|
-
mkdirSync,
|
|
27
|
-
readFileSync,
|
|
28
|
-
writeFileSync,
|
|
29
|
-
renameSync,
|
|
30
|
-
} from 'node:fs';
|
|
31
|
-
import { join, dirname, basename } from 'node:path';
|
|
32
|
-
|
|
33
|
-
// Generated-type import (unused at runtime, erased by strip-types) to satisfy
|
|
34
|
-
// Plan 20-00's requirement that every Tier-1 TS file participates in the
|
|
35
|
-
// codegen graph. We pick AuthoritySnapshotSchema as a stable anchor and
|
|
36
|
-
// re-export for downstream callers.
|
|
37
|
-
import type { AuthoritySnapshotSchema } from '../reference/schemas/generated.js';
|
|
38
|
-
export type { AuthoritySnapshotSchema };
|
|
39
|
-
|
|
40
|
-
const CWD: string = process.cwd();
|
|
41
|
-
const TELEMETRY_PATH: string = join(CWD, '.design', 'telemetry', 'costs.jsonl');
|
|
42
|
-
const METRICS_PATH: string = join(CWD, '.design', 'agent-metrics.json');
|
|
43
|
-
const PHASE_TOTALS_PATH: string = join(CWD, '.design', 'telemetry', 'phase-totals.json');
|
|
44
|
-
const AGENTS_DIR: string = join(CWD, 'agents');
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Subset of the agent-markdown frontmatter we care about. `null` means the
|
|
48
|
-
* field is absent or unparseable (aggregator is tolerant — degraded mode
|
|
49
|
-
* preferred over hard-fail per OPT-09).
|
|
50
|
-
*/
|
|
51
|
-
interface AgentFrontmatter {
|
|
52
|
-
default_tier: string | null;
|
|
53
|
-
parallel_safe: boolean | null;
|
|
54
|
-
reads_only: boolean | null;
|
|
55
|
-
typical_duration_seconds: number | null;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/** ---- frontmatter reader (no YAML dep) ---- */
|
|
59
|
-
function readAgentFrontmatter(agentName: string): Partial<AgentFrontmatter> {
|
|
60
|
-
const p: string = join(AGENTS_DIR, `${agentName}.md`);
|
|
61
|
-
if (!existsSync(p)) return {};
|
|
62
|
-
try {
|
|
63
|
-
const content: string = readFileSync(p, 'utf8');
|
|
64
|
-
const fm = content.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
65
|
-
if (!fm) return {};
|
|
66
|
-
const body: string = fm[1] ?? '';
|
|
67
|
-
const get = (key: string): string | null => {
|
|
68
|
-
const m = body.match(new RegExp(`^${key}:\\s*"?([^"\\n]+)"?`, 'm'));
|
|
69
|
-
return m && m[1] !== undefined ? m[1].trim() : null;
|
|
70
|
-
};
|
|
71
|
-
const defaultTier: string | null = get('default-tier');
|
|
72
|
-
const parallelSafe: string | null = get('parallel-safe');
|
|
73
|
-
const readsOnly: string | null = get('reads-only');
|
|
74
|
-
const typicalDuration: string | null = get('typical-duration-seconds');
|
|
75
|
-
return {
|
|
76
|
-
default_tier: defaultTier ?? null,
|
|
77
|
-
parallel_safe: parallelSafe === null ? null : /^(true|yes)$/i.test(parallelSafe),
|
|
78
|
-
reads_only: readsOnly === null ? null : /^(true|yes)$/i.test(readsOnly),
|
|
79
|
-
typical_duration_seconds:
|
|
80
|
-
typicalDuration === null ? null : Number(typicalDuration) || null,
|
|
81
|
-
};
|
|
82
|
-
} catch {
|
|
83
|
-
return {};
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Shape of a single row in .design/telemetry/costs.jsonl. Mirrors the OPT-09
|
|
89
|
-
* schema: nine mandatory fields + four optional diagnostic fields. Unknown
|
|
90
|
-
* keys are tolerated (Phase 11 reflector ignores them).
|
|
91
|
-
*/
|
|
92
|
-
export interface CostRow {
|
|
93
|
-
ts?: string;
|
|
94
|
-
agent?: string;
|
|
95
|
-
tier?: string;
|
|
96
|
-
tokens_in?: number | string;
|
|
97
|
-
tokens_out?: number | string;
|
|
98
|
-
cache_hit?: boolean;
|
|
99
|
-
est_cost_usd?: number | string;
|
|
100
|
-
cycle?: string;
|
|
101
|
-
phase?: string;
|
|
102
|
-
// Optional / diagnostic
|
|
103
|
-
tier_downgraded?: boolean;
|
|
104
|
-
enforcement_mode?: string;
|
|
105
|
-
lazy_skipped?: boolean;
|
|
106
|
-
block_reason?: string;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/** ---- telemetry reader ---- */
|
|
110
|
-
function readTelemetryRows(): CostRow[] {
|
|
111
|
-
if (!existsSync(TELEMETRY_PATH)) return [];
|
|
112
|
-
const raw: string = readFileSync(TELEMETRY_PATH, 'utf8');
|
|
113
|
-
const out: CostRow[] = [];
|
|
114
|
-
for (const line of raw.split(/\r?\n/)) {
|
|
115
|
-
if (!line.trim()) continue;
|
|
116
|
-
try {
|
|
117
|
-
out.push(JSON.parse(line) as CostRow);
|
|
118
|
-
} catch {
|
|
119
|
-
// tolerant: skip malformed lines (partial write, truncation)
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return out;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/** Per-agent roll-up accumulator. */
|
|
126
|
-
interface AgentAccumulator {
|
|
127
|
-
total_spawns: number;
|
|
128
|
-
total_cost_usd: number;
|
|
129
|
-
total_tokens_in: number;
|
|
130
|
-
total_tokens_out: number;
|
|
131
|
-
cache_hits: number;
|
|
132
|
-
lazy_skips: number;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/** Final per-agent shape written to .design/agent-metrics.json. */
|
|
136
|
-
export interface AgentMetrics {
|
|
137
|
-
typical_duration_seconds: number | null | undefined;
|
|
138
|
-
default_tier: string | null | undefined;
|
|
139
|
-
parallel_safe: boolean | null | undefined;
|
|
140
|
-
reads_only: boolean | null | undefined;
|
|
141
|
-
total_spawns: number;
|
|
142
|
-
total_cost_usd: number;
|
|
143
|
-
total_tokens_in: number;
|
|
144
|
-
total_tokens_out: number;
|
|
145
|
-
cache_hit_rate: number;
|
|
146
|
-
lazy_skip_rate: number;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/** ---- aggregator ---- */
|
|
150
|
-
function aggregate(rows: readonly CostRow[]): Record<string, AgentMetrics> {
|
|
151
|
-
const byAgent = new Map<string, AgentAccumulator>();
|
|
152
|
-
for (const r of rows) {
|
|
153
|
-
// Blocked rows represent a spawn that was denied at the hook — the agent
|
|
154
|
-
// never actually ran, so it must not contribute to spawn counts, cost, or
|
|
155
|
-
// token totals. Skip them here (mirror of the filter in aggregateByPhase).
|
|
156
|
-
if (r.block_reason) continue;
|
|
157
|
-
const agent: string = r.agent ?? 'unknown';
|
|
158
|
-
let a = byAgent.get(agent);
|
|
159
|
-
if (!a) {
|
|
160
|
-
a = {
|
|
161
|
-
total_spawns: 0,
|
|
162
|
-
total_cost_usd: 0,
|
|
163
|
-
total_tokens_in: 0,
|
|
164
|
-
total_tokens_out: 0,
|
|
165
|
-
cache_hits: 0,
|
|
166
|
-
lazy_skips: 0,
|
|
167
|
-
};
|
|
168
|
-
byAgent.set(agent, a);
|
|
169
|
-
}
|
|
170
|
-
a.total_spawns += 1;
|
|
171
|
-
a.total_cost_usd += Number(r.est_cost_usd ?? 0);
|
|
172
|
-
a.total_tokens_in += Number(r.tokens_in ?? 0);
|
|
173
|
-
a.total_tokens_out += Number(r.tokens_out ?? 0);
|
|
174
|
-
if (r.cache_hit === true) a.cache_hits += 1;
|
|
175
|
-
if (r.lazy_skipped === true) a.lazy_skips += 1;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const out: Record<string, AgentMetrics> = {};
|
|
179
|
-
for (const [agent, a] of byAgent.entries()) {
|
|
180
|
-
const fm = readAgentFrontmatter(agent);
|
|
181
|
-
const spawns: number = a.total_spawns || 1; // guard div-by-zero
|
|
182
|
-
out[agent] = {
|
|
183
|
-
typical_duration_seconds: fm.typical_duration_seconds,
|
|
184
|
-
default_tier: fm.default_tier,
|
|
185
|
-
parallel_safe: fm.parallel_safe,
|
|
186
|
-
reads_only: fm.reads_only,
|
|
187
|
-
total_spawns: a.total_spawns,
|
|
188
|
-
total_cost_usd: Number(a.total_cost_usd.toFixed(6)),
|
|
189
|
-
total_tokens_in: a.total_tokens_in,
|
|
190
|
-
total_tokens_out: a.total_tokens_out,
|
|
191
|
-
cache_hit_rate: Number((a.cache_hits / spawns).toFixed(4)),
|
|
192
|
-
lazy_skip_rate: Number((a.lazy_skips / spawns).toFixed(4)),
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
return out;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
/** ---- atomic write ---- */
|
|
199
|
-
function writeAtomic(filePath: string, content: string): void {
|
|
200
|
-
const dir: string = dirname(filePath);
|
|
201
|
-
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
202
|
-
const tmp: string = join(
|
|
203
|
-
dir,
|
|
204
|
-
`.${basename(filePath)}.${process.pid}.${Date.now()}.tmp`,
|
|
205
|
-
);
|
|
206
|
-
writeFileSync(tmp, content, 'utf8');
|
|
207
|
-
renameSync(tmp, filePath);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/** ---- phase totals aggregator (WR-02: avoids full JSONL replay in budget enforcer) ---- */
|
|
211
|
-
function aggregateByPhase(rows: readonly CostRow[]): Record<string, number> {
|
|
212
|
-
const byPhase: Record<string, number> = {};
|
|
213
|
-
for (const r of rows) {
|
|
214
|
-
// Blocked rows represent spawns that were denied by the hook — the agent
|
|
215
|
-
// never ran, so their est_cost_usd must not inflate cumulative phase spend.
|
|
216
|
-
// Counting them would make future hard-block and soft-threshold checks
|
|
217
|
-
// stricter than intended on every repeat cap hit.
|
|
218
|
-
if (r.block_reason) continue;
|
|
219
|
-
const phase: string = r.phase ?? 'unknown';
|
|
220
|
-
byPhase[phase] = (byPhase[phase] ?? 0) + Number(r.est_cost_usd ?? 0);
|
|
221
|
-
}
|
|
222
|
-
// Round to 6dp to match per-agent precision
|
|
223
|
-
for (const k of Object.keys(byPhase)) {
|
|
224
|
-
const v: number = byPhase[k] ?? 0;
|
|
225
|
-
byPhase[k] = Number(v.toFixed(6));
|
|
226
|
-
}
|
|
227
|
-
return byPhase;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/** ---- usage / --help ---- */
|
|
231
|
-
function printHelp(): void {
|
|
232
|
-
console.log(
|
|
233
|
-
`aggregate-agent-metrics.ts — Aggregate per-agent telemetry from .design/telemetry/costs.jsonl.\n` +
|
|
234
|
-
`\n` +
|
|
235
|
-
`Usage:\n` +
|
|
236
|
-
` node --experimental-strip-types scripts/aggregate-agent-metrics.ts\n` +
|
|
237
|
-
` node --experimental-strip-types scripts/aggregate-agent-metrics.ts --help\n` +
|
|
238
|
-
`\n` +
|
|
239
|
-
`Reads: .design/telemetry/costs.jsonl\n` +
|
|
240
|
-
` agents/<agent>.md (frontmatter)\n` +
|
|
241
|
-
`Writes: .design/agent-metrics.json\n` +
|
|
242
|
-
` .design/telemetry/phase-totals.json\n` +
|
|
243
|
-
`\n` +
|
|
244
|
-
`Invoked:\n` +
|
|
245
|
-
` - Detached child of hooks/budget-enforcer.js after every telemetry row.\n` +
|
|
246
|
-
` - Directly by /gdd:optimize as an explicit refresh step.\n` +
|
|
247
|
-
` - Manually, on demand.\n`,
|
|
248
|
-
);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/** ---- main ---- */
|
|
252
|
-
function main(): void {
|
|
253
|
-
if (process.argv.includes('--help') || process.argv.includes('-h')) {
|
|
254
|
-
printHelp();
|
|
255
|
-
process.exit(0);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
const rows: CostRow[] = readTelemetryRows();
|
|
259
|
-
const agents = aggregate(rows);
|
|
260
|
-
const payload = {
|
|
261
|
-
generated_at: new Date().toISOString(),
|
|
262
|
-
agents,
|
|
263
|
-
};
|
|
264
|
-
writeAtomic(METRICS_PATH, JSON.stringify(payload, null, 2) + '\n');
|
|
265
|
-
// Write lightweight phase-totals.json so budget-enforcer can read phase
|
|
266
|
-
// spend in O(1) without replaying the full JSONL on every agent spawn
|
|
267
|
-
// (WR-02).
|
|
268
|
-
const phaseTotals = {
|
|
269
|
-
generated_at: new Date().toISOString(),
|
|
270
|
-
totals: aggregateByPhase(rows),
|
|
271
|
-
};
|
|
272
|
-
writeAtomic(PHASE_TOTALS_PATH, JSON.stringify(phaseTotals, null, 2) + '\n');
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
try {
|
|
276
|
-
main();
|
|
277
|
-
} catch (err) {
|
|
278
|
-
// Fail open: aggregator must never block the hook or /gdd:optimize flow.
|
|
279
|
-
const msg: string = err instanceof Error ? err.message : String(err);
|
|
280
|
-
process.stderr.write(`aggregate-agent-metrics: ${msg}\n`);
|
|
281
|
-
process.exit(0);
|
|
282
|
-
}
|
package/scripts/bootstrap.sh
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# get-design-done bootstrap
|
|
3
|
-
# Auto-provisions companion resources that get-design-done references but which
|
|
4
|
-
# are not Claude Code plugins (so they cannot be listed in `dependencies`).
|
|
5
|
-
#
|
|
6
|
-
# Runs on SessionStart. Idempotent: uses a marker in ${CLAUDE_PLUGIN_DATA} so it
|
|
7
|
-
# only performs network work on first install or when the bundled manifest changes.
|
|
8
|
-
#
|
|
9
|
-
# Resources provisioned:
|
|
10
|
-
# - ~/.claude/libs/awesome-design-md (VoltAgent/awesome-design-md)
|
|
11
|
-
#
|
|
12
|
-
# Resources NOT provisioned (install separately, see README):
|
|
13
|
-
# - emil-design-eng skill — no canonical upstream
|
|
14
|
-
# - refero MCP — optional, add to your Claude config if you have access
|
|
15
|
-
|
|
16
|
-
set -u
|
|
17
|
-
|
|
18
|
-
PLUGIN_DATA="${CLAUDE_PLUGIN_DATA:-$HOME/.claude/plugins/data/get-design-done}"
|
|
19
|
-
PLUGIN_DATA="${PLUGIN_DATA//\\//}" # Normalize Windows backslashes to forward slashes
|
|
20
|
-
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"
|
|
21
|
-
PLUGIN_ROOT="${PLUGIN_ROOT//\\//}" # Normalize Windows backslashes to forward slashes
|
|
22
|
-
MANIFEST="${PLUGIN_ROOT}/scripts/bootstrap-manifest.txt"
|
|
23
|
-
MARKER="${PLUGIN_DATA}/bootstrap-manifest.txt"
|
|
24
|
-
|
|
25
|
-
mkdir -p "${PLUGIN_DATA}" "${HOME}/.claude/libs" "${HOME}/.claude/skills"
|
|
26
|
-
|
|
27
|
-
# Skip if bundled manifest matches the last-run marker (no-op on every other session).
|
|
28
|
-
if [[ -f "${MANIFEST}" && -f "${MARKER}" ]] && diff -q "${MANIFEST}" "${MARKER}" >/dev/null 2>&1; then
|
|
29
|
-
exit 0
|
|
30
|
-
fi
|
|
31
|
-
|
|
32
|
-
log() { printf '[get-design-done bootstrap] %s\n' "$*" >&2; }
|
|
33
|
-
|
|
34
|
-
clone_or_update() {
|
|
35
|
-
local repo_url="$1"
|
|
36
|
-
local target="$2"
|
|
37
|
-
if [[ -d "${target}/.git" ]]; then
|
|
38
|
-
log "updating ${target}"
|
|
39
|
-
git -C "${target}" pull --quiet --ff-only 2>/dev/null || log "pull failed for ${target} (continuing)"
|
|
40
|
-
elif [[ -d "${target}" ]]; then
|
|
41
|
-
log "${target} exists and is not a git checkout — skipping"
|
|
42
|
-
else
|
|
43
|
-
log "cloning ${repo_url} -> ${target}"
|
|
44
|
-
git clone --quiet --depth 1 "${repo_url}" "${target}" || log "clone failed for ${repo_url}"
|
|
45
|
-
fi
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
# Required library: awesome-design-md
|
|
49
|
-
clone_or_update "https://github.com/VoltAgent/awesome-design-md.git" "${HOME}/.claude/libs/awesome-design-md"
|
|
50
|
-
|
|
51
|
-
# Soft notice for companion skills we cannot auto-install.
|
|
52
|
-
if [[ ! -d "${HOME}/.claude/skills/emil-design-eng" ]]; then
|
|
53
|
-
log "optional: emil-design-eng skill not found in ~/.claude/skills. See get-design-done README for install options."
|
|
54
|
-
fi
|
|
55
|
-
|
|
56
|
-
# Phase 10.1: ensure .design/budget.json exists with defaults (D-12)
|
|
57
|
-
DESIGN_DIR="$(pwd)/.design"
|
|
58
|
-
mkdir -p "${DESIGN_DIR}"
|
|
59
|
-
if [ ! -f "${DESIGN_DIR}/budget.json" ]; then
|
|
60
|
-
cat > "${DESIGN_DIR}/budget.json" <<'BUDGET_EOF'
|
|
61
|
-
{
|
|
62
|
-
"per_task_cap_usd": 2.00,
|
|
63
|
-
"per_phase_cap_usd": 20.00,
|
|
64
|
-
"tier_overrides": {},
|
|
65
|
-
"auto_downgrade_on_cap": true,
|
|
66
|
-
"cache_ttl_seconds": 3600,
|
|
67
|
-
"enforcement_mode": "enforce"
|
|
68
|
-
}
|
|
69
|
-
BUDGET_EOF
|
|
70
|
-
fi
|
|
71
|
-
|
|
72
|
-
# Phase 10.1: ensure .design/telemetry/ directory is writable
|
|
73
|
-
mkdir -p "${DESIGN_DIR}/telemetry"
|
|
74
|
-
|
|
75
|
-
# Record success so we don't re-run until the bundled manifest changes.
|
|
76
|
-
if [[ -f "${MANIFEST}" ]]; then
|
|
77
|
-
cp "${MANIFEST}" "${MARKER}"
|
|
78
|
-
fi
|
|
79
|
-
|
|
80
|
-
exit 0
|