@deftai/directive-core 0.87.0 → 0.89.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 (193) hide show
  1. package/dist/authz/actions.d.ts +55 -0
  2. package/dist/authz/actions.js +125 -0
  3. package/dist/authz/classify.d.ts +23 -0
  4. package/dist/authz/classify.js +217 -0
  5. package/dist/authz/closed-verb.d.ts +42 -0
  6. package/dist/authz/closed-verb.js +279 -0
  7. package/dist/authz/evaluate.d.ts +41 -0
  8. package/dist/authz/evaluate.js +298 -0
  9. package/dist/authz/index.d.ts +15 -0
  10. package/dist/authz/index.js +15 -0
  11. package/dist/authz/origin.d.ts +28 -0
  12. package/dist/authz/origin.js +64 -0
  13. package/dist/authz/paths.d.ts +6 -0
  14. package/dist/authz/paths.js +19 -0
  15. package/dist/authz/store.d.ts +40 -0
  16. package/dist/authz/store.js +317 -0
  17. package/dist/authz/templates.d.ts +139 -0
  18. package/dist/authz/templates.js +241 -0
  19. package/dist/authz/types.d.ts +111 -0
  20. package/dist/authz/types.js +41 -0
  21. package/dist/authz/verb-classification.d.ts +44 -0
  22. package/dist/authz/verb-classification.js +237 -0
  23. package/dist/branch/evaluate.js +6 -1
  24. package/dist/cache/fetch.js +10 -5
  25. package/dist/cache/io.d.ts +9 -2
  26. package/dist/cache/io.js +30 -10
  27. package/dist/cache/scanner.d.ts +11 -1
  28. package/dist/cache/scanner.js +29 -4
  29. package/dist/cache/task-cache/store.js +11 -7
  30. package/dist/capacity/backfill.js +10 -4
  31. package/dist/category-b-namespace/index.js +10 -4
  32. package/dist/check/gate-lists.js +1 -0
  33. package/dist/codebase/default-extractor.js +3 -0
  34. package/dist/codebase/map.js +11 -4
  35. package/dist/content-contracts/skills/helpers.d.ts +10 -0
  36. package/dist/content-contracts/skills/helpers.js +35 -0
  37. package/dist/deposit/copy-tree.d.ts +19 -1
  38. package/dist/deposit/copy-tree.js +134 -5
  39. package/dist/doctor/doctor-state.js +28 -4
  40. package/dist/doctor/main.d.ts +10 -0
  41. package/dist/doctor/main.js +208 -0
  42. package/dist/doctor/types.d.ts +11 -0
  43. package/dist/escalation/actions.d.ts +63 -0
  44. package/dist/escalation/actions.js +137 -0
  45. package/dist/escalation/index.d.ts +8 -0
  46. package/dist/escalation/index.js +8 -0
  47. package/dist/escalation/paths.d.ts +3 -0
  48. package/dist/escalation/paths.js +10 -0
  49. package/dist/escalation/store.d.ts +17 -0
  50. package/dist/escalation/store.js +172 -0
  51. package/dist/escalation/types.d.ts +73 -0
  52. package/dist/escalation/types.js +43 -0
  53. package/dist/eval/crud-telemetry.js +30 -10
  54. package/dist/eval/health.js +22 -7
  55. package/dist/eval/readback.js +11 -10
  56. package/dist/eval/run.js +32 -16
  57. package/dist/events/attribution-enrichment.js +10 -4
  58. package/dist/finish-loop/directive-finish-loop.d.ts +37 -0
  59. package/dist/finish-loop/directive-finish-loop.js +239 -0
  60. package/dist/finish-loop/grant-gate.d.ts +31 -0
  61. package/dist/finish-loop/grant-gate.js +169 -0
  62. package/dist/finish-loop/index.d.ts +11 -0
  63. package/dist/finish-loop/index.js +11 -0
  64. package/dist/finish-loop/main.d.ts +35 -0
  65. package/dist/finish-loop/main.js +365 -0
  66. package/dist/finish-loop/pr-finish-loop.d.ts +34 -0
  67. package/dist/finish-loop/pr-finish-loop.js +217 -0
  68. package/dist/finish-loop/progress.d.ts +17 -0
  69. package/dist/finish-loop/progress.js +45 -0
  70. package/dist/finish-loop/queue.d.ts +16 -0
  71. package/dist/finish-loop/queue.js +65 -0
  72. package/dist/finish-loop/types.d.ts +52 -0
  73. package/dist/finish-loop/types.js +10 -0
  74. package/dist/fs/contained-write.d.ts +101 -0
  75. package/dist/fs/contained-write.js +281 -0
  76. package/dist/fs/projection-containment.d.ts +18 -0
  77. package/dist/fs/projection-containment.js +40 -0
  78. package/dist/hooks/classify/classify.d.ts +10 -0
  79. package/dist/hooks/classify/classify.js +37 -0
  80. package/dist/hooks/classify/index.d.ts +14 -0
  81. package/dist/hooks/classify/index.js +13 -0
  82. package/dist/hooks/classify/paths.d.ts +22 -0
  83. package/dist/hooks/classify/paths.js +72 -0
  84. package/dist/hooks/classify/payload.d.ts +16 -0
  85. package/dist/hooks/classify/payload.js +45 -0
  86. package/dist/hooks/classify/stdin.d.ts +12 -0
  87. package/dist/hooks/classify/stdin.js +63 -0
  88. package/dist/hooks/classify/tool-name.d.ts +18 -0
  89. package/dist/hooks/classify/tool-name.js +85 -0
  90. package/dist/hooks/classify/types.d.ts +41 -0
  91. package/dist/hooks/classify/types.js +7 -0
  92. package/dist/hooks/dispatcher.d.ts +30 -15
  93. package/dist/hooks/dispatcher.js +326 -134
  94. package/dist/hooks/fixtures/cases.d.ts +44 -0
  95. package/dist/hooks/fixtures/cases.js +595 -0
  96. package/dist/hooks/fixtures/index.d.ts +2 -0
  97. package/dist/hooks/fixtures/index.js +2 -0
  98. package/dist/hooks/index.d.ts +2 -0
  99. package/dist/hooks/index.js +2 -0
  100. package/dist/hooks/tools.d.ts +31 -0
  101. package/dist/hooks/tools.js +74 -0
  102. package/dist/index.d.ts +4 -0
  103. package/dist/index.js +5 -0
  104. package/dist/init-deposit/agent-hooks.d.ts +1 -1
  105. package/dist/init-deposit/agent-hooks.js +65 -10
  106. package/dist/init-deposit/gitignore.js +11 -3
  107. package/dist/init-deposit/headless-manifest.js +12 -4
  108. package/dist/init-deposit/hygiene.d.ts +16 -0
  109. package/dist/init-deposit/hygiene.js +26 -0
  110. package/dist/init-deposit/init-dispatch.js +28 -0
  111. package/dist/init-deposit/migrate.d.ts +1 -1
  112. package/dist/init-deposit/migrate.js +13 -3
  113. package/dist/init-deposit/prettierignore.js +12 -5
  114. package/dist/init-deposit/refresh.js +38 -7
  115. package/dist/init-deposit/scaffold.js +42 -29
  116. package/dist/init-deposit/xbrief-projections.js +17 -10
  117. package/dist/intake/candidates-log.js +46 -35
  118. package/dist/intake/github-body-cli.d.ts +6 -0
  119. package/dist/intake/github-body-cli.js +17 -0
  120. package/dist/intake/github-body.d.ts +46 -3
  121. package/dist/intake/github-body.js +191 -20
  122. package/dist/intake/issue-emit.d.ts +1 -0
  123. package/dist/intake/issue-emit.js +41 -23
  124. package/dist/intake/issue-ingest.js +11 -2
  125. package/dist/lifecycle/event-detect.js +12 -4
  126. package/dist/lifecycle/events.js +29 -20
  127. package/dist/lifecycle/lifecycle-hygiene.js +9 -3
  128. package/dist/packs/pack-render.d.ts +33 -0
  129. package/dist/packs/pack-render.js +172 -13
  130. package/dist/packs/quarantine-ext.d.ts +10 -0
  131. package/dist/packs/quarantine-ext.js +26 -2
  132. package/dist/plan-sequence/store.js +11 -4
  133. package/dist/policy/hotfix-criteria.d.ts +79 -0
  134. package/dist/policy/hotfix-criteria.js +197 -0
  135. package/dist/policy/index.d.ts +5 -0
  136. package/dist/policy/index.js +32 -1
  137. package/dist/policy/intent-ceiling.d.ts +79 -0
  138. package/dist/policy/intent-ceiling.js +181 -0
  139. package/dist/policy/no-deft-directive.d.ts +59 -0
  140. package/dist/policy/no-deft-directive.js +110 -0
  141. package/dist/policy/org-force-on-migration.d.ts +52 -0
  142. package/dist/policy/org-force-on-migration.js +269 -27
  143. package/dist/policy/require-human-merge.d.ts +75 -0
  144. package/dist/policy/require-human-merge.js +324 -0
  145. package/dist/policy/resolve.js +17 -6
  146. package/dist/policy/runtime-authority.d.ts +56 -2
  147. package/dist/policy/runtime-authority.js +297 -3
  148. package/dist/policy/write-fence.d.ts +78 -0
  149. package/dist/policy/write-fence.js +164 -0
  150. package/dist/pr-wait-mergeable/cascade.d.ts +10 -0
  151. package/dist/pr-wait-mergeable/cascade.js +28 -0
  152. package/dist/preflight/evaluate.js +10 -0
  153. package/dist/product-signal/consent.js +21 -5
  154. package/dist/product-signal/submit.js +22 -12
  155. package/dist/release/build-dist-runner.js +5 -2
  156. package/dist/release/build-dist.d.ts +19 -1
  157. package/dist/release/build-dist.js +50 -2
  158. package/dist/release/native-steps.js +7 -2
  159. package/dist/release-publish/pipeline.d.ts +13 -0
  160. package/dist/release-publish/pipeline.js +46 -1
  161. package/dist/scope/audit-log.js +19 -24
  162. package/dist/scope/decompose.js +10 -5
  163. package/dist/scope/decomposed-refs.js +18 -3
  164. package/dist/scope/demote.js +9 -2
  165. package/dist/scope/undo.js +9 -2
  166. package/dist/session/release-availability.js +26 -6
  167. package/dist/session/ritual-sentinel.js +19 -12
  168. package/dist/session/session-start-hook.d.ts +3 -0
  169. package/dist/session/session-start-hook.js +15 -0
  170. package/dist/session/session-start.js +37 -0
  171. package/dist/staleness-tickler/state.js +26 -6
  172. package/dist/swarm/launch.js +13 -3
  173. package/dist/swarm/routing.js +9 -3
  174. package/dist/task-surface/index.js +24 -9
  175. package/dist/triage/bootstrap/gitignore.js +53 -10
  176. package/dist/triage/cache-path.js +10 -3
  177. package/dist/triage/welcome/summary.js +11 -4
  178. package/dist/triage/welcome/writers.js +45 -16
  179. package/dist/validate-content/validate-links.js +5 -0
  180. package/dist/value/readback.js +11 -6
  181. package/dist/vbrief-activate/activate.js +12 -4
  182. package/dist/vbrief-build/project-definition-io.js +14 -6
  183. package/dist/verify-source/contained-writes.d.ts +59 -0
  184. package/dist/verify-source/contained-writes.js +272 -0
  185. package/dist/verify-source/cursor-tier1.js +7 -2
  186. package/dist/verify-source/index.d.ts +1 -0
  187. package/dist/verify-source/index.js +1 -0
  188. package/dist/verify-source/openclaw-tier1.js +19 -1
  189. package/dist/verify-source/verify-stubs.js +3 -0
  190. package/dist/xbrief-migrate/migrate-project.js +26 -12
  191. package/dist/xbrief-migrate/transforms.d.ts +4 -2
  192. package/dist/xbrief-migrate/transforms.js +37 -14
  193. package/package.json +16 -3
@@ -0,0 +1,595 @@
1
+ /**
2
+ * Shared host × OS × tool fixture corpus (#2950 Phase A skeleton, Phase B matrix expansion).
3
+ *
4
+ * Cases are pure data: raw stdin or structured payload → expected classification.
5
+ * Core tests and CLI hook-dispatch tests import this module (shared corpus collapse).
6
+ */
7
+ const freeFormAddPosix = [
8
+ "*** Begin Patch",
9
+ "*** Add File: xbrief/proposed/_probe-applypatch-only.txt",
10
+ "+probe",
11
+ "*** End Patch",
12
+ ].join("\n");
13
+ const freeFormUpdateWin32 = [
14
+ "*** Begin Patch",
15
+ "*** Update File: src\\example.ts",
16
+ "@@",
17
+ "-old",
18
+ "+new",
19
+ "*** End Patch",
20
+ ].join("\n");
21
+ const freeFormUpdatePosix = [
22
+ "*** Begin Patch",
23
+ "*** Update File: src/example.ts",
24
+ "@@",
25
+ "-old",
26
+ "+new",
27
+ "*** End Patch",
28
+ ].join("\n");
29
+ const freeFormAddWin32 = [
30
+ "*** Begin Patch",
31
+ "*** Add File: xbrief\\proposed\\_probe-win32.txt",
32
+ "+probe",
33
+ "*** End Patch",
34
+ ].join("\n");
35
+ /**
36
+ * Cursor × {win32, posix} × {Write, ApplyPatch, Task, StrReplace}
37
+ * plus recent regression classes (BOM, free-form, missing tool name, outside-root).
38
+ * Phase B expands Write/ApplyPatch depth and shares this corpus with CLI tests.
39
+ */
40
+ export const HOOK_FIXTURE_CASES = [
41
+ // --- Cursor × posix × Write ---
42
+ {
43
+ id: "cursor-posix-write-structured",
44
+ host: "cursor",
45
+ os: "posix",
46
+ tool: "Write",
47
+ regression: ["#2669", "#2950"],
48
+ payload: {
49
+ tool_name: "Write",
50
+ tool_input: { contents: "hello", path: "src/a.ts" },
51
+ cwd: "/project",
52
+ },
53
+ expected: {
54
+ toolName: "Write",
55
+ writeIntent: "direct-write",
56
+ writeTargetPath: "src/a.ts",
57
+ },
58
+ },
59
+ {
60
+ id: "cursor-posix-write-infer-name",
61
+ host: "cursor",
62
+ os: "posix",
63
+ tool: "Write",
64
+ regression: ["#2628", "#2669"],
65
+ payload: {
66
+ arguments: { contents: "x", path: "a.py" },
67
+ },
68
+ expected: {
69
+ toolName: "Write",
70
+ writeIntent: "direct-write",
71
+ writeTargetPath: "a.py",
72
+ },
73
+ notes: "Cursor omits tool_name; infer from contents+path",
74
+ },
75
+ {
76
+ id: "cursor-posix-write-outside-root",
77
+ host: "cursor",
78
+ os: "posix",
79
+ tool: "Write",
80
+ regression: ["#2885"],
81
+ payload: {
82
+ tool_name: "Write",
83
+ tool_input: {
84
+ file_path: "/home/user/.claude/projects/slug/memory/note.md",
85
+ },
86
+ cwd: "/project",
87
+ },
88
+ expected: {
89
+ toolName: "Write",
90
+ writeIntent: "direct-write",
91
+ writeTargetPath: "/home/user/.claude/projects/slug/memory/note.md",
92
+ },
93
+ },
94
+ {
95
+ id: "cursor-posix-write-filePath-camel",
96
+ host: "cursor",
97
+ os: "posix",
98
+ tool: "Write",
99
+ regression: ["#2625", "#2950"],
100
+ payload: {
101
+ tool_name: "Write",
102
+ tool_input: { content: "body", filePath: "docs/note.md" },
103
+ cwd: "/project",
104
+ },
105
+ expected: {
106
+ toolName: "Write",
107
+ writeIntent: "direct-write",
108
+ writeTargetPath: "docs/note.md",
109
+ },
110
+ notes: "camelCase filePath spelling on tool_input",
111
+ },
112
+ {
113
+ id: "cursor-posix-write-text-field-infer",
114
+ host: "cursor",
115
+ os: "posix",
116
+ tool: "Write",
117
+ regression: ["#2628", "#2669"],
118
+ payload: {
119
+ tool_input: { text: "hello", path: "scratch/out.txt" },
120
+ },
121
+ expected: {
122
+ toolName: "Write",
123
+ writeIntent: "direct-write",
124
+ writeTargetPath: "scratch/out.txt",
125
+ },
126
+ notes: "Cursor omits tool_name; infer Write from text+path",
127
+ },
128
+ {
129
+ id: "cursor-posix-write-edit-alias",
130
+ host: "cursor",
131
+ os: "posix",
132
+ tool: "Write",
133
+ regression: ["#2669", "#2950"],
134
+ payload: {
135
+ tool_name: "Edit",
136
+ tool_input: { path: "src/legacy.ts", contents: "x" },
137
+ cwd: "/project",
138
+ },
139
+ expected: {
140
+ toolName: "Edit",
141
+ writeIntent: "direct-write",
142
+ writeTargetPath: "src/legacy.ts",
143
+ },
144
+ notes: "Edit is a direct-write host spelling (Cursor maps Claude Edit → Write)",
145
+ },
146
+ // --- Cursor × win32 × Write ---
147
+ {
148
+ id: "cursor-win32-write-structured",
149
+ host: "cursor",
150
+ os: "win32",
151
+ tool: "Write",
152
+ regression: ["#2787", "#2950"],
153
+ payload: {
154
+ tool_name: "Write",
155
+ tool_input: {
156
+ contents: "x",
157
+ path: "C:\\Repos\\deft\\statusreport\\src\\a.ts",
158
+ },
159
+ workspace_roots: ["C:\\Repos\\deft\\statusreport"],
160
+ },
161
+ expected: {
162
+ toolName: "Write",
163
+ writeIntent: "direct-write",
164
+ writeTargetPath: "C:\\Repos\\deft\\statusreport\\src\\a.ts",
165
+ },
166
+ },
167
+ {
168
+ id: "cursor-win32-write-statusreport-shape",
169
+ host: "cursor",
170
+ os: "win32",
171
+ tool: "Write",
172
+ regression: ["#2787"],
173
+ payload: {
174
+ tool_name: "Write",
175
+ tool_input: { content: "x", file_path: "notes.md" },
176
+ workspace_roots: ["C:\\Repos\\deft\\statusreport"],
177
+ cwd: "C:\\Repos\\deft\\statusreport",
178
+ },
179
+ expected: {
180
+ toolName: "Write",
181
+ writeIntent: "direct-write",
182
+ writeTargetPath: "notes.md",
183
+ },
184
+ notes: "Ritual-root normalization is dispatcher-owned; classify keeps raw path",
185
+ },
186
+ {
187
+ id: "cursor-win32-write-bom-raw",
188
+ host: "cursor",
189
+ os: "win32",
190
+ tool: "Write",
191
+ regression: ["#2734"],
192
+ raw: `\uFEFF${JSON.stringify({
193
+ tool_name: "Write",
194
+ tool_input: { content: "x", file_path: "a.txt" },
195
+ workspace_roots: ["C:\\\\Repos\\\\deft"],
196
+ })}`,
197
+ expected: {
198
+ toolName: "Write",
199
+ writeIntent: "direct-write",
200
+ writeTargetPath: "a.txt",
201
+ stdinEmpty: false,
202
+ parseFailed: false,
203
+ },
204
+ },
205
+ {
206
+ id: "cursor-win32-write-mixed-separators",
207
+ host: "cursor",
208
+ os: "win32",
209
+ tool: "Write",
210
+ regression: ["#2787", "#2950"],
211
+ payload: {
212
+ tool_name: "Write",
213
+ tool_input: {
214
+ content: "x",
215
+ file_path: "C:/Repos/deft/statusreport/src/b.ts",
216
+ },
217
+ workspace_roots: ["C:\\Repos\\deft\\statusreport"],
218
+ },
219
+ expected: {
220
+ toolName: "Write",
221
+ writeIntent: "direct-write",
222
+ writeTargetPath: "C:/Repos/deft/statusreport/src/b.ts",
223
+ },
224
+ notes: "Forward-slash Windows path kept raw at classify layer",
225
+ },
226
+ {
227
+ id: "cursor-win32-write-infer-content",
228
+ host: "cursor",
229
+ os: "win32",
230
+ tool: "Write",
231
+ regression: ["#2628", "#2669"],
232
+ payload: {
233
+ tool_input: {
234
+ content: "x",
235
+ file_path: "C:\\Repos\\proj\\notes.md",
236
+ },
237
+ workspace_roots: ["C:\\Repos\\proj"],
238
+ },
239
+ expected: {
240
+ toolName: "Write",
241
+ writeIntent: "direct-write",
242
+ writeTargetPath: "C:\\Repos\\proj\\notes.md",
243
+ },
244
+ notes: "Cursor omits tool_name; infer Write from content+file_path",
245
+ },
246
+ {
247
+ id: "cursor-win32-write-doubled-drive-raw",
248
+ host: "cursor",
249
+ os: "win32",
250
+ tool: "Write",
251
+ regression: ["#2787", "#2764"],
252
+ payload: {
253
+ tool_name: "Write",
254
+ tool_input: {
255
+ content: "x",
256
+ file_path: "C:\\c:\\Repos\\deft\\statusreport\\src\\a.ts",
257
+ },
258
+ workspace_roots: ["C:\\Repos\\deft\\statusreport"],
259
+ },
260
+ expected: {
261
+ toolName: "Write",
262
+ writeIntent: "direct-write",
263
+ writeTargetPath: "C:\\c:\\Repos\\deft\\statusreport\\src\\a.ts",
264
+ },
265
+ notes: "Doubled-drive prefix stays raw here; normalizeHookProjectRoot is dispatcher-owned",
266
+ },
267
+ // --- Cursor × posix × ApplyPatch ---
268
+ {
269
+ id: "cursor-posix-applypatch-structured",
270
+ host: "cursor",
271
+ os: "posix",
272
+ tool: "ApplyPatch",
273
+ regression: ["#2738", "#2790"],
274
+ payload: {
275
+ tool_name: "ApplyPatch",
276
+ tool_input: {
277
+ path: "xbrief/proposed/a.xbrief.json",
278
+ patch: "*** Begin Patch\n*** Add File: x\n+probe\n*** End Patch",
279
+ },
280
+ },
281
+ expected: {
282
+ toolName: "ApplyPatch",
283
+ writeIntent: "direct-write",
284
+ writeTargetPath: "xbrief/proposed/a.xbrief.json",
285
+ },
286
+ },
287
+ {
288
+ id: "cursor-posix-applypatch-freeform",
289
+ host: "cursor",
290
+ os: "posix",
291
+ tool: "ApplyPatch",
292
+ regression: ["#2738"],
293
+ raw: freeFormAddPosix,
294
+ expected: {
295
+ toolName: "ApplyPatch",
296
+ writeIntent: "direct-write",
297
+ writeTargetPath: "xbrief/proposed/_probe-applypatch-only.txt",
298
+ parseFailed: false,
299
+ },
300
+ },
301
+ {
302
+ id: "cursor-posix-applypatch-infer-from-patch-field",
303
+ host: "cursor",
304
+ os: "posix",
305
+ tool: "ApplyPatch",
306
+ regression: ["#2669"],
307
+ payload: {
308
+ tool_input: { path: "src/a.ts", patch: "diff" },
309
+ },
310
+ expected: {
311
+ toolName: "ApplyPatch",
312
+ writeIntent: "direct-write",
313
+ writeTargetPath: "src/a.ts",
314
+ },
315
+ },
316
+ {
317
+ id: "cursor-posix-applypatch-freeform-update",
318
+ host: "cursor",
319
+ os: "posix",
320
+ tool: "ApplyPatch",
321
+ regression: ["#2738", "#2950"],
322
+ raw: freeFormUpdatePosix,
323
+ expected: {
324
+ toolName: "ApplyPatch",
325
+ writeIntent: "direct-write",
326
+ writeTargetPath: "src/example.ts",
327
+ parseFailed: false,
328
+ },
329
+ },
330
+ {
331
+ id: "cursor-posix-applypatch-unified-diff-key",
332
+ host: "cursor",
333
+ os: "posix",
334
+ tool: "ApplyPatch",
335
+ regression: ["#2669", "#2950"],
336
+ payload: {
337
+ tool_input: {
338
+ path: "lib/b.ts",
339
+ unified_diff: "*** Begin Patch\n*** Update File: lib/b.ts\n*** End Patch",
340
+ },
341
+ },
342
+ expected: {
343
+ toolName: "ApplyPatch",
344
+ writeIntent: "direct-write",
345
+ writeTargetPath: "lib/b.ts",
346
+ },
347
+ notes: "Cursor omits tool_name; infer ApplyPatch from unified_diff",
348
+ },
349
+ {
350
+ id: "cursor-posix-applypatch-delete-only-fail-closed",
351
+ host: "cursor",
352
+ os: "posix",
353
+ tool: "ApplyPatch",
354
+ regression: ["#2738"],
355
+ raw: ["*** Begin Patch", "*** Delete File: src/a.ts", "*** End Patch"].join("\n"),
356
+ expected: {
357
+ toolName: null,
358
+ writeIntent: "unknown",
359
+ writeTargetPath: null,
360
+ parseFailed: true,
361
+ },
362
+ notes: "Delete-only free-form is fail-closed at parse (no synthesize)",
363
+ },
364
+ // --- Cursor × win32 × ApplyPatch ---
365
+ {
366
+ id: "cursor-win32-applypatch-structured",
367
+ host: "cursor",
368
+ os: "win32",
369
+ tool: "ApplyPatch",
370
+ regression: ["#2738", "#2790"],
371
+ payload: {
372
+ tool_name: "ApplyPatch",
373
+ tool_input: {
374
+ path: "C:\\Repos\\proj\\src\\a.ts",
375
+ patch: "*** Begin Patch",
376
+ },
377
+ workspace_roots: ["C:\\Repos\\proj"],
378
+ },
379
+ expected: {
380
+ toolName: "ApplyPatch",
381
+ writeIntent: "direct-write",
382
+ writeTargetPath: "C:\\Repos\\proj\\src\\a.ts",
383
+ },
384
+ },
385
+ {
386
+ id: "cursor-win32-applypatch-freeform",
387
+ host: "cursor",
388
+ os: "win32",
389
+ tool: "ApplyPatch",
390
+ regression: ["#2738"],
391
+ raw: freeFormUpdateWin32,
392
+ expected: {
393
+ toolName: "ApplyPatch",
394
+ writeIntent: "direct-write",
395
+ writeTargetPath: "src\\example.ts",
396
+ parseFailed: false,
397
+ },
398
+ },
399
+ {
400
+ id: "cursor-win32-applypatch-freeform-add",
401
+ host: "cursor",
402
+ os: "win32",
403
+ tool: "ApplyPatch",
404
+ regression: ["#2738", "#2950"],
405
+ raw: freeFormAddWin32,
406
+ expected: {
407
+ toolName: "ApplyPatch",
408
+ writeIntent: "direct-write",
409
+ writeTargetPath: "xbrief\\proposed\\_probe-win32.txt",
410
+ parseFailed: false,
411
+ },
412
+ },
413
+ {
414
+ id: "cursor-win32-applypatch-infer-from-patch",
415
+ host: "cursor",
416
+ os: "win32",
417
+ tool: "ApplyPatch",
418
+ regression: ["#2669", "#2950"],
419
+ payload: {
420
+ tool_input: {
421
+ path: "C:\\Repos\\proj\\src\\patch-me.ts",
422
+ patch: "diff",
423
+ },
424
+ workspace_roots: ["C:\\Repos\\proj"],
425
+ },
426
+ expected: {
427
+ toolName: "ApplyPatch",
428
+ writeIntent: "direct-write",
429
+ writeTargetPath: "C:\\Repos\\proj\\src\\patch-me.ts",
430
+ },
431
+ },
432
+ {
433
+ id: "cursor-win32-applypatch-multifile-fail-closed",
434
+ host: "cursor",
435
+ os: "win32",
436
+ tool: "ApplyPatch",
437
+ regression: ["#2738"],
438
+ raw: [
439
+ "*** Begin Patch",
440
+ "*** Add File: a.txt",
441
+ "+a",
442
+ "*** Add File: b.txt",
443
+ "+b",
444
+ "*** End Patch",
445
+ ].join("\n"),
446
+ expected: {
447
+ toolName: null,
448
+ writeIntent: "unknown",
449
+ writeTargetPath: null,
450
+ parseFailed: true,
451
+ },
452
+ },
453
+ // --- Cursor × posix × Task ---
454
+ {
455
+ id: "cursor-posix-task-spawn",
456
+ host: "cursor",
457
+ os: "posix",
458
+ tool: "Task",
459
+ regression: ["#1185", "#2864", "#2950"],
460
+ payload: {
461
+ tool_name: "Task",
462
+ tool_input: { description: "explore", prompt: "scan hooks" },
463
+ cwd: "/project",
464
+ },
465
+ expected: {
466
+ toolName: "Task",
467
+ writeIntent: "spawn",
468
+ writeTargetPath: null,
469
+ },
470
+ },
471
+ // --- Cursor × win32 × Task ---
472
+ {
473
+ id: "cursor-win32-task-spawn",
474
+ host: "cursor",
475
+ os: "win32",
476
+ tool: "Task",
477
+ regression: ["#1185", "#2864", "#2950"],
478
+ payload: {
479
+ tool_name: "Task",
480
+ tool_input: { description: "implement", prompt: "fix write path" },
481
+ workspace_roots: ["C:\\Repos\\deft\\statusreport"],
482
+ },
483
+ expected: {
484
+ toolName: "Task",
485
+ writeIntent: "spawn",
486
+ writeTargetPath: null,
487
+ },
488
+ },
489
+ // --- Cursor × posix/win32 × StrReplace (direct-write family) ---
490
+ {
491
+ id: "cursor-posix-strreplace-infer",
492
+ host: "cursor",
493
+ os: "posix",
494
+ tool: "StrReplace",
495
+ regression: ["#2628", "#2669", "#2950"],
496
+ payload: {
497
+ tool_input: {
498
+ path: "src/edit-me.ts",
499
+ old_string: "a",
500
+ new_string: "b",
501
+ },
502
+ },
503
+ expected: {
504
+ toolName: "StrReplace",
505
+ writeIntent: "direct-write",
506
+ writeTargetPath: "src/edit-me.ts",
507
+ },
508
+ },
509
+ {
510
+ id: "cursor-win32-strreplace-structured",
511
+ host: "cursor",
512
+ os: "win32",
513
+ tool: "StrReplace",
514
+ regression: ["#2628", "#2950"],
515
+ payload: {
516
+ tool_name: "StrReplace",
517
+ tool_input: {
518
+ file_path: "C:\\Repos\\proj\\src\\edit-me.ts",
519
+ old_string: "a",
520
+ new_string: "b",
521
+ },
522
+ workspace_roots: ["C:\\Repos\\proj"],
523
+ },
524
+ expected: {
525
+ toolName: "StrReplace",
526
+ writeIntent: "direct-write",
527
+ writeTargetPath: "C:\\Repos\\proj\\src\\edit-me.ts",
528
+ },
529
+ },
530
+ // --- Regression: empty / missing tool name ---
531
+ {
532
+ id: "cursor-posix-stdin-empty",
533
+ host: "cursor",
534
+ os: "posix",
535
+ tool: "other",
536
+ regression: ["#2864"],
537
+ raw: "",
538
+ expected: {
539
+ toolName: null,
540
+ writeIntent: "unknown",
541
+ writeTargetPath: null,
542
+ stdinEmpty: true,
543
+ },
544
+ },
545
+ {
546
+ id: "cursor-posix-missing-tool-name-keys",
547
+ host: "cursor",
548
+ os: "posix",
549
+ tool: "other",
550
+ regression: ["#2669", "#2864"],
551
+ payload: { host_version: "1.2.3" },
552
+ expected: {
553
+ toolName: null,
554
+ writeIntent: "unknown",
555
+ writeTargetPath: null,
556
+ },
557
+ },
558
+ {
559
+ id: "cursor-posix-applypatch-multifile-fail-closed",
560
+ host: "cursor",
561
+ os: "posix",
562
+ tool: "ApplyPatch",
563
+ regression: ["#2738"],
564
+ raw: [
565
+ "*** Begin Patch",
566
+ "*** Add File: a.txt",
567
+ "+a",
568
+ "*** Add File: b.txt",
569
+ "+b",
570
+ "*** End Patch",
571
+ ].join("\n"),
572
+ expected: {
573
+ toolName: null,
574
+ writeIntent: "unknown",
575
+ writeTargetPath: null,
576
+ parseFailed: true,
577
+ },
578
+ },
579
+ ];
580
+ export function fixtureCasesFor(filter) {
581
+ return HOOK_FIXTURE_CASES.filter((c) => {
582
+ if (filter.host !== undefined && c.host !== filter.host)
583
+ return false;
584
+ if (filter.os !== undefined && c.os !== filter.os)
585
+ return false;
586
+ if (filter.tool !== undefined && c.tool !== filter.tool)
587
+ return false;
588
+ return true;
589
+ });
590
+ }
591
+ /** Look up a single case by stable id (CLI/core shared helpers). */
592
+ export function fixtureCaseById(id) {
593
+ return HOOK_FIXTURE_CASES.find((c) => c.id === id);
594
+ }
595
+ //# sourceMappingURL=cases.js.map
@@ -0,0 +1,2 @@
1
+ export { type FixtureOs, type FixtureToolFamily, fixtureCaseById, fixtureCasesFor, HOOK_FIXTURE_CASES, type HookFixtureCase, } from "./cases.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,2 @@
1
+ export { fixtureCaseById, fixtureCasesFor, HOOK_FIXTURE_CASES, } from "./cases.js";
2
+ //# sourceMappingURL=index.js.map
@@ -1,4 +1,6 @@
1
+ export * from "./classify/index.js";
1
2
  export * from "./cursor-hooks.js";
2
3
  export * from "./dispatcher.js";
4
+ export * from "./fixtures/index.js";
3
5
  export * from "./scope.js";
4
6
  //# sourceMappingURL=index.d.ts.map
@@ -1,4 +1,6 @@
1
+ export * from "./classify/index.js";
1
2
  export * from "./cursor-hooks.js";
2
3
  export * from "./dispatcher.js";
4
+ export * from "./fixtures/index.js";
3
5
  export * from "./scope.js";
4
6
  //# sourceMappingURL=index.js.map
@@ -2,10 +2,41 @@
2
2
  export declare const DIRECT_WRITE_TOOL_NAMES: readonly ["Edit", "Write", "WriteFile", "CreateFile", "MultiEdit", "NotebookEdit", "StrReplace", "SearchReplace", "Delete", "DeleteFile", "ApplyPatch", "apply_patch"];
3
3
  /** PreToolUse spawn / sub-agent dispatch tools (#1185 / #2437). */
4
4
  export declare const SPAWN_TOOL_NAMES: readonly ["Task", "SubagentStart", "spawn_subagent", "start_agent", "CreateAgent"];
5
+ /**
6
+ * Host spellings for Shell/Bash execution tools (#2711).
7
+ * Used for runtimeAuthority scopes.push / scopes.merge classification.
8
+ */
9
+ export declare const SHELL_TOOL_NAMES: readonly ["Shell", "Bash", "BashTool", "shell", "bash"];
5
10
  /** Env override forcing hook-level read-only write denial (#1185). */
6
11
  export declare const READ_ONLY_HOOK_ENV = "DEFT_HOOK_READ_ONLY";
7
12
  export declare function isDirectWriteTool(toolName: string): boolean;
8
13
  export declare function isSpawnTool(toolName: string): boolean;
14
+ /** True for host Shell/Bash-class tools that carry a command string (#2711). */
15
+ export declare function isShellTool(toolName: string): boolean;
16
+ /**
17
+ * Best-effort MCP tool detection for runtimeAuthority push/merge scopes (#2711).
18
+ * Host spellings vary (`mcp__*`, `server__tool`, bare MCP-looking names).
19
+ * Unclassifiable MCP tools fail open at the operation classifier.
20
+ *
21
+ * Bare push/merge names (e.g. `merge_pull_request`) are NOT detected here —
22
+ * they are classified by `classifyMcpTool` and routed from `decideHook` so
23
+ * tools.ts stays free of policy imports (#2711 Greptile conf holdout).
24
+ */
25
+ export declare function isMcpTool(toolName: string): boolean;
26
+ /**
27
+ * Bare tool names that hosts may emit without mcp__/server__ prefixes and that
28
+ * `classifyMcpTool` treats as push or merge (#2711).
29
+ * Keep in sync with classifyMcpTool name patterns (narrow list for PreToolUse matchers).
30
+ */
31
+ export declare const MCP_PUSH_MERGE_BARE_NAMES: readonly ["merge_pull_request", "merge-pull-request", "pull_request_merge", "pull-request-merge", "merge_pr", "pr_merge", "pr-merge", "git_push", "git-push", "push_branch", "push-branch"];
9
32
  export declare const DIRECT_WRITE_HOOK_MATCHER: string;
10
33
  export declare const SPAWN_HOOK_MATCHER: string;
34
+ export declare const SHELL_HOOK_MATCHER: string;
35
+ /**
36
+ * PreToolUse matcher for MCP-class push/merge tools (#2711).
37
+ * Regex-friendly for Claude/nested hosts. Prefer broad install match +
38
+ * fail-open classify in the dispatcher over missing a classifiable push/merge
39
+ * tool name (e.g. `server__push_to_remote` via push+remote).
40
+ */
41
+ export declare const MCP_HOOK_MATCHER: string;
11
42
  //# sourceMappingURL=tools.d.ts.map