@holmes-lab/holmes-kit 0.1.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 (107) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/LICENSE +21 -0
  3. package/README.md +102 -0
  4. package/bin/holmes-hook-antigravity.js +31 -0
  5. package/bin/holmes-kit.js +23 -0
  6. package/bin/holmes-mcp.js +34 -0
  7. package/bin/holmes-stop-antigravity.js +29 -0
  8. package/dist/.build-id +1 -0
  9. package/dist/holmes/cli/agents.js +168 -0
  10. package/dist/holmes/cli/doctor.js +625 -0
  11. package/dist/holmes/cli/gitignore-merge.js +84 -0
  12. package/dist/holmes/cli/governed-precondition.js +157 -0
  13. package/dist/holmes/cli/index.js +384 -0
  14. package/dist/holmes/cli/init.js +462 -0
  15. package/dist/holmes/cli/playbook-skills.js +711 -0
  16. package/dist/holmes/cli/roles-readme.js +134 -0
  17. package/dist/holmes/cli/settings-merge.js +122 -0
  18. package/dist/holmes/config/config.js +70 -0
  19. package/dist/holmes/context/bundler.js +114 -0
  20. package/dist/holmes/context/render.js +29 -0
  21. package/dist/holmes/context/tiers.js +110 -0
  22. package/dist/holmes/context/tokens.js +8 -0
  23. package/dist/holmes/cpg/cpg-scanner.js +213 -0
  24. package/dist/holmes/cpg/hash-cache.js +86 -0
  25. package/dist/holmes/cpg/language-parser-walk.js +917 -0
  26. package/dist/holmes/cpg/language-parser-worker.js +81 -0
  27. package/dist/holmes/cpg/language-parser.js +234 -0
  28. package/dist/holmes/cpg/scan-cache.js +108 -0
  29. package/dist/holmes/cpg/source-path.js +44 -0
  30. package/dist/holmes/cpg/test-files.js +84 -0
  31. package/dist/holmes/governance/constitution-debt.js +73 -0
  32. package/dist/holmes/governance/constitution-report.js +25 -0
  33. package/dist/holmes/governance/constitution.js +129 -0
  34. package/dist/holmes/governance/identity.js +30 -0
  35. package/dist/holmes/governance/ledger-lock.js +165 -0
  36. package/dist/holmes/governance/ledger-store.conformance.js +90 -0
  37. package/dist/holmes/governance/ledger-store.js +106 -0
  38. package/dist/holmes/governance/progress-ledger.js +83 -0
  39. package/dist/holmes/governance/provenance-chain.js +365 -0
  40. package/dist/holmes/governance/provenance-ledger.js +0 -0
  41. package/dist/holmes/governance/provenance-schema.js +47 -0
  42. package/dist/holmes/governance/replica-id.js +106 -0
  43. package/dist/holmes/governance/role-policy.js +137 -0
  44. package/dist/holmes/governance/trust-score.js +43 -0
  45. package/dist/holmes/guardrail/anchors.js +31 -0
  46. package/dist/holmes/guardrail/blind-spots.js +38 -0
  47. package/dist/holmes/guardrail/decision-ledger.js +107 -0
  48. package/dist/holmes/guardrail/executable-artifact.js +129 -0
  49. package/dist/holmes/guardrail/governance-history.js +101 -0
  50. package/dist/holmes/guardrail/phase.js +169 -0
  51. package/dist/holmes/guardrail/risk-classifier.js +450 -0
  52. package/dist/holmes/guardrail/risk-gate.js +160 -0
  53. package/dist/holmes/guardrail/risk-types.js +6 -0
  54. package/dist/holmes/guardrail/tspec-state.js +392 -0
  55. package/dist/holmes/guardrail/write-target.js +224 -0
  56. package/dist/holmes/hooks/adapters/antigravity.js +194 -0
  57. package/dist/holmes/hooks/pre-tool-use.js +1262 -0
  58. package/dist/holmes/hooks/stop.js +416 -0
  59. package/dist/holmes/mcp/basis.js +162 -0
  60. package/dist/holmes/mcp/handlers.js +1831 -0
  61. package/dist/holmes/mcp/server.js +71 -0
  62. package/dist/holmes/mcp/stdio-client.js +165 -0
  63. package/dist/holmes/mcp/supervisor.js +178 -0
  64. package/dist/holmes/mcp/tool-schemas.js +394 -0
  65. package/dist/holmes/mcp/validate-args.js +281 -0
  66. package/dist/holmes/messages/registry.js +50 -0
  67. package/dist/holmes/project/baseline.js +210 -0
  68. package/dist/holmes/project/change-source.js +233 -0
  69. package/dist/holmes/project/ignore.js +145 -0
  70. package/dist/holmes/project/root.js +113 -0
  71. package/dist/holmes/reverse/anchor.js +162 -0
  72. package/dist/holmes/reverse/cluster.js +187 -0
  73. package/dist/holmes/reverse/draft.js +151 -0
  74. package/dist/holmes/reverse/dynamic-wiring.js +47 -0
  75. package/dist/holmes/reverse/scan.js +194 -0
  76. package/dist/holmes/reverse/surface.js +154 -0
  77. package/dist/holmes/reverse/test-map.js +263 -0
  78. package/dist/holmes/review/coverage.js +33 -0
  79. package/dist/holmes/review/findings.js +123 -0
  80. package/dist/holmes/review/package.js +40 -0
  81. package/dist/holmes/review/review-targets.js +92 -0
  82. package/dist/holmes/review/scope.js +57 -0
  83. package/dist/holmes/review/test-evidence.js +77 -0
  84. package/dist/holmes/review/test-runner.js +572 -0
  85. package/dist/holmes/rtm/dataflow-taint.js +262 -0
  86. package/dist/holmes/rtm/gap-analyzer.js +27 -0
  87. package/dist/holmes/rtm/git-changes.js +72 -0
  88. package/dist/holmes/rtm/incremental.js +45 -0
  89. package/dist/holmes/rtm/localize.js +100 -0
  90. package/dist/holmes/rtm/rtm-builder.js +191 -0
  91. package/dist/holmes/rtm/rtm-check.js +89 -0
  92. package/dist/holmes/rtm/rtm-graph.js +232 -0
  93. package/dist/holmes/rtm/taint.js +92 -0
  94. package/dist/holmes/rtm/test-scope.js +336 -0
  95. package/dist/holmes/spec/approval-blockers.js +204 -0
  96. package/dist/holmes/spec/breaking-change.js +89 -0
  97. package/dist/holmes/spec/legacy-format.js +87 -0
  98. package/dist/holmes/spec/spec-digest.js +71 -0
  99. package/dist/holmes/spec/spec-parser.js +106 -0
  100. package/dist/holmes/spec/spec-store.conformance.js +118 -0
  101. package/dist/holmes/spec/spec-store.js +331 -0
  102. package/dist/holmes/spec/spec-types.js +177 -0
  103. package/dist/holmes/spec/validator.js +280 -0
  104. package/package.json +76 -0
  105. package/playbooks/adopt/PLAYBOOK.md +125 -0
  106. package/playbooks/author-slice/PLAYBOOK.md +119 -0
  107. package/playbooks/promote-slice/PLAYBOOK.md +134 -0
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.readReviewNeeded = readReviewNeeded;
37
+ exports.anchoredForReview = anchoredForReview;
38
+ const path = __importStar(require("node:path"));
39
+ /**
40
+ * Read the outstanding `review-needed` signals off the provenance chain. P4 does not auto-clear, so
41
+ * every recorded signal is currently "outstanding" — the surface lists them so a reviewer knows what
42
+ * moved and which files to examine. A missing/unreadable chain → [] (nothing to route), never a throw.
43
+ */
44
+ function readReviewNeeded(ledgerFile) {
45
+ // @implements A-SPEC-148
46
+ // Reads EVERY replica chain. Bound to the legacy filename this returned nothing once writes moved
47
+ // to the per-replica chain — a routing signal that silently stops arriving is worse than one that
48
+ // never existed, because the absence looks like "no review needed".
49
+ let events;
50
+ try {
51
+ const { FileLedgerStore } = require('../governance/ledger-store');
52
+ events = new FileLedgerStore(path.dirname(ledgerFile)).loadAll();
53
+ }
54
+ catch {
55
+ return [];
56
+ }
57
+ const out = [];
58
+ for (const evt of events) {
59
+ if (evt.kind === 'review-needed' && Array.isArray(evt.inputs) && evt.inputs.length >= 3) {
60
+ const [spec, from, to, ...files] = evt.inputs;
61
+ out.push({ spec, from, to, files });
62
+ }
63
+ }
64
+ return out;
65
+ }
66
+ /**
67
+ * The deterministic set of source files a targeted adversarial review must re-examine when a spec's
68
+ * approved content MOVES (P4). This is a ROUTING computation, not a verdict: it names WHERE to look,
69
+ * never whether the code is right — that judgment stays with the review layer / a human, which is the
70
+ * whole point of P4 (the decision layer checks form/existence/execution, never meaning).
71
+ *
72
+ * - An A-SPEC's targets are the source files whose scanned `@implements` names it (its direct anchors).
73
+ * - A REQ's or H-SPEC's targets are the union of its APPROVED direct A-SPEC children's anchors (one
74
+ * hop): a moved parent implicates the code under the approved slices beneath it.
75
+ *
76
+ * Pure, deduped, path-sorted — same (spec, anchor graph) → same set.
77
+ */
78
+ function anchoredForReview(specId, scanned, specs) {
79
+ const self = specs.find((s) => s.id === specId);
80
+ const collectDirect = (aspecId) => scanned.filter((f) => f.implementsSpecs.includes(aspecId)).map((f) => f.sourcePath);
81
+ let files;
82
+ if (self && (self.type === 'REQ' || self.type === 'H-SPEC')) {
83
+ // one hop: approved direct A-SPEC children
84
+ const children = specs.filter((s) => s.type === 'A-SPEC' && s.status === 'approved' && s.dependsOn.includes(specId));
85
+ files = children.flatMap((c) => collectDirect(c.id));
86
+ }
87
+ else {
88
+ // A-SPEC (or an unknown id): its own direct anchors
89
+ files = collectDirect(specId);
90
+ }
91
+ return [...new Set(files)].sort();
92
+ }
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.computeReviewScope = computeReviewScope;
4
+ const rtm_builder_1 = require("../rtm/rtm-builder");
5
+ const ACCEPTANCE_SECTION_BY_TYPE = {
6
+ 'A-SPEC': 'Done When',
7
+ 'H-SPEC': 'Acceptance Criteria',
8
+ REQ: 'Success Criteria',
9
+ };
10
+ function stripSpecPrefix(specNodeId) {
11
+ return specNodeId.startsWith('SPEC:') ? specNodeId.slice('SPEC:'.length) : specNodeId;
12
+ }
13
+ // @implements A-SPEC-102.1
14
+ function computeReviewScope(graph, specs, changedSymbols) {
15
+ const specById = new Map();
16
+ for (const s of specs) {
17
+ specById.set(s.id, s);
18
+ }
19
+ const dedupedChangedSymbols = [...new Set(changedSymbols)].sort();
20
+ const impactedSpecs = [...new Set((0, rtm_builder_1.impactedBy)(graph, dedupedChangedSymbols))].sort();
21
+ const acceptanceCriteria = [];
22
+ for (const specNodeId of impactedSpecs) {
23
+ const specId = stripSpecPrefix(specNodeId);
24
+ const spec = specById.get(specId);
25
+ if (!spec)
26
+ continue;
27
+ const sectionName = ACCEPTANCE_SECTION_BY_TYPE[spec.type];
28
+ if (!sectionName)
29
+ continue;
30
+ const criteria = spec.sections[sectionName];
31
+ if (!criteria)
32
+ continue;
33
+ acceptanceCriteria.push({ specId, criteria });
34
+ }
35
+ acceptanceCriteria.sort((a, b) => (a.specId < b.specId ? -1 : a.specId > b.specId ? 1 : 0));
36
+ const unrequestedSymbols = dedupedChangedSymbols
37
+ .filter((qn) => !(0, rtm_builder_1.impactedBy)(graph, [qn]).some((id) => id.startsWith('SPEC:')))
38
+ .sort();
39
+ const coverageGaps = [];
40
+ for (const specNodeId of impactedSpecs) {
41
+ if (!specNodeId.startsWith('SPEC:A-SPEC-'))
42
+ continue;
43
+ const aSpecId = stripSpecPrefix(specNodeId);
44
+ const hasTSpecChild = specs.some((s) => s.type === 'T-SPEC' && s.dependsOn.includes(aSpecId));
45
+ if (!hasTSpecChild) {
46
+ coverageGaps.push(aSpecId);
47
+ }
48
+ }
49
+ coverageGaps.sort();
50
+ return {
51
+ changedSymbols: dedupedChangedSymbols,
52
+ impactedSpecs,
53
+ acceptanceCriteria,
54
+ unrequestedSymbols,
55
+ coverageGaps,
56
+ };
57
+ }
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.EVIDENCE_FILE = void 0;
37
+ exports.computeExecutedByAspec = computeExecutedByAspec;
38
+ exports.isFresh = isFresh;
39
+ exports.writeTestEvidence = writeTestEvidence;
40
+ exports.readTestEvidence = readTestEvidence;
41
+ // @implements A-SPEC-102.1
42
+ const fs = __importStar(require("node:fs"));
43
+ const path = __importStar(require("node:path"));
44
+ /** Map per-test-file executed counts onto the A-SPECs those files @implement (pure). */
45
+ function computeExecutedByAspec(executedByFile, testAnchors) {
46
+ const out = {};
47
+ for (const [file, n] of Object.entries(executedByFile)) {
48
+ for (const id of testAnchors[file] ?? [])
49
+ out[id] = (out[id] ?? 0) + n;
50
+ }
51
+ return out;
52
+ }
53
+ /** Evidence is usable only for the exact commit it was produced at (pure). */
54
+ function isFresh(ev, currentHead) {
55
+ return !!ev && !!ev.head && ev.head === currentHead;
56
+ }
57
+ exports.EVIDENCE_FILE = path.join('.ax', 'ledger', 'test-evidence.json');
58
+ function writeTestEvidence(root, ev) {
59
+ try {
60
+ const file = path.join(root, exports.EVIDENCE_FILE);
61
+ fs.mkdirSync(path.dirname(file), { recursive: true });
62
+ fs.writeFileSync(file, JSON.stringify(ev, null, 2), 'utf8');
63
+ return true;
64
+ }
65
+ catch {
66
+ return false;
67
+ } // evidence recording must never break a run
68
+ }
69
+ function readTestEvidence(root) {
70
+ try {
71
+ const ev = JSON.parse(fs.readFileSync(path.join(root, exports.EVIDENCE_FILE), 'utf8'));
72
+ return ev && typeof ev.head === 'string' && ev.executedByAspec && typeof ev.executedByAspec === 'object' ? ev : undefined;
73
+ }
74
+ catch {
75
+ return undefined;
76
+ }
77
+ }