@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,194 @@
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.TOOL_MAP = void 0;
37
+ exports.adaptPreToolUse = adaptPreToolUse;
38
+ exports.adaptStop = adaptStop;
39
+ // @implements A-SPEC-193
40
+ const fs = __importStar(require("node:fs"));
41
+ const path = __importStar(require("node:path"));
42
+ const node_child_process_1 = require("node:child_process");
43
+ /**
44
+ * 실측한 도구만 등재한다.
45
+ *
46
+ * 이름과 인자 키는 이 기계에 설치된 Antigravity CLI 의 실제 대화 기록에서 뽑았다
47
+ * (run_command{CommandLine,Cwd} 101건, view_file{AbsolutePath} 99건,
48
+ * replace_file_content{TargetFile,ReplacementContent,TargetContent} 46건, grep_search, list_dir).
49
+ * **추측으로 이름을 더하지 않는다** — 읽기로 잘못 등재하면 쓰기가 게이트를 지나가고, 쓰기로
50
+ * 잘못 등재하면 읽기가 막힌다. 등재되지 않은 이름은 그대로 게이트에 넘겨 fail-closed 로 받는다
51
+ * (A-SPEC-163: 읽기 전용이라고 알려지지 않은 도구가 경로를 들고 오면 그것은 쓰기다).
52
+ */
53
+ exports.TOOL_MAP = {
54
+ run_command: { as: 'Bash', commandArg: 'CommandLine' },
55
+ replace_file_content: { as: 'Edit', pathArg: 'TargetFile', contentArg: 'ReplacementContent' },
56
+ view_file: { as: 'Read', pathArg: 'AbsolutePath' },
57
+ grep_search: { as: 'Grep' },
58
+ list_dir: { as: 'Glob' },
59
+ };
60
+ const str = (v) => (typeof v === 'string' ? v : undefined);
61
+ /** 출하된 훅 프로그램의 자리 — 이 파일에서 패키지 뿌리로 올라간다. */
62
+ const shippedHook = (name) => path.resolve(__dirname, '..', '..', '..', '..', 'dist', 'holmes', 'hooks', name);
63
+ const runShippedHook = (hookPath, payload, cwd) => {
64
+ const r = (0, node_child_process_1.spawnSync)(process.execPath, [hookPath], {
65
+ cwd, input: payload, encoding: 'utf8', timeout: 30_000,
66
+ env: { ...process.env },
67
+ });
68
+ const out = String(r.stdout ?? '').trim();
69
+ if (out === '')
70
+ return null;
71
+ try {
72
+ return JSON.parse(out);
73
+ }
74
+ catch {
75
+ return null;
76
+ }
77
+ };
78
+ /**
79
+ * 이 호출이 판정하는 프로젝트.
80
+ *
81
+ * 하네스가 `workspacePaths` 로 말해 주면 그것을 쓴다 — 훅을 부른 쪽이 어느 작업공간인지 아는
82
+ * 유일한 주체다. 말해 주지 않으면 훅 자신이 제 순서(A-SPEC-191 §24: 표지 → 배선된 스펙
83
+ * 디렉터리 → cwd)로 찾도록 cwd 를 그대로 넘긴다 — 여기서 다른 순서를 쓰면 두 하네스가 같은
84
+ * 저장소를 다른 프로젝트로 읽는다.
85
+ */
86
+ function workspaceOf(payload, cwd) {
87
+ const first = Array.isArray(payload.workspacePaths) ? str(payload.workspacePaths[0]) : undefined;
88
+ if (first === undefined || first === '')
89
+ return cwd;
90
+ try {
91
+ return fs.statSync(first).isDirectory() ? first : cwd;
92
+ }
93
+ catch {
94
+ return cwd;
95
+ }
96
+ }
97
+ /** 게이트의 결정 문면에서 사유를 꺼낸다 — 훅은 두 모양 중 하나로 답한다. */
98
+ function decisionOf(out) {
99
+ if (out === null)
100
+ return {};
101
+ const nested = out.hookSpecificOutput;
102
+ if (nested !== undefined && typeof nested === 'object') {
103
+ return {
104
+ decision: str(nested.permissionDecision),
105
+ reason: str(nested.permissionDecisionReason),
106
+ };
107
+ }
108
+ return { decision: str(out.permissionDecision) ?? str(out.decision), reason: str(out.permissionDecisionReason) ?? str(out.reason) };
109
+ }
110
+ /**
111
+ * PreToolUse: Antigravity 의 말 → 게이트 → Antigravity 의 말.
112
+ *
113
+ * 번역할 수 없는 입력은 **닫는 쪽**으로 답한다. 어댑터가 조용히 `allow` 를 돌려주면 게이트가
114
+ * 없는 것과 같고, 그 사실은 아무 데도 나타나지 않는다 — REQ-144 가 같은 방향으로 세운 규율이다.
115
+ */
116
+ function adaptPreToolUse(stdin, cwd = process.cwd(), run = runShippedHook) {
117
+ let payload;
118
+ try {
119
+ payload = JSON.parse(stdin);
120
+ }
121
+ catch {
122
+ return { decision: 'deny', reason: '[Holmes-Kit] 훅 입력을 읽을 수 없습니다(JSON 아님) — 무엇을 판정하는지 알 수 없어 허용하지 않습니다.' };
123
+ }
124
+ const call = payload?.toolCall;
125
+ const name = str(call?.name);
126
+ if (call === null || call === undefined || name === undefined || name === '') {
127
+ return { decision: 'deny', reason: '[Holmes-Kit] 훅 입력에 toolCall.name 이 없습니다 — 무엇을 판정하는지 알 수 없어 허용하지 않습니다.' };
128
+ }
129
+ const args = (call.args ?? {});
130
+ const map = exports.TOOL_MAP[name];
131
+ const toolInput = {};
132
+ if (map?.commandArg !== undefined) {
133
+ const command = str(args[map.commandArg]);
134
+ if (command === undefined) {
135
+ return { decision: 'deny', reason: `[Holmes-Kit] ${name} 의 ${map.commandArg} 를 읽을 수 없습니다 — 판정할 수 없는 호출은 허용하지 않습니다.` };
136
+ }
137
+ toolInput.command = command;
138
+ }
139
+ if (map?.pathArg !== undefined) {
140
+ const p = str(args[map.pathArg]);
141
+ if (p !== undefined)
142
+ toolInput.file_path = p;
143
+ }
144
+ if (map?.contentArg !== undefined) {
145
+ const c = str(args[map.contentArg]);
146
+ if (c !== undefined) {
147
+ toolInput.content = c;
148
+ toolInput.new_string = c;
149
+ }
150
+ }
151
+ // 등재되지 않은 도구: 이름을 그대로 넘기고 인자에서 경로처럼 보이는 것을 실어 준다.
152
+ // 게이트가 "읽기 전용으로 알려지지 않았는데 경로를 들고 왔다 → 쓰기"로 받는다.
153
+ if (map === undefined) {
154
+ for (const key of ['TargetFile', 'AbsolutePath', 'FilePath', 'Path']) {
155
+ const p = str(args[key]);
156
+ if (p !== undefined) {
157
+ toolInput.file_path = p;
158
+ break;
159
+ }
160
+ }
161
+ }
162
+ const root = workspaceOf(payload, cwd);
163
+ const out = decisionOf(run(shippedHook('pre-tool-use.js'), JSON.stringify({
164
+ tool_name: map?.as ?? name,
165
+ tool_input: toolInput,
166
+ cwd: root,
167
+ }), root));
168
+ if (out.decision === undefined) {
169
+ return { decision: 'deny', reason: '[Holmes-Kit] 게이트가 답하지 않았습니다 — 판정 없이 진행하지 않습니다.' };
170
+ }
171
+ return out.decision === 'deny' ? { decision: 'deny', reason: out.reason } : { decision: 'allow' };
172
+ }
173
+ /**
174
+ * Stop: 게이트가 "막아라"라고 하면, 이 하네스에서 막는 말은 `continue` 다.
175
+ *
176
+ * 이름이 반대라서 헷갈리기 쉽다 — Claude Code 의 `block` 은 "정지를 막아라"이고 Antigravity 의
177
+ * `continue` 도 "정지하지 말고 계속하라"이다. 같은 뜻, 다른 낱말이다.
178
+ *
179
+ * 여기서는 실행 실패를 **열어 준다**. Stop 훅은 이미 fail-open 계약이다(턴을 죽이지 않는다).
180
+ */
181
+ function adaptStop(stdin, cwd = process.cwd(), run = runShippedHook) {
182
+ let payload;
183
+ try {
184
+ payload = JSON.parse(stdin);
185
+ }
186
+ catch {
187
+ payload = {};
188
+ }
189
+ const root = workspaceOf(payload, cwd);
190
+ const out = decisionOf(run(shippedHook('stop.js'), JSON.stringify({
191
+ session_id: str(payload.conversationId) ?? 'antigravity',
192
+ }), root));
193
+ return out.decision === 'block' ? { decision: 'continue', reason: out.reason } : {};
194
+ }