@holmes-lab/holmes-kit 0.20.2 โ†’ 0.22.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.
Files changed (59) hide show
  1. package/CHANGELOG.md +100 -0
  2. package/dist/.build-id +1 -1
  3. package/dist/holmes/cli/agents.js +1 -0
  4. package/dist/holmes/cli/doctor.d.ts +1 -0
  5. package/dist/holmes/cli/doctor.js +42 -0
  6. package/dist/holmes/cli/index.js +1 -0
  7. package/dist/holmes/cli/init.js +1 -0
  8. package/dist/holmes/cpg/language-parser-walk.js +1 -0
  9. package/dist/holmes/governance/constitution.d.ts +11 -0
  10. package/dist/holmes/governance/constitution.js +15 -1
  11. package/dist/holmes/guardrail/impact-gate.d.ts +10 -1
  12. package/dist/holmes/guardrail/impact-gate.js +19 -0
  13. package/dist/holmes/guardrail/risk-classifier.d.ts +1 -0
  14. package/dist/holmes/guardrail/risk-classifier.js +26 -3
  15. package/dist/holmes/hooks/stop.d.ts +16 -0
  16. package/dist/holmes/hooks/stop.js +116 -1
  17. package/dist/holmes/mcp/handlers/graph-operations.d.ts +1 -0
  18. package/dist/holmes/mcp/handlers/graph-operations.js +18 -1
  19. package/dist/holmes/mcp/handlers/maintenance-evidence.d.ts +4 -0
  20. package/dist/holmes/mcp/handlers/maintenance-evidence.js +16 -1
  21. package/dist/holmes/mcp/handlers/operator-inspection.d.ts +28 -1
  22. package/dist/holmes/mcp/handlers/operator-inspection.js +91 -3
  23. package/dist/holmes/mcp/handlers/spec-approval.d.ts +6 -0
  24. package/dist/holmes/mcp/handlers/spec-approval.js +87 -1
  25. package/dist/holmes/mcp/handlers/test-execution.d.ts +4 -0
  26. package/dist/holmes/mcp/handlers/test-execution.js +6 -2
  27. package/dist/holmes/mcp/handlers.d.ts +34 -1
  28. package/dist/holmes/mcp/handlers.js +5 -0
  29. package/dist/holmes/mcp/maintenance-analyze.js +1 -0
  30. package/dist/holmes/mcp/tool-schemas.js +1 -0
  31. package/dist/holmes/project/ci-runs.d.ts +46 -0
  32. package/dist/holmes/project/ci-runs.js +137 -0
  33. package/dist/holmes/project/install-scripts-policy.js +1 -0
  34. package/dist/holmes/review/evaluation-metrics.js +1 -0
  35. package/dist/holmes/review/kills-check.d.ts +40 -0
  36. package/dist/holmes/review/kills-check.js +147 -0
  37. package/dist/holmes/review/manual-baseline.js +1 -0
  38. package/dist/holmes/rtm/advisory-outcomes.d.ts +137 -0
  39. package/dist/holmes/rtm/advisory-outcomes.js +314 -0
  40. package/dist/holmes/rtm/anchor-comment.d.ts +2 -0
  41. package/dist/holmes/rtm/anchor-comment.js +8 -0
  42. package/dist/holmes/rtm/file-anchors.d.ts +9 -0
  43. package/dist/holmes/rtm/file-anchors.js +128 -0
  44. package/dist/holmes/rtm/ftt-fulfilment.d.ts +42 -0
  45. package/dist/holmes/rtm/ftt-fulfilment.js +195 -0
  46. package/dist/holmes/rtm/known-defects.d.ts +26 -0
  47. package/dist/holmes/rtm/known-defects.js +77 -0
  48. package/dist/holmes/rtm/link-census.d.ts +61 -0
  49. package/dist/holmes/rtm/link-census.js +90 -0
  50. package/dist/holmes/rtm/rtm-graph.js +1 -0
  51. package/dist/holmes/rtm/taint-benchmark.js +1 -0
  52. package/dist/holmes/rtm/trace-gaps.d.ts +20 -0
  53. package/dist/holmes/rtm/trace-gaps.js +64 -0
  54. package/dist/holmes/server/dashboard-launcher.d.ts +20 -0
  55. package/dist/holmes/server/dashboard-launcher.js +24 -1
  56. package/dist/holmes/server/dashboard.js +40 -2
  57. package/package.json +1 -1
  58. package/playbooks/author-slice/PLAYBOOK.md +30 -0
  59. package/playbooks/tdd-slice/PLAYBOOK.md +4 -0
@@ -55,6 +55,9 @@ const ast_store_1 = require("../cpg/foundation/ast-store");
55
55
  const cfg_1 = require("../cpg/foundation/cfg");
56
56
  const cdg_1 = require("../cpg/foundation/cdg");
57
57
  const cfg_view_1 = require("./cfg-view");
58
+ const link_census_1 = require("../rtm/link-census");
59
+ const test_scope_1 = require("../rtm/test-scope");
60
+ const file_anchors_1 = require("../rtm/file-anchors");
58
61
  /**
59
62
  * Start a lightweight standalone Node.js HTTP server for interactive dashboard & RTM visualization.
60
63
  *
@@ -94,10 +97,44 @@ async function startDashboardServer(options) {
94
97
  for (const s of f.implementsSpecs)
95
98
  implementedSpecIds.add(s);
96
99
  }
100
+ // @implements A-SPEC-655 โ€” the code-link axis, with a reason on every unlinked A-SPEC.
101
+ // Tests and non-AST files stay OUT of the graph (cpg-scanner.ts:141-147 is sealed); their
102
+ // anchors are read off-graph so the census can tell "anchored where the graph cannot see"
103
+ // from "no trace at all". Measured 2026-09-16 on this repository: 72 of 630 approved
104
+ // A-SPECs were invisible to the graph and every one of them was a test-only slice.
105
+ const approvedAspecs = specs.filter((s) => s.id.startsWith('A-SPEC') && s.status === 'approved');
106
+ const testAnchors = (0, test_scope_1.scanTestAnchors)(root);
107
+ const fileAnchors = (0, file_anchors_1.scanFileAnchors)(root);
108
+ const anchoredAnywhere = new Set(implementedSpecIds);
109
+ for (const ids of [...Object.values(testAnchors), ...Object.values(fileAnchors)])
110
+ for (const id of ids)
111
+ anchoredAnywhere.add(id);
112
+ const readRel = (rel) => {
113
+ const abs = path.resolve(root, rel);
114
+ if (!abs.startsWith(root + path.sep))
115
+ return null; // a Files-to-Touch line is text, not a path we trust
116
+ try {
117
+ return fs.readFileSync(abs, 'utf8');
118
+ }
119
+ catch {
120
+ return null;
121
+ }
122
+ };
123
+ const weakMentions = {};
124
+ for (const s of approvedAspecs) {
125
+ if (anchoredAnywhere.has(s.id))
126
+ continue;
127
+ const ftt = String(s.sections?.['Files to Touch'] ?? '');
128
+ const tokens = [...new Set(ftt.match(/[\w@.*-]+(?:\/[\w@.*-]+)+/g) ?? [])].filter((t) => !t.includes('*'));
129
+ weakMentions[s.id] = (0, link_census_1.weakMentionsFor)(s.id, tokens, readRel);
130
+ }
131
+ const census = (0, link_census_1.linkCensus)({ approvedIds: approvedAspecs.map((s) => s.id), implemented: implementedSpecIds, testAnchors, fileAnchors, weakMentions });
132
+ const reasonOf = new Map(census.unlinked.map((u) => [u.id, u.reason]));
97
133
  const enrichedSpecs = specs.map((s) => {
98
134
  const isA = s.id.startsWith('A-SPEC');
99
135
  const covered = isA ? implementedSpecIds.has(s.id) : s.status === 'approved';
100
- return { ...s, covered, legacyStatus: !isCanonicalStatus(s.status) };
136
+ const reason = reasonOf.get(s.id);
137
+ return { ...s, covered, legacyStatus: !isCanonicalStatus(s.status), ...(reason ? { unlinkedReason: reason } : {}) };
101
138
  });
102
139
  // Two axes, never one number. Approval (a spec was signed off) and implementation (code is
103
140
  // anchored to it) answer different questions, and a spec whose status is outside the
@@ -156,6 +193,7 @@ async function startDashboardServer(options) {
156
193
  coveredCount,
157
194
  approval,
158
195
  implementation,
196
+ linkCensus: census,
159
197
  unmapped,
160
198
  nonSpec,
161
199
  retired,
@@ -1131,7 +1169,7 @@ function renderDashboardHtml() {
1131
1169
  <div class="tree-row tree-row-aspec">
1132
1170
  <div class="tree-label">๐Ÿ”ต <strong>\${escapeHtml(a.id)}</strong>: \${escapeHtml(a.title || '')}</div>
1133
1171
  <div>
1134
- <span class="neighbor-rel \${a.covered ? 'badge-covered' : 'badge-uncovered'}" style="margin-right:8px;">\${a.covered ? 'COVERED' : 'UNCOVERED'}</span>
1172
+ <span class="neighbor-rel \${a.covered ? 'badge-covered' : 'badge-uncovered'}" style="margin-right:8px;">\${a.covered ? 'COVERED' : 'UNLINKED ยท ' + escapeHtml(a.unlinkedReason || 'none')}</span>
1135
1173
  <button class="jump-btn" onclick="focusSpecInGraph('\${escapeHtml(a.id)}')">๐Ÿ•ธ๏ธ View in Graph</button>
1136
1174
  </div>
1137
1175
  </div>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "//": "@implements A-SPEC-209",
3
3
  "name": "@holmes-lab/holmes-kit",
4
- "version": "0.20.2",
4
+ "version": "0.22.0",
5
5
  "description": "Holmes-Kit โ€” deterministic Agentic Software Engineering (ASE) harness with causal traceability (spec chain + D-CPG + RTM + phase guardrail)",
6
6
  "main": "dist/holmes/mcp/server.js",
7
7
  "types": "dist/holmes/mcp/server.d.ts",
@@ -82,6 +82,13 @@ Criteria ยท Non-Functional ยท Assumptions ยท Open Questions.** ํ•„์ˆ˜ ํ•„๋“œ: `r
82
82
  ๋ถ€๋ชจ REQ์˜ Success Criteria๊ฐ€ ์ด ์„ค๊ณ„๋กœ ์–ด๋–ป๊ฒŒ ๋‹ฌ์„ฑ๋˜๋Š”์ง€๊ฐ€ ๋ณธ๋ฌธ์ด๋‹ค. Open Questions๋Š” ๋น„์›Œ๋‘๋Š”
83
83
  ์นธ์ด ์•„๋‹ˆ๋‹ค โ€” ์•„์ง ๊ฒฐ์ •ํ•˜์ง€ ์•Š์€ ๊ฒƒ์„ ๊ฒฐ์ •ํ•˜์ง€ ์•Š์•˜๋‹ค๊ณ  ์ ๋Š” ๊ณณ์ด๊ณ , ๋‹ซ์„ ๋•Œ๋Š” ๊ทผ๊ฑฐ์™€ ํ•จ๊ป˜ ๋‹ซ๋Š”๋‹ค.
84
84
 
85
+ **๊ด€์ธก์„ ์‹ ์„คํ•˜๊ฑฐ๋‚˜ ์ขŒํ‘œ๋ฅผ ๋ฐ”๊พธ๋Š” ์Šฌ๋ผ์ด์Šค**(๊ณ„์ธกยท์›์žฅยท์นด์šดํ„ฐยท์ง€ํ‘œยท์ด๋ฒคํŠธ ๊ธฐ๋ก)๋Š” `## Non-Functional`์—
86
+ `- [observability] <๋ฌด์—‡์„ ๊ธฐ๋กํ•˜๊ณ  ์–ด๋””์„œ ์–ด๋–ค ํ‚ค๋กœ ์ฝ๋Š”๊ฐ€>` ์˜๋ฌด๋ฅผ ์ ๋Š”๋‹ค. ๊ธฐ๋ก ์ชฝ๋งŒ ๊ฒ€์ฆํ•œ ํ…Œ์ŠคํŠธ๋Š”
87
+ ์ฝ๋Š” ์ชฝ์ด ๋ณด๋Š” ์ขŒํ‘œ์— ์—†๋Š” ๊ธฐ๋ก์„ ์žก์ง€ ๋ชปํ•œ๋‹ค โ€” jarvis ์‹ค์‚ฌ๊ณ (2026-09-08): `kind`๊ฐ€ ๊ณ ์ •๋ผ ์กฐํšŒ๊ฐ€
88
+ ๊ตฌ์กฐ์ ์œผ๋กœ 0์ด์—ˆ๊ณ , ๊ทธ 0 ์œ„์—์„œ ์„ค๊ณ„ ๊ฒฐ์ •์ด ๋‘ ๋ฒˆ ๋‚ด๋ ค์กŒ๋‹ค. ์ด ์˜๋ฌด๋Š” T-SPEC์˜ `[observability]`
89
+ ์ผ€์ด์Šค์™€ ๋Œ€์‘๋˜์–ด์•ผ ํ•˜๋ฉฐ, ๋Œ€์‘์ด ์—†์œผ๋ฉด `review_scope`ยท`maintenance_analyze`๊ฐ€ `obligationGaps`๋กœ
90
+ **๋ณด๊ณ **ํ•œ๋‹ค โ€” ์ฐจ๋‹จ์ด ์•„๋‹ˆ๋ผ ๋ณด๊ณ ๋‹ค(`obligationGapsFor`; ํƒœ๊ทธ ์–ดํœ˜๋Š” ์—ด๋ ค ์žˆ์–ด ์ƒˆ ํ•„๋“œ๊ฐ€ ํ•„์š” ์—†๋‹ค).
91
+
85
92
  ## Files to Touch๋ฅผ ํ™•์ •ํ•˜๊ธฐ ์ „์— โ€” ์„ค๊ณ„-์‹œ์  ์˜ํ–ฅ ๋ฒ”์œ„ ์ฝ๊ธฐ
86
93
 
87
94
  A-SPEC์˜ Files to Touch๋Š” **์Šค์ฝ”ํ”„ ์„ ์–ธ**์ด๊ณ , ๊ทธ๋ž˜ํ”„๋Š” ๊ทธ ์„ ์–ธ์ด ๋ฌด์—‡์„ ๋น ๋œจ๋ฆฌ๋Š”์ง€ ์ด๋ฏธ ์•ˆ๋‹ค.
@@ -117,6 +124,29 @@ T-SPEC ํ•„์ˆ˜ ์„น์…˜์€ 4๋ถ„๋ฉด ๊ทธ๋Œ€๋กœ๋‹ค: **Normal ยท Corner ยท Negative ยท
117
124
  ์ผ€์ด์Šค์ธ์ง€**๊ฐ€ ๋“œ๋Ÿฌ๋‚˜๊ฒŒ ์“ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  frontmatter `depends_on: [๋Œ€์ƒ A-SPEC]` โ€” ์ด ๊ฐ„์„ ์ด ์—†์œผ๋ฉด
118
125
  ์Šน์ธํ•ด๋„ ์ฝ”๋“œ ๊ฒŒ์ดํŠธ๊ฐ€ ์—ด๋ฆฌ์ง€ ์•Š๋Š”๋‹ค โ€” ๊ทธ๋•Œ ๊ฒŒ์ดํŠธ๊ฐ€ `depends_on`์„ ์ง€๋ชฉํ•œ๋‹ค(`promote-slice`์˜ ใ€ŒT-SPEC ๊ฑฐ๋ถ€๋Š” ์ƒํƒœ๋ฅผ ๊ตฌ๋ณ„ํ•ด ๋งํ•œ๋‹คใ€).
119
126
 
127
+ ### `kills:` ๋ฌธ๋ฒ• โ€” `where`๋Š” ์†Œ์Šค ์กฐ๊ฐ์ด์ง€ ํŒŒ์ผ ๊ฒฝ๋กœ๊ฐ€ ์•„๋‹ˆ๋‹ค
128
+
129
+ T-SPEC frontmatter์˜ `kills`๋Š” ํŒ๋ณ„๋ ฅ์„ ์ŠคํŽ™ ํ•„๋“œ๋กœ ์Šน๊ฒฉํ•œ ๊ฒƒ์ด๋‹ค: ์—”์ง„(`test_run --mutate`)์ด A-SPEC์„
130
+ `@implements`ํ•˜๋Š” **ํ”„๋กœ๋•์…˜ ์†Œ์Šค ์•ˆ์˜ ๋ฆฌํ„ฐ๋Ÿด `where`๋ฅผ `mutate`๋กœ ์น˜ํ™˜**ํ•˜๊ณ , ์ปค๋ฒ„ ํ…Œ์ŠคํŠธ๊ฐ€ ๋ถ‰์–ด์ง€๋Š”์ง€
131
+ ๋ณธ๋‹ค. ๊ทธ๋ž˜์„œ `where`๋Š” ๊ทธ ์†Œ์Šค์— **๊ธ€์ž ๊ทธ๋Œ€๋กœ ์กด์žฌํ•˜๋Š” ์กฐ๊ฐ**์ด์–ด์•ผ ํ•œ๋‹ค.
132
+
133
+ ```yaml
134
+ kills:
135
+ - where: "if (reason === '')"
136
+ mutate: "if (false)"
137
+ ```
138
+
139
+ `where: src/holmes/foo.ts`์ฒ˜๋Ÿผ ํŒŒ์ผ ๊ฒฝ๋กœ๋ฅผ ์ ๊ฑฐ๋‚˜ `mutate`์— ์‚ฐ๋ฌธ("๊ฒ€์‚ฌ๋ฅผ ์ œ๊ฑฐํ•œ๋‹ค")์„ ์ ์œผ๋ฉด ์•„๋ฌด๊ฒƒ๋„
140
+ ์ ์šฉ๋˜์ง€ ์•Š๋Š”๋‹ค โ€” 2026-09-17 ์‹ค์ธก์—์„œ ์ด ์ €์žฅ์†Œ์˜ 22๊ฐœ ์—”ํŠธ๋ฆฌ ์ „๋ถ€๊ฐ€ ๊ทธ ๋ชจ์–‘์ด์—ˆ๋‹ค. ์ด์ œ ๋‘ ๊ณณ์ด ๊ทธ๊ฒƒ์„
141
+ ๋งํ•œ๋‹ค: T-SPEC ์Šน์ธ(`spec_approve`ยท`approval_status`)์ด ์ ์šฉ ๋ถˆ๊ฐ€ ์—”ํŠธ๋ฆฌ๋ฅผ `killsAdvisory`
142
+ (`kills-unapplicable`) **์†Œ๊ฒฌ์œผ๋กœ ๋ณด๊ณ **ํ•˜๊ณ (๋ด‰์ธ์€ ๊ทธ๋Œ€๋กœ ๋œ๋‹ค), `test_run --mutate`๋Š” ์ ์šฉ๋˜์ง€ ์•Š์€
143
+ ์—”ํŠธ๋ฆฌ๋ฅผ `unapplied`๋กœ `survivors`์™€ ๊ตฌ๋ณ„ํ•ด ์‹ฃ๋Š”๋‹ค. `survivors: []`๋Š” `unapplied`๊ฐ€ ๋น„์–ด ์žˆ์„ ๋•Œ๋งŒ "์ƒ์กด
144
+ ๋ณ€์ด ์—†์Œ"์ด๋‹ค.
145
+
146
+ H-SPEC์— `[observability]` ์˜๋ฌด๊ฐ€ ์žˆ์œผ๋ฉด T-SPEC์€ **๊ธฐ๋กโ†’์กฐํšŒ ์™•๋ณต** ์ผ€์ด์Šค๋ฅผ
147
+ `- [observability] Given โ€ฆ When โ€ฆ Then โ€ฆ`์œผ๋กœ ์ ๋Š”๋‹ค: ์“ฐ๊ธฐ API๋ฅผ ๋ถ€๋ฅด๊ณ , **์ฝ๋Š” ์ชฝ์ด ์‹ค์ œ๋กœ ์“ฐ๋Š” ์ฝ๊ธฐ
148
+ API**๋กœ ๊ฐ™์€ ์ขŒํ‘œ๋ฅผ ์กฐํšŒํ•ด ํ–‰์ด ์žˆ์Œ์„ ๋‹จ์–ธํ•œ๋‹ค. ํƒœ๊ทธ๋Š” ์ค„ ์‹œ์ž‘์—์„œ๋งŒ ์ธ์‹๋œ๋‹ค(`nonfunctional.ts`).
149
+
120
150
  ## ํ”ํ•œ ์˜คํ•ด
121
151
 
122
152
  | ์˜คํ•ด | ์‚ฌ์‹ค |
@@ -57,6 +57,10 @@ holmes๋Š” ๊ธฐ๊ณ„์ ์œผ๋กœ ํŒ๋ณ„ํ•œ๋‹ค: `red-error`๋กœ๋Š” redโ†’green ์‹œํ€€์Šค
57
57
  ์š”๊ตฌํ•œ๋‹ค.
58
58
  - `[๋ช…์˜ˆ์ œ]` ํ…Œ์ŠคํŠธ๋ฅผ ์“ฐ๊ธฐ ์ „์— **๊ทธ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํŒจ์‹œํ‚ฌ ํ”„๋กœ๋•์…˜ ๋ณ€๊ฒฝ์„ ํ•œ ๋ฌธ์žฅ์œผ๋กœ ๋งํ•˜๋ผ**. ๋งํ• 
59
59
  ์ˆ˜ ์—†๋‹ค๋ฉด ๊ทธ ํ…Œ์ŠคํŠธ๋Š” ๋ฌด์—‡๋„ ์ง€ํ‚ค์ง€ ๋ชปํ•œ๋‹ค. (C์ธต `kills:`๊ฐ€ ์ด๋ฅผ ์ŠคํŽ™ ํ•„๋“œ๋กœ ์Šน๊ฒฉํ•œ๋‹ค.)
60
+ - `[obligationGaps]` ๊ด€์ธก์„ ์‹ ์„คํ•˜๋Š” ์Šฌ๋ผ์ด์Šค๋Š” **๊ธฐ๋กโ†’์กฐํšŒ ์™•๋ณต**์„ ๋‹จ์–ธํ•œ๋‹ค โ€” ๊ธฐ๋ก ํ•จ์ˆ˜๋ฅผ ๋ถ€๋ฅธ ๋’ค
61
+ ์†Œ๋น„์ž๊ฐ€ ์“ฐ๋Š” ์ฝ๊ธฐ ๊ฒฝ๋กœ๋กœ ๊ฐ™์€ ์ขŒํ‘œ๋ฅผ ์ฝ๋Š”๋‹ค. H-SPEC `[observability]` ์˜๋ฌด์™€ T-SPEC ์ผ€์ด์Šค ํƒœ๊ทธ์˜
62
+ ๋Œ€์‘์„ `obligationGapsFor`๊ฐ€ ๊ฒ€์‚ฌํ•ด `obligationGaps`๋กœ ๋ณด๊ณ ํ•œ๋‹ค(์ง‘ํ–‰ ํ‘œ๋Š” ๊ทธ๋Œ€๋กœ: ์ด๊ฒƒ์€ ๊ฒŒ์ดํŠธ๊ฐ€
63
+ ์•„๋‹ˆ๋ผ ๋ณด๊ณ ๋‹ค).
60
64
 
61
65
  ## ์ง‘ํ–‰ ์š”์•ฝ
62
66