@hegemonart/get-design-done 1.43.0 → 1.44.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.
@@ -5,14 +5,14 @@
5
5
  },
6
6
  "metadata": {
7
7
  "description": "Get Design Done — 5-stage agent-orchestrated design pipeline with 9 connections, handoff-first workflow, bidirectional Figma write-back, 22+ specialized agents, queryable knowledge layer (intel store, dependency analysis, learnings extraction), and a self-improvement loop (reflector, frontmatter + budget feedback, global-skills layer). v1.20.0 ships the SDK foundation: gdd-state MCP server (11 typed tools), lockfile-safe STATE.md mutations, event stream, and resilience primitives (jittered-backoff, rate-guard, error-classifier, iteration-budget) for rate-limit + 429 + context-overflow recovery. Full CI/CD pipeline (Node 22/24 × Linux/macOS/Windows) and release automation (auto-tag + GitHub Release + release-time smoke test).",
8
- "version": "1.43.0"
8
+ "version": "1.44.0"
9
9
  },
10
10
  "plugins": [
11
11
  {
12
12
  "name": "get-design-done",
13
13
  "source": "./",
14
14
  "description": "Agent-orchestrated 5-stage design pipeline: Brief → Explore → Plan → Design → Verify. 22+ specialized agents, 9 connections (Figma, Refero, Preview, Storybook, Chromatic, Figma Writer, Graphify, Pinterest, Claude Design), Claude Design handoff, bidirectional Figma write-back, and a queryable intel store (.design/intel/) for dependency and learnings queries. Standalone commands: style, darkmode, compare, figma-write, graphify, handoff, analyze-dependencies, skill-manifest, extract-learnings. Embeds NNG heuristics, WCAG thresholds, typographic systems, motion framework, and anti-pattern catalog. Ships with a full CI/CD pipeline (Node 22/24 × Linux/macOS/Windows) and release automation. Optimization layer (v1.0.4.1, retroactive): gdd-router + gdd-cache-manager skills, PreToolUse budget-enforcer hook, tier-aware agent frontmatter, lazy checker gates, streaming synthesizer, /gdd:warm-cache + /gdd:optimize commands, and cost telemetry at .design/telemetry/costs.jsonl — targeting 50-70% per-task token-cost reduction with no quality-floor regression. v1.20.0 SDK foundation: gdd-state MCP server (11 typed tools), lockfile-safe STATE.md mutations, event stream at .design/telemetry/events.jsonl, resilience primitives (jittered-backoff, rate-guard, error-classifier, iteration-budget) with rate-limit + 429 + context-overflow recovery, and TypeScript toolchain.",
15
- "version": "1.43.0",
15
+ "version": "1.44.0",
16
16
  "author": {
17
17
  "name": "hegemonart"
18
18
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "get-design-done",
3
3
  "short_name": "gdd",
4
- "version": "1.43.0",
4
+ "version": "1.44.0",
5
5
  "description": "Agent-orchestrated 5-stage design pipeline: Brief → Explore → Plan → Design → Verify. 22+ specialized agents, 9 connections (Figma, Refero, Preview, Storybook, Chromatic, Figma Writer, Graphify, Pinterest, Claude Design), handoff-first workflow via Claude Design bundles, bidirectional Figma write-back (annotations, Code Connect), queryable intel store (`.design/intel/`) for O(1) design surface lookups, and self-improvement loop (reflector agent, frontmatter + budget feedback, global-skills layer at `~/.claude/gdd/global-skills/`). Standalone commands: style, darkmode, compare, figma-write, graphify, handoff, analyze-dependencies, skill-manifest, extract-learnings, reflect, apply-reflections. Embeds NNG heuristics, WCAG thresholds, typographic systems, motion framework, and anti-pattern catalog. Ships with a full CI/CD pipeline (Node 22/24 × Linux/macOS/Windows, lint + schema + frontmatter + stale-ref + shellcheck + gitleaks + injection-scan + blocking size-budget) and release automation (auto-tag + GitHub Release + release-time smoke test). Optimization layer (v1.0.4.1, retroactive): gdd-router + gdd-cache-manager skills, PreToolUse budget-enforcer hook, tier-aware agent frontmatter, lazy checker gates, streaming synthesizer, /gdd:warm-cache + /gdd:optimize commands, and cost telemetry at .design/telemetry/costs.jsonl — targeting 50-70% per-task token-cost reduction with no quality-floor regression. v1.20.0 SDK foundation: gdd-state MCP server (11 typed tools), lockfile-safe STATE.md mutations, event stream at .design/telemetry/events.jsonl, resilience primitives (jittered-backoff, rate-guard, error-classifier, iteration-budget) with rate-limit + 429 + context-overflow recovery, and TypeScript toolchain. v1.27.7 ships gdd-mcp (Phase 27.7): 12 read-only MCP tools for sub-3s priming. v1.28.0 (Phase 28): Foundational References Tier 2 — 5 new reference files (color-theory, composition, proportion-systems, i18n, contrast-advanced), 2 verifier i18n probes + 1 explore i18n-readiness probe, 12 additive cross-link insertions across 10 existing references, 2 orthogonal audit-scoring lens-tags (composition_alignment + i18n_readiness).",
6
6
  "author": {
7
7
  "name": "hegemonart",
package/CHANGELOG.md CHANGED
@@ -4,6 +4,52 @@ All notable changes to get-design-done are documented here. Versions follow [sem
4
4
 
5
5
  ---
6
6
 
7
+ ## [1.44.0] - 2026-06-02
8
+
9
+ ### Phase 44 - Harness Capability Matrix
10
+
11
+ Verifying support for a harness used to mean reading five reference files plus the README, with no "is
12
+ this still current?" stamp anywhere. Phase 44 consolidates it into a generated `HARNESSES.md` backed by
13
+ one source of truth, with an honest status taxonomy and a freshness gate. Planned and executed via the GSD
14
+ pipeline (parallel research + pattern-mapper subagents, then parallel executor agents). No new runtime
15
+ dependency, no new egress.
16
+
17
+ ### Breaking changes
18
+
19
+ - **A harness freshness gate now runs in CI.** `npm run check:harness-freshness` warns at 60 days and
20
+ fails at 180 days for harnesses marked `tested` (others report `n/a` and never fail). A `tested` harness
21
+ whose `last_verified` stamp goes stale will fail the build until re-verified with
22
+ `npm run verify:harness <id>`. CI also gains `npm run build:harnesses:check` (HARNESSES.md drift gate)
23
+ and `npm run validate:manifest`. Contributors editing harness support must edit
24
+ `scripts/lib/manifest/harnesses.json` and regenerate `HARNESSES.md`; see `CONTRIBUTING.md`.
25
+
26
+ ### Added
27
+
28
+ - **`HARNESSES.md`** at repo root - the human-readable capability matrix (skill discovery, command syntax,
29
+ MCP, placeholder substitution, install path, status) + per-harness deep-dive links + a `Last verified`
30
+ stamp. GENERATED by `scripts/generate-harnesses-md.cjs` from the SoT; CI drift-gates it.
31
+ - **Harness matrix as a view of the Phase 41.5 SoT** - `scripts/lib/manifest/harnesses.json` records gain
32
+ a `capability_matrix` + `last_verified` + `fragment_links`; the manifest schema + `validate:manifest`
33
+ gate them. Unified with Phase 42's `harness-configs.cjs` (a `phase-44-harness-agreement` test fails on
34
+ any ID or command-syntax disagreement).
35
+ - **`scripts/lib/harness-freshness.cjs`** (shippable, pure, status-aware) + `scripts/check-harness-freshness.cjs`
36
+ (CLI) + `gdd:health` check #8 (`harness_freshness`).
37
+ - **`scripts/verify-harness.cjs <id>`** - runs the Phase 42 compile + smoke, then atomically stamps
38
+ `last_verified` and regenerates `HARNESSES.md`.
39
+ - **Honest status taxonomy** - `claude` is `tested`; the five peer-CLI runtimes (codex, gemini, cursor,
40
+ copilot, qwen) are `experimental`; the other eight are `untested`. The five reference fragments stay as
41
+ appendices, cross-linked from the matrix (a cross-link checker fails generation on a broken anchor).
42
+
43
+ ### Notes
44
+
45
+ - 6-manifest lockstep at **v1.44.0** + `OFF_CADENCE_VERSIONS.add('1.44.0')` + 37 `manifests-version.txt`
46
+ baselines forward-propagated 1.43.0 -> 1.44.0.
47
+ - `gdd_health` now returns 8 checks (harness_freshness added). The generator, freshness CLI, and verify
48
+ script are maintainer-only (not shipped); only `scripts/lib/harness-freshness.cjs` ships. Tarball golden
49
+ 868 -> 869 (+`scripts/lib/harness-freshness.cjs`). `HARNESSES.md` is repo-root, not in the npm tarball.
50
+
51
+ ---
52
+
7
53
  ## [1.43.0] - 2026-06-02
8
54
 
9
55
  ### Phase 43 - Editorial Quality Floor
package/README.md CHANGED
@@ -247,6 +247,8 @@ All 14 runtimes receive their native artifact layout (`skills/`, `command/`, `ag
247
247
 
248
248
  **Editorial quality floor (v1.43.0).** A tool that audits design quality should hold its own prose to the same bar. `npm run lint:prose` is a CI gate that fails on em dashes, prose double hyphens, and AI-prose tells (`load-bearing`, `leverage`, `robust`, `seamless`, ...) across the README, `SKILL.md`, `source/skills/`, `agents/`, `CHANGELOG.md`, and `reference/` (bodies and frontmatter descriptions). Fenced/inline code, HTML comments, and Cyrillic-majority files are skipped. The ruleset lives in `STYLE.md`, generated from the shared denylist at `scripts/lib/manifest/prose-denylist.json`. See `CONTRIBUTING.md`. **No new runtime dependency.**
249
249
 
250
+ **Harness capability matrix (v1.44.0).** The full per-harness support matrix (skill discovery, command syntax, MCP, install path, status) lives in **[`HARNESSES.md`](HARNESSES.md)** at the repo root, generated from `scripts/lib/manifest/harnesses.json` (the single source of truth; CI drift-gates it). Each harness carries an honest status (`tested` / `experimental` / `untested`) and a `last_verified` stamp; a freshness gate warns at 60 days and fails at 180 for `tested` harnesses, surfaced in `/gdd:health`. The 14-harness count above is the same SoT the matrix reads, so it cannot drift. The five deep-dive reference files (`reference/codex-tools.md`, `reference/gemini-tools.md`, `reference/peer-cli-capabilities.md`, `reference/peer-protocols.md`, `reference/runtime-models.md`) remain as appendices linked from the matrix. **No new runtime dependency.**
251
+
250
252
  Verify with:
251
253
 
252
254
  ```
@@ -67,7 +67,7 @@ Token PRESENCE only is detected (D-10) - the token value is never read, logged,
67
67
 
68
68
  The `gdd_health` MCP surface also reports a `skill_discipline` check (Phase 32) confirming the using-gdd SessionStart bootstrap is live - detail is one of three exact strings:
69
69
  - `skill-discipline: ready` - `skills/using-gdd/SKILL.md` exists AND `hooks/hooks.json` SessionStart wires `inject-using-gdd.sh` (status `ok`).
70
- - `skill-discipline: missing using-gdd` (skill absent) or `skill-discipline: hook not wired` (skill present, no SessionStart inject) - both `warn`.
70
+ - `skill-discipline: missing using-gdd` (skill absent) or `skill-discipline: hook not wired` (skill present, no SessionStart inject) - both `warn`. The MCP surface also reports a `harness_freshness` check (Phase 44): per-harness `last_verified` age, status-aware (only `tested` harnesses warn at 60d / fail at 180d; others `n/a`). Full taxonomy in `HARNESSES.md`; refresh with `npm run verify:harness <id>`.
71
71
 
72
72
  ## Check MCP registration (gdd-mcp)
73
73
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hegemonart/get-design-done",
3
- "version": "1.43.0",
3
+ "version": "1.44.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",
@@ -65,6 +65,10 @@
65
65
  "lint:design": "node bin/gdd-detect test/fixtures/detect/negative --json",
66
66
  "build:style": "node scripts/generate-style-md.cjs",
67
67
  "build:style:check": "node scripts/generate-style-md.cjs --check",
68
+ "build:harnesses": "node scripts/generate-harnesses-md.cjs",
69
+ "build:harnesses:check": "node scripts/generate-harnesses-md.cjs --check",
70
+ "check:harness-freshness": "node scripts/check-harness-freshness.cjs",
71
+ "verify:harness": "node scripts/verify-harness.cjs",
68
72
  "sync:rule-catalogue": "node scripts/sync-rule-catalogue.cjs --check",
69
73
  "validate:manifest": "node scripts/validate-manifest.cjs --check",
70
74
  "validate:schemas": "node --experimental-strip-types scripts/validate-schemas.ts",
@@ -0,0 +1,59 @@
1
+ // Phase 44 - harness freshness (shippable pure module). Read by health-mirror + check-harness-freshness.cjs.
2
+ 'use strict';
3
+
4
+ const { readHarnesses } = require('./manifest/index.cjs');
5
+
6
+ const WARN_DAYS = 60;
7
+ const FAIL_DAYS = 180;
8
+ const MS_PER_DAY = 86400000;
9
+
10
+ /**
11
+ * Returns the age of a last_verified timestamp in fractional days.
12
+ * Returns Infinity when the timestamp is absent or unparseable.
13
+ * @param {string|null|undefined} last_verified
14
+ * @param {number} nowMs
15
+ * @returns {number}
16
+ */
17
+ function ageInDays(last_verified, nowMs) {
18
+ if (!last_verified) return Infinity;
19
+ const t = Date.parse(last_verified);
20
+ if (!Number.isFinite(t)) return Infinity;
21
+ return (nowMs - t) / MS_PER_DAY;
22
+ }
23
+
24
+ /**
25
+ * Evaluate freshness for every harness in the manifest (or a supplied list).
26
+ *
27
+ * STATUS-AWARE (D-04): only `tested` harnesses can warn/fail on a stale
28
+ * last_verified date. experimental / untested / known-broken harnesses
29
+ * make no freshness promise — their freshness is always 'n/a'.
30
+ *
31
+ * @param {{ nowMs?: number, harnesses?: object[] }} [opts]
32
+ * @returns {{ id: string, status: string, last_verified: string|null, age_days: number|null, freshness: string }[]}
33
+ */
34
+ function checkFreshness({ nowMs, harnesses } = {}) {
35
+ const list = harnesses || readHarnesses().harnesses || [];
36
+ const now = typeof nowMs === 'number' ? nowMs : Date.now();
37
+
38
+ return list.map((h) => {
39
+ const status = (h.capability_matrix && h.capability_matrix.status) || 'untested';
40
+ const age = ageInDays(h.last_verified, now);
41
+
42
+ // Only `tested` harnesses carry a freshness obligation.
43
+ // All other statuses → 'n/a' (never a build failure).
44
+ let freshness = 'n/a';
45
+ if (status === 'tested') {
46
+ freshness = age >= FAIL_DAYS ? 'fail' : age >= WARN_DAYS ? 'warn' : 'ok';
47
+ }
48
+
49
+ return {
50
+ id: h.id,
51
+ status,
52
+ last_verified: h.last_verified || null,
53
+ age_days: Number.isFinite(age) ? Math.floor(age) : null,
54
+ freshness,
55
+ };
56
+ });
57
+ }
58
+
59
+ module.exports = { checkFreshness, ageInDays, WARN_DAYS, FAIL_DAYS };
@@ -51,6 +51,7 @@ const fs = require('node:fs');
51
51
  const path = require('node:path');
52
52
 
53
53
  const { getDisableReason } = require('../issue-reporter/kill-switch.cjs');
54
+ const { checkFreshness, WARN_DAYS, FAIL_DAYS } = require('../harness-freshness.cjs');
54
55
 
55
56
  function fileExists(p) {
56
57
  try {
@@ -211,6 +212,32 @@ async function getHealthChecks(rootDir) {
211
212
  checks.push({ name: 'skill_discipline', status, detail });
212
213
  }
213
214
 
215
+ // 8. harness_freshness — per-harness last_verified age (Phase 44). PURE: reads the manifest SoT via the
216
+ // shippable harness-freshness module; status-aware (only `tested` harnesses can warn/fail). NEVER throws.
217
+ {
218
+ let status = 'ok';
219
+ let detail;
220
+ try {
221
+ const results = checkFreshness();
222
+ const failing = results.filter((r) => r.freshness === 'fail');
223
+ const warning = results.filter((r) => r.freshness === 'warn');
224
+ const tested = results.filter((r) => r.status === 'tested');
225
+ if (failing.length) {
226
+ status = 'fail';
227
+ detail = `harness freshness: ${failing.length} stale (>${FAIL_DAYS}d): ${failing.map((r) => r.id).join(', ')}`;
228
+ } else if (warning.length) {
229
+ status = 'warn';
230
+ detail = `harness freshness: ${warning.length} aging (>${WARN_DAYS}d): ${warning.map((r) => r.id).join(', ')}`;
231
+ } else {
232
+ detail = `harness freshness: ${tested.length} tested harness(es) current`;
233
+ }
234
+ } catch {
235
+ status = 'warn';
236
+ detail = 'harness freshness: unavailable';
237
+ }
238
+ checks.push({ name: 'harness_freshness', status, detail });
239
+ }
240
+
214
241
  return { checks };
215
242
  }
216
243
 
@@ -7,85 +7,351 @@
7
7
  "id": "claude",
8
8
  "name": "Claude Code",
9
9
  "config_dir": ".claude",
10
- "runtime_models_ref": "reference/runtime-models.md#claude"
10
+ "runtime_models_ref": "reference/runtime-models.md#claude",
11
+ "capability_matrix": {
12
+ "skill_discovery": true,
13
+ "frontmatter_fields_supported": [
14
+ "name",
15
+ "description",
16
+ "argument-hint",
17
+ "tools",
18
+ "disable-model-invocation"
19
+ ],
20
+ "command_syntax": "/gdd:<skill>",
21
+ "mcp_support": true,
22
+ "placeholder_substitution": true,
23
+ "install_path": "dist/claude-code/.claude/skills/",
24
+ "status": "tested"
25
+ },
26
+ "last_verified": "2026-06-02",
27
+ "capability_notes": "Host runtime. Marketplace-registered, end-to-end documented, Phase 42 golden baseline.",
28
+ "fragment_links": [
29
+ "reference/runtime-models.md#claude---claude-code"
30
+ ]
11
31
  },
12
32
  {
13
33
  "id": "codex",
14
34
  "name": "OpenAI Codex CLI",
15
35
  "config_dir": ".codex",
16
- "runtime_models_ref": "reference/runtime-models.md#codex"
36
+ "runtime_models_ref": "reference/runtime-models.md#codex",
37
+ "capability_matrix": {
38
+ "skill_discovery": true,
39
+ "frontmatter_fields_supported": [
40
+ "name",
41
+ "description",
42
+ "tools"
43
+ ],
44
+ "command_syntax": "/gdd-<skill>",
45
+ "mcp_support": true,
46
+ "placeholder_substitution": true,
47
+ "install_path": "dist/codex/.codex/skills/",
48
+ "status": "experimental"
49
+ },
50
+ "last_verified": null,
51
+ "capability_notes": "Peer-CLI delegation target (ASP). Flat /gdd- command namespace. MCP auto-registered.",
52
+ "fragment_links": [
53
+ "reference/runtime-models.md#codex---openai-codex-cli",
54
+ "reference/codex-tools.md#tool-name-mapping",
55
+ "reference/peer-cli-capabilities.md#codex-asp",
56
+ "reference/peer-protocols.md#asp---app-server-protocol-codex"
57
+ ]
17
58
  },
18
59
  {
19
60
  "id": "gemini",
20
61
  "name": "Gemini CLI",
21
62
  "config_dir": ".gemini",
22
- "runtime_models_ref": "reference/runtime-models.md#gemini"
63
+ "runtime_models_ref": "reference/runtime-models.md#gemini",
64
+ "capability_matrix": {
65
+ "skill_discovery": true,
66
+ "frontmatter_fields_supported": [
67
+ "name",
68
+ "description",
69
+ "tools"
70
+ ],
71
+ "command_syntax": "/gdd:<skill>",
72
+ "mcp_support": true,
73
+ "placeholder_substitution": true,
74
+ "install_path": "dist/gemini/.gemini/skills/",
75
+ "status": "experimental"
76
+ },
77
+ "last_verified": null,
78
+ "capability_notes": "",
79
+ "fragment_links": [
80
+ "reference/runtime-models.md#gemini---gemini-cli",
81
+ "reference/gemini-tools.md#tool-name-mapping",
82
+ "reference/peer-cli-capabilities.md#gemini-acp",
83
+ "reference/peer-protocols.md#acp---agent-client-protocol"
84
+ ]
23
85
  },
24
86
  {
25
87
  "id": "qwen",
26
88
  "name": "Qwen Code",
27
89
  "config_dir": ".qwen",
28
- "runtime_models_ref": "reference/runtime-models.md#qwen"
90
+ "runtime_models_ref": "reference/runtime-models.md#qwen",
91
+ "capability_matrix": {
92
+ "skill_discovery": true,
93
+ "frontmatter_fields_supported": [
94
+ "name",
95
+ "description",
96
+ "tools"
97
+ ],
98
+ "command_syntax": "/gdd:<skill>",
99
+ "mcp_support": false,
100
+ "placeholder_substitution": true,
101
+ "install_path": "dist/qwen/.qwen/skills/",
102
+ "status": "experimental"
103
+ },
104
+ "last_verified": null,
105
+ "capability_notes": "",
106
+ "fragment_links": [
107
+ "reference/runtime-models.md#qwen---qwen-code",
108
+ "reference/peer-cli-capabilities.md#qwen-acp",
109
+ "reference/peer-protocols.md#acp---agent-client-protocol"
110
+ ]
29
111
  },
30
112
  {
31
113
  "id": "kilo",
32
114
  "name": "Kilo Code",
33
115
  "config_dir": ".kilo",
34
- "runtime_models_ref": "reference/runtime-models.md#kilo"
116
+ "runtime_models_ref": "reference/runtime-models.md#kilo",
117
+ "capability_matrix": {
118
+ "skill_discovery": true,
119
+ "frontmatter_fields_supported": [
120
+ "name",
121
+ "description",
122
+ "tools"
123
+ ],
124
+ "command_syntax": "/gdd:<skill>",
125
+ "mcp_support": false,
126
+ "placeholder_substitution": true,
127
+ "install_path": "dist/kilo/.kilo/skills/",
128
+ "status": "untested"
129
+ },
130
+ "last_verified": null,
131
+ "capability_notes": "",
132
+ "fragment_links": [
133
+ "reference/runtime-models.md#kilo---kilo-code"
134
+ ]
35
135
  },
36
136
  {
37
137
  "id": "copilot",
38
138
  "name": "GitHub Copilot CLI",
39
139
  "config_dir": ".copilot",
40
- "runtime_models_ref": "reference/runtime-models.md#copilot"
140
+ "runtime_models_ref": "reference/runtime-models.md#copilot",
141
+ "capability_matrix": {
142
+ "skill_discovery": true,
143
+ "frontmatter_fields_supported": [
144
+ "name",
145
+ "description",
146
+ "tools"
147
+ ],
148
+ "command_syntax": "/gdd:<skill>",
149
+ "mcp_support": false,
150
+ "placeholder_substitution": true,
151
+ "install_path": "dist/copilot/.copilot/skills/",
152
+ "status": "experimental"
153
+ },
154
+ "last_verified": null,
155
+ "capability_notes": "",
156
+ "fragment_links": [
157
+ "reference/runtime-models.md#copilot---github-copilot-cli",
158
+ "reference/peer-cli-capabilities.md#copilot-acp",
159
+ "reference/peer-protocols.md#acp---agent-client-protocol"
160
+ ]
41
161
  },
42
162
  {
43
163
  "id": "cursor",
44
164
  "name": "Cursor",
45
165
  "config_dir": ".cursor",
46
- "runtime_models_ref": "reference/runtime-models.md#cursor"
166
+ "runtime_models_ref": "reference/runtime-models.md#cursor",
167
+ "capability_matrix": {
168
+ "skill_discovery": true,
169
+ "frontmatter_fields_supported": [
170
+ "name",
171
+ "description",
172
+ "tools"
173
+ ],
174
+ "command_syntax": "/gdd:<skill>",
175
+ "mcp_support": false,
176
+ "placeholder_substitution": true,
177
+ "install_path": "dist/cursor/.cursor/skills/",
178
+ "status": "experimental"
179
+ },
180
+ "last_verified": null,
181
+ "capability_notes": "",
182
+ "fragment_links": [
183
+ "reference/runtime-models.md#cursor---cursor",
184
+ "reference/peer-cli-capabilities.md#cursor-acp",
185
+ "reference/peer-protocols.md#acp---agent-client-protocol"
186
+ ]
47
187
  },
48
188
  {
49
189
  "id": "windsurf",
50
190
  "name": "Windsurf (Cascade)",
51
191
  "config_dir": ".windsurf",
52
- "runtime_models_ref": "reference/runtime-models.md#windsurf"
192
+ "runtime_models_ref": "reference/runtime-models.md#windsurf",
193
+ "capability_matrix": {
194
+ "skill_discovery": true,
195
+ "frontmatter_fields_supported": [
196
+ "name",
197
+ "description",
198
+ "tools"
199
+ ],
200
+ "command_syntax": "/gdd:<skill>",
201
+ "mcp_support": false,
202
+ "placeholder_substitution": true,
203
+ "install_path": "dist/windsurf/.windsurf/skills/",
204
+ "status": "untested"
205
+ },
206
+ "last_verified": null,
207
+ "capability_notes": "",
208
+ "fragment_links": [
209
+ "reference/runtime-models.md#windsurf---windsurf"
210
+ ]
53
211
  },
54
212
  {
55
213
  "id": "antigravity",
56
214
  "name": "Antigravity",
57
215
  "config_dir": ".antigravity",
58
- "runtime_models_ref": "reference/runtime-models.md#antigravity"
216
+ "runtime_models_ref": "reference/runtime-models.md#antigravity",
217
+ "capability_matrix": {
218
+ "skill_discovery": true,
219
+ "frontmatter_fields_supported": [
220
+ "name",
221
+ "description",
222
+ "tools"
223
+ ],
224
+ "command_syntax": "/gdd:<skill>",
225
+ "mcp_support": false,
226
+ "placeholder_substitution": true,
227
+ "install_path": "dist/antigravity/.antigravity/skills/",
228
+ "status": "untested"
229
+ },
230
+ "last_verified": null,
231
+ "capability_notes": "",
232
+ "fragment_links": [
233
+ "reference/runtime-models.md#antigravity---antigravity"
234
+ ]
59
235
  },
60
236
  {
61
237
  "id": "augment",
62
238
  "name": "Augment",
63
239
  "config_dir": ".augment",
64
- "runtime_models_ref": "reference/runtime-models.md#augment"
240
+ "runtime_models_ref": "reference/runtime-models.md#augment",
241
+ "capability_matrix": {
242
+ "skill_discovery": true,
243
+ "frontmatter_fields_supported": [
244
+ "name",
245
+ "description",
246
+ "tools"
247
+ ],
248
+ "command_syntax": "/gdd:<skill>",
249
+ "mcp_support": false,
250
+ "placeholder_substitution": true,
251
+ "install_path": "dist/augment/.augment/skills/",
252
+ "status": "untested"
253
+ },
254
+ "last_verified": null,
255
+ "capability_notes": "",
256
+ "fragment_links": [
257
+ "reference/runtime-models.md#augment---augment"
258
+ ]
65
259
  },
66
260
  {
67
261
  "id": "trae",
68
262
  "name": "Trae",
69
263
  "config_dir": ".trae",
70
- "runtime_models_ref": "reference/runtime-models.md#trae"
264
+ "runtime_models_ref": "reference/runtime-models.md#trae",
265
+ "capability_matrix": {
266
+ "skill_discovery": true,
267
+ "frontmatter_fields_supported": [
268
+ "name",
269
+ "description",
270
+ "tools"
271
+ ],
272
+ "command_syntax": "/gdd:<skill>",
273
+ "mcp_support": false,
274
+ "placeholder_substitution": true,
275
+ "install_path": "dist/trae/.trae/skills/",
276
+ "status": "untested"
277
+ },
278
+ "last_verified": null,
279
+ "capability_notes": "",
280
+ "fragment_links": [
281
+ "reference/runtime-models.md#trae---trae"
282
+ ]
71
283
  },
72
284
  {
73
285
  "id": "codebuddy",
74
286
  "name": "CodeBuddy",
75
287
  "config_dir": ".codebuddy",
76
- "runtime_models_ref": "reference/runtime-models.md#codebuddy"
288
+ "runtime_models_ref": "reference/runtime-models.md#codebuddy",
289
+ "capability_matrix": {
290
+ "skill_discovery": true,
291
+ "frontmatter_fields_supported": [
292
+ "name",
293
+ "description",
294
+ "tools"
295
+ ],
296
+ "command_syntax": "/gdd:<skill>",
297
+ "mcp_support": false,
298
+ "placeholder_substitution": true,
299
+ "install_path": "dist/codebuddy/.codebuddy/skills/",
300
+ "status": "untested"
301
+ },
302
+ "last_verified": null,
303
+ "capability_notes": "",
304
+ "fragment_links": [
305
+ "reference/runtime-models.md#codebuddy---codebuddy"
306
+ ]
77
307
  },
78
308
  {
79
309
  "id": "cline",
80
310
  "name": "Cline",
81
311
  "config_dir": ".cline",
82
- "runtime_models_ref": "reference/runtime-models.md#cline"
312
+ "runtime_models_ref": "reference/runtime-models.md#cline",
313
+ "capability_matrix": {
314
+ "skill_discovery": true,
315
+ "frontmatter_fields_supported": [
316
+ "name",
317
+ "description",
318
+ "tools"
319
+ ],
320
+ "command_syntax": "/gdd:<skill>",
321
+ "mcp_support": false,
322
+ "placeholder_substitution": true,
323
+ "install_path": "dist/cline/.cline/skills/",
324
+ "status": "untested"
325
+ },
326
+ "last_verified": null,
327
+ "capability_notes": "Installs into .clinerules at install time (clinerules-embed special case); dist/cline/ is the compile artifact only.",
328
+ "fragment_links": [
329
+ "reference/runtime-models.md#cline---cline"
330
+ ]
83
331
  },
84
332
  {
85
333
  "id": "opencode",
86
334
  "name": "OpenCode",
87
335
  "config_dir": ".opencode",
88
- "runtime_models_ref": "reference/runtime-models.md#opencode"
336
+ "runtime_models_ref": "reference/runtime-models.md#opencode",
337
+ "capability_matrix": {
338
+ "skill_discovery": true,
339
+ "frontmatter_fields_supported": [
340
+ "name",
341
+ "description",
342
+ "tools"
343
+ ],
344
+ "command_syntax": "/gdd:<skill>",
345
+ "mcp_support": false,
346
+ "placeholder_substitution": true,
347
+ "install_path": "dist/opencode/.opencode/skills/",
348
+ "status": "untested"
349
+ },
350
+ "last_verified": null,
351
+ "capability_notes": "",
352
+ "fragment_links": [
353
+ "reference/runtime-models.md#opencode---opencode"
354
+ ]
89
355
  }
90
356
  ]
91
357
  }
@@ -30,6 +30,38 @@
30
30
  "name": {
31
31
  "type": "string",
32
32
  "minLength": 1
33
+ },
34
+ "last_verified": {
35
+ "type": ["string", "null"],
36
+ "description": "YYYY-MM-DD of the last verify-harness run; null if never verified (Phase 44)."
37
+ },
38
+ "capability_notes": {
39
+ "type": "string"
40
+ },
41
+ "fragment_links": {
42
+ "type": "array",
43
+ "items": { "type": "string" }
44
+ },
45
+ "capability_matrix": {
46
+ "type": "object",
47
+ "description": "Phase 44 harness capability matrix (a view of this SoT; HARNESSES.md is generated from it).",
48
+ "additionalProperties": true,
49
+ "required": ["status", "command_syntax", "install_path"],
50
+ "properties": {
51
+ "skill_discovery": { "type": "boolean" },
52
+ "frontmatter_fields_supported": {
53
+ "type": "array",
54
+ "items": { "type": "string" }
55
+ },
56
+ "command_syntax": { "type": "string", "minLength": 1 },
57
+ "mcp_support": { "type": "boolean" },
58
+ "placeholder_substitution": { "type": "boolean" },
59
+ "install_path": { "type": "string", "minLength": 1 },
60
+ "status": {
61
+ "type": "string",
62
+ "enum": ["tested", "experimental", "untested", "known-broken"]
63
+ }
64
+ }
33
65
  }
34
66
  }
35
67
  }
@@ -136,6 +136,107 @@ var require_kill_switch = __commonJS({
136
136
  }
137
137
  });
138
138
 
139
+ // scripts/lib/manifest/loader.cjs
140
+ var require_loader = __commonJS({
141
+ "scripts/lib/manifest/loader.cjs"(exports2, module2) {
142
+ "use strict";
143
+ var fs = require("node:fs");
144
+ var path = require("node:path");
145
+ var MANIFEST_DIR = __dirname;
146
+ var _cache = /* @__PURE__ */ new Map();
147
+ function reset() {
148
+ _cache.clear();
149
+ }
150
+ function load(name13, opts) {
151
+ const o = opts || {};
152
+ const dir = o.dir || MANIFEST_DIR;
153
+ const fallback = Object.prototype.hasOwnProperty.call(o, "fallback") ? o.fallback : {};
154
+ const abs = path.join(dir, `${name13}.json`);
155
+ let stat;
156
+ try {
157
+ stat = fs.statSync(abs);
158
+ } catch {
159
+ if (!o.quiet) process.stderr.write(`manifest: ${name13}.json not found \u2014 using empty fallback (a consumer phase may not have shipped its data yet)
160
+ `);
161
+ return fallback;
162
+ }
163
+ const cached = _cache.get(abs);
164
+ if (cached && cached.mtimeMs === stat.mtimeMs) return cached.data;
165
+ try {
166
+ const data = JSON.parse(fs.readFileSync(abs, "utf8"));
167
+ _cache.set(abs, { mtimeMs: stat.mtimeMs, data });
168
+ return data;
169
+ } catch (e) {
170
+ if (!o.quiet) process.stderr.write(`manifest: ${name13}.json parse error (${e.message}) \u2014 using empty fallback
171
+ `);
172
+ return fallback;
173
+ }
174
+ }
175
+ module2.exports = { load, reset, MANIFEST_DIR };
176
+ }
177
+ });
178
+
179
+ // scripts/lib/manifest/index.cjs
180
+ var require_manifest = __commonJS({
181
+ "scripts/lib/manifest/index.cjs"(exports2, module2) {
182
+ "use strict";
183
+ var loader = require_loader();
184
+ function readHarnesses(opts) {
185
+ return loader.load("harnesses", { ...opts, fallback: { schema_version: 1, generated_at: null, harnesses: [] } });
186
+ }
187
+ function readSkills(opts) {
188
+ return loader.load("skills", { ...opts, fallback: { schema_version: 1, skills: [] } });
189
+ }
190
+ function readProseDenylist(opts) {
191
+ return loader.load("prose-denylist", { ...opts, fallback: { schema_version: 1, tells: [] } });
192
+ }
193
+ module2.exports = {
194
+ readHarnesses,
195
+ readSkills,
196
+ readProseDenylist,
197
+ reset: loader.reset,
198
+ MANIFEST_DIR: loader.MANIFEST_DIR
199
+ };
200
+ }
201
+ });
202
+
203
+ // scripts/lib/harness-freshness.cjs
204
+ var require_harness_freshness = __commonJS({
205
+ "scripts/lib/harness-freshness.cjs"(exports2, module2) {
206
+ "use strict";
207
+ var { readHarnesses } = require_manifest();
208
+ var WARN_DAYS = 60;
209
+ var FAIL_DAYS = 180;
210
+ var MS_PER_DAY = 864e5;
211
+ function ageInDays(last_verified, nowMs) {
212
+ if (!last_verified) return Infinity;
213
+ const t = Date.parse(last_verified);
214
+ if (!Number.isFinite(t)) return Infinity;
215
+ return (nowMs - t) / MS_PER_DAY;
216
+ }
217
+ function checkFreshness({ nowMs, harnesses } = {}) {
218
+ const list = harnesses || readHarnesses().harnesses || [];
219
+ const now = typeof nowMs === "number" ? nowMs : Date.now();
220
+ return list.map((h) => {
221
+ const status = h.capability_matrix && h.capability_matrix.status || "untested";
222
+ const age = ageInDays(h.last_verified, now);
223
+ let freshness = "n/a";
224
+ if (status === "tested") {
225
+ freshness = age >= FAIL_DAYS ? "fail" : age >= WARN_DAYS ? "warn" : "ok";
226
+ }
227
+ return {
228
+ id: h.id,
229
+ status,
230
+ last_verified: h.last_verified || null,
231
+ age_days: Number.isFinite(age) ? Math.floor(age) : null,
232
+ freshness
233
+ };
234
+ });
235
+ }
236
+ module2.exports = { checkFreshness, ageInDays, WARN_DAYS, FAIL_DAYS };
237
+ }
238
+ });
239
+
139
240
  // scripts/lib/health-mirror/index.cjs
140
241
  var require_health_mirror = __commonJS({
141
242
  "scripts/lib/health-mirror/index.cjs"(exports2, module2) {
@@ -143,6 +244,7 @@ var require_health_mirror = __commonJS({
143
244
  var fs = require("node:fs");
144
245
  var path = require("node:path");
145
246
  var { getDisableReason } = require_kill_switch();
247
+ var { checkFreshness, WARN_DAYS, FAIL_DAYS } = require_harness_freshness();
146
248
  function fileExists(p) {
147
249
  try {
148
250
  return fs.statSync(p).isFile();
@@ -270,6 +372,29 @@ var require_health_mirror = __commonJS({
270
372
  }
271
373
  checks.push({ name: "skill_discipline", status, detail });
272
374
  }
375
+ {
376
+ let status = "ok";
377
+ let detail;
378
+ try {
379
+ const results = checkFreshness();
380
+ const failing = results.filter((r) => r.freshness === "fail");
381
+ const warning = results.filter((r) => r.freshness === "warn");
382
+ const tested = results.filter((r) => r.status === "tested");
383
+ if (failing.length) {
384
+ status = "fail";
385
+ detail = `harness freshness: ${failing.length} stale (>${FAIL_DAYS}d): ${failing.map((r) => r.id).join(", ")}`;
386
+ } else if (warning.length) {
387
+ status = "warn";
388
+ detail = `harness freshness: ${warning.length} aging (>${WARN_DAYS}d): ${warning.map((r) => r.id).join(", ")}`;
389
+ } else {
390
+ detail = `harness freshness: ${tested.length} tested harness(es) current`;
391
+ }
392
+ } catch {
393
+ status = "warn";
394
+ detail = "harness freshness: unavailable";
395
+ }
396
+ checks.push({ name: "harness_freshness", status, detail });
397
+ }
273
398
  return { checks };
274
399
  }
275
400
  function sessionStartWiresInject(rootDir) {
@@ -67,7 +67,7 @@ Token PRESENCE only is detected (D-10) - the token value is never read, logged,
67
67
 
68
68
  The `gdd_health` MCP surface also reports a `skill_discipline` check (Phase 32) confirming the using-gdd SessionStart bootstrap is live - detail is one of three exact strings:
69
69
  - `skill-discipline: ready` - `skills/using-gdd/SKILL.md` exists AND `hooks/hooks.json` SessionStart wires `inject-using-gdd.sh` (status `ok`).
70
- - `skill-discipline: missing using-gdd` (skill absent) or `skill-discipline: hook not wired` (skill present, no SessionStart inject) - both `warn`.
70
+ - `skill-discipline: missing using-gdd` (skill absent) or `skill-discipline: hook not wired` (skill present, no SessionStart inject) - both `warn`. The MCP surface also reports a `harness_freshness` check (Phase 44): per-harness `last_verified` age, status-aware (only `tested` harnesses warn at 60d / fail at 180d; others `n/a`). Full taxonomy in `HARNESSES.md`; refresh with `npm run verify:harness <id>`.
71
71
 
72
72
  ## Check MCP registration (gdd-mcp)
73
73