@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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +46 -0
- package/README.md +2 -0
- package/dist/claude-code/.claude/skills/health/SKILL.md +1 -1
- package/package.json +5 -1
- package/scripts/lib/harness-freshness.cjs +59 -0
- package/scripts/lib/health-mirror/index.cjs +27 -0
- package/scripts/lib/manifest/harnesses.json +280 -14
- package/scripts/lib/manifest/schemas/harnesses.schema.json +32 -0
- package/sdk/mcp/gdd-mcp/server.js +125 -0
- package/skills/health/SKILL.md +1 -1
|
@@ -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.
|
|
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.
|
|
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.
|
|
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.
|
|
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) {
|
package/skills/health/SKILL.md
CHANGED
|
@@ -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
|
|