@nathapp/nax-agent 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 (398) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/LICENSE +21 -0
  3. package/README.md +49 -0
  4. package/dist/coding-tools/coding-tool-bash.d.ts +46 -0
  5. package/dist/coding-tools/coding-tool-bash.js +44 -0
  6. package/dist/coding-tools/coding-tool-extras.d.ts +35 -0
  7. package/dist/coding-tools/coding-tool-extras.js +56 -0
  8. package/dist/coding-tools/coding-tool-sandbox.d.ts +74 -0
  9. package/dist/coding-tools/coding-tool-sandbox.js +215 -0
  10. package/dist/coding-tools/coding-tool-support.d.ts +132 -0
  11. package/dist/coding-tools/coding-tool-support.js +159 -0
  12. package/dist/coding-tools/universal-coding-tools.d.ts +11 -0
  13. package/dist/coding-tools/universal-coding-tools.js +5 -0
  14. package/dist/command-interceptor/index.d.ts +55 -0
  15. package/dist/command-interceptor/index.js +60 -0
  16. package/dist/command-interceptor/shell.d.ts +36 -0
  17. package/dist/command-interceptor/shell.js +137 -0
  18. package/dist/command-safety/build.d.ts +19 -0
  19. package/dist/command-safety/build.js +47 -0
  20. package/dist/command-safety/guard.d.ts +32 -0
  21. package/dist/command-safety/guard.js +179 -0
  22. package/dist/command-safety/identifiers.d.ts +24 -0
  23. package/dist/command-safety/identifiers.js +20 -0
  24. package/dist/command-safety/index.d.ts +17 -0
  25. package/dist/command-safety/index.js +11 -0
  26. package/dist/command-safety/questions.d.ts +19 -0
  27. package/dist/command-safety/questions.js +60 -0
  28. package/dist/command-safety/row.d.ts +2 -0
  29. package/dist/command-safety/row.js +14 -0
  30. package/dist/command-safety/rule-scorer.d.ts +9 -0
  31. package/dist/command-safety/rule-scorer.js +391 -0
  32. package/dist/command-safety/shadow.d.ts +33 -0
  33. package/dist/command-safety/shadow.js +188 -0
  34. package/dist/command-safety/systemone-client.d.ts +16 -0
  35. package/dist/command-safety/systemone-client.js +92 -0
  36. package/dist/command-safety/tap.d.ts +37 -0
  37. package/dist/command-safety/tap.js +77 -0
  38. package/dist/command-safety/temp-only.d.ts +6 -0
  39. package/dist/command-safety/temp-only.js +215 -0
  40. package/dist/command-safety/tmp-write.d.ts +2 -0
  41. package/dist/command-safety/tmp-write.js +112 -0
  42. package/dist/command-safety/types.d.ts +185 -0
  43. package/dist/command-safety/types.js +21 -0
  44. package/dist/config/bash-approval.d.ts +33 -0
  45. package/dist/config/bash-approval.js +30 -0
  46. package/dist/config/catalog-overrides.d.ts +94 -0
  47. package/dist/config/catalog-overrides.js +7 -0
  48. package/dist/config/native-agent/index.d.ts +8 -0
  49. package/dist/config/native-agent/index.js +8 -0
  50. package/dist/config/schemas-sandbox.d.ts +31 -0
  51. package/dist/config/schemas-sandbox.js +45 -0
  52. package/dist/cost/core/index.d.ts +8 -0
  53. package/dist/cost/core/index.js +7 -0
  54. package/dist/cost/estimate.d.ts +34 -0
  55. package/dist/cost/estimate.js +65 -0
  56. package/dist/cost/model-spec.d.ts +28 -0
  57. package/dist/cost/model-spec.js +29 -0
  58. package/dist/cost/standard-types.d.ts +9 -0
  59. package/dist/cost/standard-types.js +1 -0
  60. package/dist/cost/usage-math.d.ts +18 -0
  61. package/dist/cost/usage-math.js +46 -0
  62. package/dist/index.d.ts +26 -0
  63. package/dist/index.js +21 -0
  64. package/dist/infra/agent-logger.d.ts +22 -0
  65. package/dist/infra/agent-logger.js +19 -0
  66. package/dist/infra/credentials-config.d.ts +20 -0
  67. package/dist/infra/credentials-config.js +15 -0
  68. package/dist/infra/errors.d.ts +9 -0
  69. package/dist/infra/errors.js +11 -0
  70. package/dist/infra/index.d.ts +7 -0
  71. package/dist/infra/index.js +7 -0
  72. package/dist/infra/nax-error.d.ts +10 -0
  73. package/dist/infra/nax-error.js +16 -0
  74. package/dist/infra/spin-breaker/hash.d.ts +2 -0
  75. package/dist/infra/spin-breaker/hash.js +5 -0
  76. package/dist/infra/spin-breaker/index.d.ts +120 -0
  77. package/dist/infra/spin-breaker/index.js +340 -0
  78. package/dist/internal/agent-output-env.d.ts +44 -0
  79. package/dist/internal/agent-output-env.js +57 -0
  80. package/dist/internal/argv-exec.d.ts +58 -0
  81. package/dist/internal/argv-exec.js +224 -0
  82. package/dist/internal/bounded-io.d.ts +24 -0
  83. package/dist/internal/bounded-io.js +51 -0
  84. package/dist/internal/command-spec/index.d.ts +29 -0
  85. package/dist/internal/command-spec/index.js +36 -0
  86. package/dist/internal/describe-value-type.d.ts +8 -0
  87. package/dist/internal/describe-value-type.js +14 -0
  88. package/dist/internal/exec-framing.d.ts +18 -0
  89. package/dist/internal/exec-framing.js +22 -0
  90. package/dist/internal/file-lock.d.ts +91 -0
  91. package/dist/internal/file-lock.js +212 -0
  92. package/dist/internal/file-size.d.ts +2 -0
  93. package/dist/internal/file-size.js +12 -0
  94. package/dist/internal/git-add.d.ts +43 -0
  95. package/dist/internal/git-add.js +59 -0
  96. package/dist/internal/git-env.d.ts +59 -0
  97. package/dist/internal/git-env.js +93 -0
  98. package/dist/internal/git-exec.d.ts +58 -0
  99. package/dist/internal/git-exec.js +115 -0
  100. package/dist/internal/path-file-lock.d.ts +23 -0
  101. package/dist/internal/path-file-lock.js +25 -0
  102. package/dist/internal/process-alive.d.ts +42 -0
  103. package/dist/internal/process-alive.js +56 -0
  104. package/dist/internal/process-kill.d.ts +27 -0
  105. package/dist/internal/process-kill.js +54 -0
  106. package/dist/internal/realpath.d.ts +29 -0
  107. package/dist/internal/realpath.js +52 -0
  108. package/dist/internal/redact.d.ts +40 -0
  109. package/dist/internal/redact.js +161 -0
  110. package/dist/internal/shell-quote.d.ts +2 -0
  111. package/dist/internal/shell-quote.js +4 -0
  112. package/dist/internal/sort.d.ts +20 -0
  113. package/dist/internal/sort.js +20 -0
  114. package/dist/internal/strip-control-chars.d.ts +19 -0
  115. package/dist/internal/strip-control-chars.js +38 -0
  116. package/dist/internal/thenable.d.ts +10 -0
  117. package/dist/internal/thenable.js +15 -0
  118. package/dist/internal.d.ts +91 -0
  119. package/dist/internal.js +91 -0
  120. package/dist/native/adapter-deps.d.ts +46 -0
  121. package/dist/native/adapter-deps.js +43 -0
  122. package/dist/native/auth-types.d.ts +70 -0
  123. package/dist/native/auth-types.js +13 -0
  124. package/dist/native/auth.d.ts +133 -0
  125. package/dist/native/auth.js +362 -0
  126. package/dist/native/client.d.ts +50 -0
  127. package/dist/native/client.js +174 -0
  128. package/dist/native/complete.d.ts +33 -0
  129. package/dist/native/complete.js +88 -0
  130. package/dist/native/credentials/chained-store.d.ts +30 -0
  131. package/dist/native/credentials/chained-store.js +68 -0
  132. package/dist/native/credentials/change-guard.d.ts +51 -0
  133. package/dist/native/credentials/change-guard.js +136 -0
  134. package/dist/native/credentials/exec-source.d.ts +50 -0
  135. package/dist/native/credentials/exec-source.js +222 -0
  136. package/dist/native/credentials/fingerprint.d.ts +26 -0
  137. package/dist/native/credentials/fingerprint.js +174 -0
  138. package/dist/native/credentials/helper-process.d.ts +79 -0
  139. package/dist/native/credentials/helper-process.js +259 -0
  140. package/dist/native/credentials/helper-protocol.d.ts +36 -0
  141. package/dist/native/credentials/helper-protocol.js +79 -0
  142. package/dist/native/credentials/index.d.ts +60 -0
  143. package/dist/native/credentials/index.js +184 -0
  144. package/dist/native/errors.d.ts +34 -0
  145. package/dist/native/errors.js +109 -0
  146. package/dist/native/index.d.ts +25 -0
  147. package/dist/native/index.js +23 -0
  148. package/dist/native/model-resolver.d.ts +57 -0
  149. package/dist/native/model-resolver.js +73 -0
  150. package/dist/native/models.d.ts +116 -0
  151. package/dist/native/models.js +183 -0
  152. package/dist/native/session/ask-human.d.ts +15 -0
  153. package/dist/native/session/ask-human.js +22 -0
  154. package/dist/native/session/compaction.d.ts +94 -0
  155. package/dist/native/session/compaction.js +170 -0
  156. package/dist/native/session/handle-invalid-tool-call.d.ts +111 -0
  157. package/dist/native/session/handle-invalid-tool-call.js +159 -0
  158. package/dist/native/session/loop-events/cache-boundary.d.ts +11 -0
  159. package/dist/native/session/loop-events/cache-boundary.js +29 -0
  160. package/dist/native/session/loop-events/external-handler.d.ts +38 -0
  161. package/dist/native/session/loop-events/external-handler.js +193 -0
  162. package/dist/native/session/loop-events/index.d.ts +16 -0
  163. package/dist/native/session/loop-events/index.js +15 -0
  164. package/dist/native/session/loop-events/payload-guard.d.ts +9 -0
  165. package/dist/native/session/loop-events/payload-guard.js +31 -0
  166. package/dist/native/session/loop-events/registry.d.ts +84 -0
  167. package/dist/native/session/loop-events/registry.js +305 -0
  168. package/dist/native/session/loop-events/types.d.ts +251 -0
  169. package/dist/native/session/loop-events/types.js +14 -0
  170. package/dist/native/session/loop-handlers.d.ts +73 -0
  171. package/dist/native/session/loop-handlers.js +137 -0
  172. package/dist/native/session/nudge.d.ts +29 -0
  173. package/dist/native/session/nudge.js +35 -0
  174. package/dist/native/session/rate-provenance.d.ts +17 -0
  175. package/dist/native/session/rate-provenance.js +39 -0
  176. package/dist/native/session/session.d.ts +139 -0
  177. package/dist/native/session/session.js +208 -0
  178. package/dist/native/session/tool-input-exemplar.d.ts +2 -0
  179. package/dist/native/session/tool-input-exemplar.js +66 -0
  180. package/dist/native/session/tool-input-validation.d.ts +15 -0
  181. package/dist/native/session/tool-input-validation.js +146 -0
  182. package/dist/native/session/tool-mapping.d.ts +18 -0
  183. package/dist/native/session/tool-mapping.js +27 -0
  184. package/dist/native/session/tool-result.d.ts +37 -0
  185. package/dist/native/session/tool-result.js +25 -0
  186. package/dist/native/session/transcript-store.d.ts +77 -0
  187. package/dist/native/session/transcript-store.js +200 -0
  188. package/dist/native/session/truncation-handler.d.ts +47 -0
  189. package/dist/native/session/truncation-handler.js +83 -0
  190. package/dist/native/session/turn-accumulator.d.ts +45 -0
  191. package/dist/native/session/turn-accumulator.js +67 -0
  192. package/dist/native/session/turn-ask-human.d.ts +23 -0
  193. package/dist/native/session/turn-ask-human.js +41 -0
  194. package/dist/native/session/turn-compaction-step.d.ts +74 -0
  195. package/dist/native/session/turn-compaction-step.js +128 -0
  196. package/dist/native/session/turn-complete-step.d.ts +77 -0
  197. package/dist/native/session/turn-complete-step.js +159 -0
  198. package/dist/native/session/turn-end-event.d.ts +3 -0
  199. package/dist/native/session/turn-end-event.js +17 -0
  200. package/dist/native/session/turn-events.d.ts +63 -0
  201. package/dist/native/session/turn-events.js +48 -0
  202. package/dist/native/session/turn-loop-round-trip.d.ts +116 -0
  203. package/dist/native/session/turn-loop-round-trip.js +318 -0
  204. package/dist/native/session/turn-loop.d.ts +23 -0
  205. package/dist/native/session/turn-loop.js +250 -0
  206. package/dist/native/session/turn-result.d.ts +39 -0
  207. package/dist/native/session/turn-result.js +64 -0
  208. package/dist/native/session/turn-retry.d.ts +120 -0
  209. package/dist/native/session/turn-retry.js +182 -0
  210. package/dist/native/session/turn-tool-batch.d.ts +61 -0
  211. package/dist/native/session/turn-tool-batch.js +259 -0
  212. package/dist/native/session/turn-types.d.ts +164 -0
  213. package/dist/native/session/turn-types.js +36 -0
  214. package/dist/native/session-adapter.d.ts +56 -0
  215. package/dist/native/session-adapter.js +369 -0
  216. package/dist/native/session-affinity.d.ts +36 -0
  217. package/dist/native/session-affinity.js +43 -0
  218. package/dist/native/tier-providers.d.ts +18 -0
  219. package/dist/native/tier-providers.js +20 -0
  220. package/dist/permissions/approval-audit.d.ts +10 -0
  221. package/dist/permissions/approval-audit.js +22 -0
  222. package/dist/permissions/approvals-link.d.ts +20 -0
  223. package/dist/permissions/approvals-link.js +62 -0
  224. package/dist/permissions/approvals-store.d.ts +168 -0
  225. package/dist/permissions/approvals-store.js +259 -0
  226. package/dist/permissions/approvals-taint.d.ts +33 -0
  227. package/dist/permissions/approvals-taint.js +138 -0
  228. package/dist/permissions/ask-chain.d.ts +69 -0
  229. package/dist/permissions/ask-chain.js +32 -0
  230. package/dist/permissions/ask.d.ts +23 -0
  231. package/dist/permissions/ask.js +25 -0
  232. package/dist/permissions/bash-lex.d.ts +59 -0
  233. package/dist/permissions/bash-lex.js +279 -0
  234. package/dist/permissions/grammar.d.ts +12 -0
  235. package/dist/permissions/grammar.js +24 -0
  236. package/dist/permissions/index.d.ts +11 -0
  237. package/dist/permissions/index.js +9 -0
  238. package/dist/permissions/secret-spans.d.ts +19 -0
  239. package/dist/permissions/secret-spans.js +88 -0
  240. package/dist/permissions/types.d.ts +85 -0
  241. package/dist/permissions/types.js +1 -0
  242. package/dist/runtime/index.d.ts +3 -0
  243. package/dist/runtime/index.js +2 -0
  244. package/dist/runtime/node-glob.d.ts +3 -0
  245. package/dist/runtime/node-glob.js +83 -0
  246. package/dist/runtime/node-runtime.d.ts +3 -0
  247. package/dist/runtime/node-runtime.js +126 -0
  248. package/dist/runtime/slot.d.ts +11 -0
  249. package/dist/runtime/slot.js +17 -0
  250. package/dist/runtime/types.d.ts +51 -0
  251. package/dist/runtime/types.js +1 -0
  252. package/dist/runtime/which.d.ts +8 -0
  253. package/dist/runtime/which.js +32 -0
  254. package/dist/sandbox/argv-quote.d.ts +11 -0
  255. package/dist/sandbox/argv-quote.js +13 -0
  256. package/dist/sandbox/defaults.d.ts +27 -0
  257. package/dist/sandbox/defaults.js +47 -0
  258. package/dist/sandbox/git-guards.d.ts +64 -0
  259. package/dist/sandbox/git-guards.js +161 -0
  260. package/dist/sandbox/index.d.ts +11 -0
  261. package/dist/sandbox/index.js +10 -0
  262. package/dist/sandbox/launcher.d.ts +37 -0
  263. package/dist/sandbox/launcher.js +160 -0
  264. package/dist/sandbox/messages.d.ts +17 -0
  265. package/dist/sandbox/messages.js +46 -0
  266. package/dist/sandbox/policy-builder.d.ts +44 -0
  267. package/dist/sandbox/policy-builder.js +149 -0
  268. package/dist/sandbox/policy-inputs.d.ts +53 -0
  269. package/dist/sandbox/policy-inputs.js +76 -0
  270. package/dist/sandbox/probe.d.ts +8 -0
  271. package/dist/sandbox/probe.js +66 -0
  272. package/dist/sandbox/registry.d.ts +17 -0
  273. package/dist/sandbox/registry.js +57 -0
  274. package/dist/sandbox/session-tmp.d.ts +20 -0
  275. package/dist/sandbox/session-tmp.js +95 -0
  276. package/dist/sandbox/srt-backend.d.ts +21 -0
  277. package/dist/sandbox/srt-backend.js +99 -0
  278. package/dist/sandbox/types.d.ts +102 -0
  279. package/dist/sandbox/types.js +1 -0
  280. package/dist/session/adapter-failure.d.ts +60 -0
  281. package/dist/session/adapter-failure.js +11 -0
  282. package/dist/session/agent-stream-events.d.ts +103 -0
  283. package/dist/session/agent-stream-events.js +6 -0
  284. package/dist/session/interaction-handler.d.ts +53 -0
  285. package/dist/session/interaction-handler.js +2 -0
  286. package/dist/session/no-op-interaction-handler.d.ts +9 -0
  287. package/dist/session/no-op-interaction-handler.js +11 -0
  288. package/dist/session/protocol-types.d.ts +12 -0
  289. package/dist/session/protocol-types.js +1 -0
  290. package/dist/session/session-types.d.ts +456 -0
  291. package/dist/session/session-types.js +64 -0
  292. package/dist/session/tool-descriptor.d.ts +23 -0
  293. package/dist/session/tool-descriptor.js +5 -0
  294. package/dist/session/turn-deadline.d.ts +17 -0
  295. package/dist/session/turn-deadline.js +23 -0
  296. package/dist/tools/ask-request.d.ts +35 -0
  297. package/dist/tools/ask-request.js +57 -0
  298. package/dist/tools/bash-cwd.d.ts +82 -0
  299. package/dist/tools/bash-cwd.js +55 -0
  300. package/dist/tools/bash.d.ts +69 -0
  301. package/dist/tools/bash.js +283 -0
  302. package/dist/tools/delete.d.ts +57 -0
  303. package/dist/tools/delete.js +154 -0
  304. package/dist/tools/denial-redirect.d.ts +42 -0
  305. package/dist/tools/denial-redirect.js +266 -0
  306. package/dist/tools/deny-paths.d.ts +35 -0
  307. package/dist/tools/deny-paths.js +76 -0
  308. package/dist/tools/edit-region.d.ts +50 -0
  309. package/dist/tools/edit-region.js +90 -0
  310. package/dist/tools/edit.d.ts +25 -0
  311. package/dist/tools/edit.js +114 -0
  312. package/dist/tools/exec-allowlist-text.d.ts +18 -0
  313. package/dist/tools/exec-allowlist-text.js +24 -0
  314. package/dist/tools/exec-guard.d.ts +69 -0
  315. package/dist/tools/exec-guard.js +151 -0
  316. package/dist/tools/git-commit.d.ts +59 -0
  317. package/dist/tools/git-commit.js +220 -0
  318. package/dist/tools/git-flags/index.d.ts +10 -0
  319. package/dist/tools/git-flags/index.js +10 -0
  320. package/dist/tools/git.d.ts +88 -0
  321. package/dist/tools/git.js +397 -0
  322. package/dist/tools/glob.d.ts +29 -0
  323. package/dist/tools/glob.js +153 -0
  324. package/dist/tools/grep.d.ts +21 -0
  325. package/dist/tools/grep.js +162 -0
  326. package/dist/tools/index.d.ts +36 -0
  327. package/dist/tools/index.js +28 -0
  328. package/dist/tools/narrow-grants.d.ts +19 -0
  329. package/dist/tools/narrow-grants.js +54 -0
  330. package/dist/tools/nax-owned-writes.d.ts +135 -0
  331. package/dist/tools/nax-owned-writes.js +259 -0
  332. package/dist/tools/package-managers-table.d.ts +146 -0
  333. package/dist/tools/package-managers-table.js +325 -0
  334. package/dist/tools/package-managers-types.d.ts +36 -0
  335. package/dist/tools/package-managers-types.js +6 -0
  336. package/dist/tools/package-managers.d.ts +85 -0
  337. package/dist/tools/package-managers.js +391 -0
  338. package/dist/tools/path-list.d.ts +38 -0
  339. package/dist/tools/path-list.js +62 -0
  340. package/dist/tools/policy-bash-raw.d.ts +19 -0
  341. package/dist/tools/policy-bash-raw.js +210 -0
  342. package/dist/tools/policy-bash.d.ts +64 -0
  343. package/dist/tools/policy-bash.js +232 -0
  344. package/dist/tools/policy-command-branch.d.ts +32 -0
  345. package/dist/tools/policy-command-branch.js +63 -0
  346. package/dist/tools/policy-input.d.ts +2 -0
  347. package/dist/tools/policy-input.js +10 -0
  348. package/dist/tools/policy-match.d.ts +75 -0
  349. package/dist/tools/policy-match.js +117 -0
  350. package/dist/tools/policy-paths-branch.d.ts +97 -0
  351. package/dist/tools/policy-paths-branch.js +314 -0
  352. package/dist/tools/policy.d.ts +65 -0
  353. package/dist/tools/policy.js +232 -0
  354. package/dist/tools/protected-paths.d.ts +26 -0
  355. package/dist/tools/protected-paths.js +8 -0
  356. package/dist/tools/provider-adapt.d.ts +4 -0
  357. package/dist/tools/provider-adapt.js +32 -0
  358. package/dist/tools/provider-advertise.d.ts +39 -0
  359. package/dist/tools/provider-advertise.js +50 -0
  360. package/dist/tools/provider-grants.d.ts +36 -0
  361. package/dist/tools/provider-grants.js +72 -0
  362. package/dist/tools/provider-sanitize.d.ts +19 -0
  363. package/dist/tools/provider-sanitize.js +53 -0
  364. package/dist/tools/provider-types.d.ts +41 -0
  365. package/dist/tools/provider-types.js +26 -0
  366. package/dist/tools/read-continuation.d.ts +147 -0
  367. package/dist/tools/read-continuation.js +176 -0
  368. package/dist/tools/read-file.d.ts +32 -0
  369. package/dist/tools/read-file.js +85 -0
  370. package/dist/tools/read.d.ts +25 -0
  371. package/dist/tools/read.js +182 -0
  372. package/dist/tools/registry.d.ts +125 -0
  373. package/dist/tools/registry.js +67 -0
  374. package/dist/tools/request-capability.d.ts +13 -0
  375. package/dist/tools/request-capability.js +23 -0
  376. package/dist/tools/run-command-exec.d.ts +14 -0
  377. package/dist/tools/run-command-exec.js +161 -0
  378. package/dist/tools/run-command.d.ts +107 -0
  379. package/dist/tools/run-command.js +398 -0
  380. package/dist/tools/runtime-calltool.d.ts +146 -0
  381. package/dist/tools/runtime-calltool.js +223 -0
  382. package/dist/tools/runtime.d.ts +149 -0
  383. package/dist/tools/runtime.js +345 -0
  384. package/dist/tools/scratchpad.d.ts +20 -0
  385. package/dist/tools/scratchpad.js +197 -0
  386. package/dist/tools/spill.d.ts +81 -0
  387. package/dist/tools/spill.js +251 -0
  388. package/dist/tools/tool-audit.d.ts +171 -0
  389. package/dist/tools/tool-audit.js +183 -0
  390. package/dist/tools/truncate.d.ts +98 -0
  391. package/dist/tools/truncate.js +297 -0
  392. package/dist/tools/types.d.ts +145 -0
  393. package/dist/tools/types.js +24 -0
  394. package/dist/tools/verb-denial-argv-hint.d.ts +35 -0
  395. package/dist/tools/verb-denial-argv-hint.js +40 -0
  396. package/dist/tools/write.d.ts +9 -0
  397. package/dist/tools/write.js +45 -0
  398. package/package.json +54 -0
@@ -0,0 +1,398 @@
1
+ /**
2
+ * Runs a command the PROJECT declared, never one the model wrote.
3
+ *
4
+ * This reaches a shell, deliberately: nax's quality runner
5
+ * (`src/quality/runner.ts`, supplied as `runDeclaredCommand`) executes every
6
+ * configured command through one to preserve their quoting semantics, and a
7
+ * declared command like "CI=1 bun test {{files}}" has no argv form -- CI=1 is a
8
+ * shell assignment, not a binary. Building a second execution path would mean
9
+ * the same command behaved differently depending on who invoked it.
10
+ *
11
+ * So the property here is narrower than the Git tool's, and is stated rather
12
+ * than implied: the model does not author the command string. It names a
13
+ * declared key and supplies placeholder values, and those values are the entire
14
+ * injection surface. They are quoted with shellQuoteArg -- the same helper
15
+ * command-resolver.ts already applies to {{package}}.
16
+ */
17
+ import { statSync } from "node:fs";
18
+ import { describeValuesType } from "#src/internal/describe-value-type";
19
+ import { shellQuoteArg } from "#src/internal/shell-quote";
20
+ import { sandboxSentence, unsandboxedSentence } from "../sandbox/index.js";
21
+ import { describeExecAllowlist } from "./exec-allowlist-text.js";
22
+ import { pathListElements } from "./path-list.js";
23
+ import { runExecBranch } from "./run-command-exec.js";
24
+ import { cutToByteCap, READ_CEILING } from "./truncate.js";
25
+ const PLACEHOLDER = /\{\{([a-zA-Z]+)\}\}/g;
26
+ function quoteAt(template, end) {
27
+ let quote;
28
+ let escaped = false;
29
+ for (let i = 0; i < end; i += 1) {
30
+ const char = template[i];
31
+ if (escaped) {
32
+ escaped = false;
33
+ continue;
34
+ }
35
+ if (char === "\\" && quote !== "single") {
36
+ escaped = true;
37
+ continue;
38
+ }
39
+ if (char === "'" && quote !== "double")
40
+ quote = quote === "single" ? undefined : "single";
41
+ if (char === '"' && quote !== "single")
42
+ quote = quote === "double" ? undefined : "double";
43
+ }
44
+ return quote;
45
+ }
46
+ function placeholderContextError(template) {
47
+ for (const match of template.matchAll(PLACEHOLDER)) {
48
+ const start = match.index ?? 0;
49
+ const key = match[1];
50
+ if (quoteAt(template, start) !== undefined) {
51
+ return `placeholder {{${key}}} may not appear inside shell quotes`;
52
+ }
53
+ const tokenStart = Math.max(template.lastIndexOf(" ", start), template.lastIndexOf("\t", start)) + 1;
54
+ const tokenEndMatch = /[ \t\r\n]/.exec(template.slice(start));
55
+ const tokenEnd = tokenEndMatch === null ? template.length : start + tokenEndMatch.index;
56
+ const token = template.slice(tokenStart, tokenEnd);
57
+ if (/[$`()]/.test(token)) {
58
+ return `placeholder {{${key}}} may not appear in a shell expansion`;
59
+ }
60
+ }
61
+ return undefined;
62
+ }
63
+ // A bare "no" is what produced the defect this exists to fix (#1924): denied
64
+ // with no legal alternative named, the model repeated the identical rejected
65
+ // call 18 times in one session because it was never told the placeholder
66
+ // set. Matches git.ts's "valid for: ..." phrasing convention. A command with
67
+ // no placeholders reads naturally rather than printing "(declared: )".
68
+ function declaredPlaceholdersSuffix(declared) {
69
+ if (declared.size === 0)
70
+ return "this command declares no placeholders";
71
+ return `declared: ${[...declared].join(", ")}`;
72
+ }
73
+ /**
74
+ * An ARRAY value is quoted per element and joined; a string value is quoted
75
+ * whole. The distinction carries the element boundaries through substitution,
76
+ * which a pre-joined string cannot: the join would be re-split and a path
77
+ * under `/tmp/my dir/` would become two arguments (nax#1998).
78
+ */
79
+ export function substituteCommand(template, values) {
80
+ const declared = new Set([...template.matchAll(PLACEHOLDER)].map((m) => m[1]));
81
+ for (const key of Object.keys(values)) {
82
+ if (!declared.has(key)) {
83
+ return { error: `value "${key}" is not a placeholder in this command (${declaredPlaceholdersSuffix(declared)})` };
84
+ }
85
+ }
86
+ for (const key of declared) {
87
+ if (values[key] === undefined) {
88
+ return { error: `placeholder {{${key}}} has no value (${declaredPlaceholdersSuffix(declared)})` };
89
+ }
90
+ }
91
+ const contextError = placeholderContextError(template);
92
+ if (contextError !== undefined)
93
+ return { error: contextError };
94
+ return template.replaceAll(PLACEHOLDER, (_m, key) => {
95
+ const value = values[key];
96
+ return Array.isArray(value) ? value.map(shellQuoteArg).join(" ") : shellQuoteArg(value);
97
+ });
98
+ }
99
+ /**
100
+ * Apply placeholder substitution across a spec. A list substitutes into every
101
+ * entry and fails as a whole if any entry fails, so a partially-substituted
102
+ * list can never reach the shell.
103
+ *
104
+ * Each entry only receives the subset of `values` it actually declares
105
+ * placeholders for -- list entries commonly have different placeholder needs
106
+ * (e.g. `["tsc --noEmit", "bun test {{files}}"]`), and `substituteCommand`
107
+ * rejects a value that isn't a placeholder in the template it's checking, by
108
+ * design (it's what stops a value silently going nowhere). Passing the full
109
+ * shared `values` object to every entry would make every entry without
110
+ * {{files}} fail that check.
111
+ *
112
+ * But per-entry filtering alone would let a value that no entry in the whole
113
+ * spec declares vanish silently (every entry's filtered set would just be
114
+ * empty, and every entry would substitute cleanly) -- so before filtering
115
+ * per entry, every key in `values` is checked against the UNION of
116
+ * placeholders declared across the whole spec, and rejected with the same
117
+ * "unrecognized value" contract `substituteCommand` gives the single-string
118
+ * case if it isn't declared anywhere.
119
+ */
120
+ export function substituteCommandSpec(spec, values) {
121
+ if (typeof spec === "string")
122
+ return substituteCommand(spec, values);
123
+ const allDeclared = new Set();
124
+ for (const entry of spec) {
125
+ for (const match of entry.matchAll(PLACEHOLDER))
126
+ allDeclared.add(match[1]);
127
+ }
128
+ for (const key of Object.keys(values)) {
129
+ if (!allDeclared.has(key)) {
130
+ return {
131
+ error: `value "${key}" is not a placeholder in this command (${declaredPlaceholdersSuffix(allDeclared)})`,
132
+ };
133
+ }
134
+ }
135
+ const out = [];
136
+ for (const entry of spec) {
137
+ const declaredKeys = new Set([...entry.matchAll(PLACEHOLDER)].map((m) => m[1]));
138
+ const entryValues = {};
139
+ for (const [key, value] of Object.entries(values)) {
140
+ if (declaredKeys.has(key))
141
+ entryValues[key] = value;
142
+ }
143
+ const substituted = substituteCommand(entry, entryValues);
144
+ if (typeof substituted !== "string")
145
+ return substituted;
146
+ out.push(substituted);
147
+ }
148
+ return out;
149
+ }
150
+ // #1924, second half: the description-only fix, which is what prevents the
151
+ // repeated-call loop rather than merely explaining it after the first
152
+ // failure. Renders each declared command with the placeholders its OWN
153
+ // template actually contains, so the model can pick values before it
154
+ // guesses -- e.g. "test (no placeholders), testScoped ({{files}})".
155
+ function placeholdersOf(spec) {
156
+ const templates = typeof spec === "string" ? [spec] : spec;
157
+ return new Set(templates.flatMap((template) => [...template.matchAll(PLACEHOLDER)].map((m) => m[1])));
158
+ }
159
+ function describeDeclaredCommand(name, spec) {
160
+ const placeholders = [...placeholdersOf(spec)];
161
+ if (placeholders.length === 0)
162
+ return `${name} (no placeholders)`;
163
+ return `${name} (${placeholders.map((p) => `{{${p}}}`).join(", ")})`;
164
+ }
165
+ function describeDeclaredCommands(declared) {
166
+ return [...declared.entries()].map(([name, template]) => describeDeclaredCommand(name, template)).join(", ");
167
+ }
168
+ // The live-run defect this exists to fix (run-2026-09-14T08-21-43-607Z): the
169
+ // "values" input was cast straight to Record<string, unknown> with no shape
170
+ // check, so a model sending a STRING got its characters iterated as if they
171
+ // were object keys. An empty string produced no rejected keys at all, so the
172
+ // unrelated "has no value" branch fired instead; "\t" produced the key "0",
173
+ // so the response named a placeholder that was never in the input. 84 of 97
174
+ // RunCommand calls in that run hit one of these two shapes, in a loop the
175
+ // model could not escape because neither message ever said "values" itself
176
+ // was the wrong type. Checked before "raw" is derived, so a malformed shape
177
+ // can never reach Object.keys/Object.entries below.
178
+ function isPlainValuesObject(value) {
179
+ return typeof value === "object" && value !== null && !Array.isArray(value);
180
+ }
181
+ // #1924, third half (run-2026-09-14T05-55-54-734Z audit, Shape A): the
182
+ // original error only ever named what the CHOSEN command declares, never
183
+ // which OTHER declared command accepts the rejected key -- an agent that
184
+ // wants scoped tests and picks "test" learns "no placeholders" and has to
185
+ // guess a second time. Naming the real alternative ends the loop on the
186
+ // first denial. Returns an empty array (no hint appended) when no other
187
+ // command declares the key either, so a genuinely unrecognized value stays
188
+ // exactly as informative as before -- never a false pointer.
189
+ function otherCommandsDeclaring(declared, key, currentCommand) {
190
+ const names = [];
191
+ for (const [name, spec] of declared) {
192
+ if (name !== currentCommand && placeholdersOf(spec).has(key))
193
+ names.push(name);
194
+ }
195
+ return names;
196
+ }
197
+ function execSandboxNote(launcher) {
198
+ const state = launcher?.state;
199
+ if (state?.kind === "available")
200
+ return ` An "argv" call runs ${sandboxSentence(state.network, state.sharedTmp !== false)}`;
201
+ if (state?.kind === "unavailable")
202
+ return ` ${unsandboxedSentence(state.reason)}`;
203
+ return "";
204
+ }
205
+ const MISSING_RUNNER_OUTPUT = "no declared-command runner is configured for this session";
206
+ /** The runner a tool built without one uses: refuses, spawns nothing. */
207
+ async function refuseWithoutRunner() {
208
+ return { success: false, exitCode: 1, output: MISSING_RUNNER_OUTPUT };
209
+ }
210
+ /** One named default, so the refusal path lives in a single place. */
211
+ function declaredCommandRunner(opts) {
212
+ return opts.runDeclaredCommand ?? refuseWithoutRunner;
213
+ }
214
+ export function createRunCommandTool(declared, opts = {}) {
215
+ const keys = [...declared.keys()];
216
+ const exec = opts.exec;
217
+ const hasExec = exec !== undefined;
218
+ const commandDescriptions = describeDeclaredCommands(declared);
219
+ const runDeclared = declaredCommandRunner(opts);
220
+ return {
221
+ name: "RunCommand",
222
+ // A non-zero exit here is the agent's red/green loop, not a fault.
223
+ routineErrors: true,
224
+ description: exec !== undefined
225
+ ? `Two ways to run something. (1) Run one of this project's declared commands: ${commandDescriptions} — supply "command" and, optionally, "values" for its placeholders. (2) Run an allowlisted external command via "argv" (an array, e.g. ["bun","add","left-pad"]) — no shell, so no quoting and no shell metacharacters; ${describeExecAllowlist(exec.patterns)}. Supply exactly one of "command" or "argv".${execSandboxNote(exec.launcher)}`
226
+ : `Run one of this project's declared commands: ${commandDescriptions}. Supply values for its placeholders; you cannot write a command of your own.`,
227
+ inputSchema: {
228
+ type: "object",
229
+ properties: {
230
+ command: { type: "string", enum: keys, description: "Which declared command to run" },
231
+ values: {
232
+ type: "object",
233
+ description: 'Values for the command\'s placeholders, e.g. { files: "a.test.ts" }. A path placeholder takes several paths separated by spaces, e.g. { files: "a.test.ts b.test.ts" }, or as an array of paths, e.g. { files: ["test/a.test.ts", "test/b.test.ts"] } -- one call, not one per file.',
234
+ },
235
+ ...(hasExec
236
+ ? {
237
+ argv: {
238
+ type: "array",
239
+ items: { type: "string" },
240
+ description: 'Argv for an allowlisted external command, e.g. ["bun","add","left-pad"]. No shell: each element is one literal argument. Supply exactly one of "command" or "argv".',
241
+ },
242
+ target: {
243
+ type: "string",
244
+ enum: ["repoRoot", "package"],
245
+ description: 'Working directory for "argv": this package (default) or the repo root.',
246
+ },
247
+ }
248
+ : {}),
249
+ },
250
+ // With exec available, neither field is unconditionally required —
251
+ // run() enforces "exactly one of command or argv" at call time, which
252
+ // a static JSON Schema `required` list cannot express as an either/or.
253
+ ...(hasExec ? {} : { required: ["command"] }),
254
+ },
255
+ // `{{files}}` is the declared scoped-test path parameter. Keeping it in
256
+ // the policy's containment seam prevents a quoted-but-otherwise harmless
257
+ // absolute filename from making the configured command act outside root.
258
+ // `argvField` is set only when exec is available: it is what lets the
259
+ // policy recognize an argv call and check it under the `Exec` identity
260
+ // (see src/tools/runtime.ts and src/tools/policy.ts) rather than under
261
+ // RunCommand's own grant.
262
+ scope: {
263
+ pathFields: [],
264
+ listPathFields: ["values.files"],
265
+ verbField: "command",
266
+ allowedVerbs: keys,
267
+ ...(hasExec ? { argvField: "argv" } : {}),
268
+ },
269
+ async run(input, ctx) {
270
+ const hasCommand = typeof input.command === "string" && input.command.length > 0;
271
+ const hasArgv = input.argv !== undefined;
272
+ if (hasCommand && hasArgv) {
273
+ return { content: "supply exactly one of command or argv, not both", isError: true };
274
+ }
275
+ if (hasArgv)
276
+ return runExecBranch(input, ctx, opts);
277
+ // #2066: `target` is read only on the argv branch (run-command-exec.ts).
278
+ // 48 of 136 declared-command calls in one audited run carried a `target`
279
+ // that was silently discarded, and the transcript shows the model
280
+ // reasoning about it while trying to fix a failure. Silently ignoring it
281
+ // is the one option that teaches nothing.
282
+ if (input.target !== undefined) {
283
+ return {
284
+ content: `"target" applies only to "argv" calls; a declared command runs in the directory its configuration declares. Remove "target" and call "${typeof input.command === "string" ? input.command : ""}" on its own.`,
285
+ isError: true,
286
+ };
287
+ }
288
+ const key = typeof input.command === "string" ? input.command : "";
289
+ const template = declared.get(key);
290
+ if (template === undefined)
291
+ return { content: `unknown command "${key}"`, isError: true };
292
+ if (input.values !== undefined && !isPlainValuesObject(input.values)) {
293
+ return {
294
+ content: `"values" must be an object mapping placeholder names to values, e.g. { files: "a.test.ts" } -- got ${describeValuesType(input.values)} instead`,
295
+ isError: true,
296
+ };
297
+ }
298
+ const raw = (input.values ?? {});
299
+ // Shape A of the run-2026-09-14T05-55-54-734Z audit: check every
300
+ // rejected key against every OTHER declared command before falling
301
+ // through to substituteCommandSpec's generic error, so the response
302
+ // can name the command that actually accepts it. Only the first
303
+ // rejected key with a real alternative is reported -- consistent with
304
+ // substituteCommandSpec, which also stops at the first offending key.
305
+ const templateKeys = placeholdersOf(template);
306
+ for (const rejectedKey of Object.keys(raw)) {
307
+ if (templateKeys.has(rejectedKey))
308
+ continue;
309
+ const alternates = otherCommandsDeclaring(declared, rejectedKey, key);
310
+ if (alternates.length === 0)
311
+ continue;
312
+ return {
313
+ content: `value "${rejectedKey}" is not a placeholder in this command (${declaredPlaceholdersSuffix(templateKeys)}) -- "${rejectedKey}" is a placeholder in: ${alternates.join(", ")}`,
314
+ isError: true,
315
+ };
316
+ }
317
+ const values = {};
318
+ for (const [k, v] of Object.entries(raw)) {
319
+ values[k] = Array.isArray(v) && v.every((element) => typeof element === "string") ? v : String(v);
320
+ }
321
+ // `scope.listPathFields: ["values.files"]` means the policy split this
322
+ // value on whitespace and resolved EACH element into ctx.resolvedPaths --
323
+ // absolute, and approved against the grant. Substituting those instead of
324
+ // the raw string is what read.ts, write.ts, edit.ts and grep.ts already
325
+ // do, and it fixes a real defect: `bun test .nax/features/x/foo.test.ts`
326
+ // treats a bare dot-prefixed relative path as a test FILTER, not a path,
327
+ // and reports a confident false "no tests matched" (#1936). The absolute
328
+ // form runs.
329
+ //
330
+ // But a path field is a POLICY declaration, not a claim about what the
331
+ // agent actually passed. `{{files}}` is equally a test-NAME filter
332
+ // (`bun test run-command`), and resolveWithin accepts one happily,
333
+ // turning it into a nonexistent absolute path. So the resolved form is
334
+ // taken only for an element that is an existing FILE; everything else
335
+ // keeps the raw token it arrived as. "" splits to nothing, so it cannot
336
+ // absolutise to the root and run the entire suite.
337
+ //
338
+ // The result is an ARRAY, so each element survives substitution as its
339
+ // own argument -- which is what makes a multi-file scoped run possible
340
+ // at all, and what makes this path agree with scoped-selection.ts
341
+ // (nax#1998). One stat per element against a process spawn is free.
342
+ const rawFiles = raw.files;
343
+ const rawFilesValue = typeof rawFiles === "string"
344
+ ? rawFiles
345
+ : Array.isArray(rawFiles) && rawFiles.every((element) => typeof element === "string")
346
+ ? rawFiles
347
+ : undefined;
348
+ const elements = typeof rawFilesValue === "string"
349
+ ? pathListElements(rawFilesValue, ctx.root)
350
+ : Array.isArray(rawFilesValue)
351
+ ? rawFilesValue
352
+ : undefined;
353
+ if (elements !== undefined && rawFilesValue !== undefined) {
354
+ // The pairing is positional, and sound because `values.files` is this
355
+ // tool's only path field, so the policy appended exactly these
356
+ // elements in exactly this order (pinned by a test on `scope`).
357
+ //
358
+ // A length mismatch means the two layers disagreed -- a different root
359
+ // spelling, or a file created between the two stats. Falling back to
360
+ // the raw value is the fail-safe direction in BOTH directions: the
361
+ // shell then gets one argument, and one argument is always a subset of
362
+ // what the policy approved, however it split.
363
+ values.files =
364
+ ctx.resolvedPaths.length === elements.length
365
+ ? elements.map((element, i) => {
366
+ const resolved = ctx.resolvedPaths[i];
367
+ const isFile = resolved !== undefined && statSync(resolved, { throwIfNoEntry: false })?.isFile() === true;
368
+ return isFile ? resolved : element;
369
+ })
370
+ : rawFilesValue;
371
+ }
372
+ const command = substituteCommandSpec(template, values);
373
+ if (typeof command !== "string" && !Array.isArray(command))
374
+ return { content: command.error, isError: true };
375
+ const result = await runDeclared({
376
+ commandName: key,
377
+ command,
378
+ // Post-PR2 `ctx.root` is the repo root (not the package dir), so an
379
+ // omitted `commandCwd` runs the declared command at the repo root —
380
+ // every production caller threads `commandCwd` via `buildCodingToolSupport`;
381
+ // this fallback only fires from tests that bypass the support seam.
382
+ workdir: opts.commandCwd ?? ctx.root,
383
+ stripEnvVars: [...(opts.stripEnvVars ?? [])],
384
+ // The agent's own iteration loop, not a harness gate: kept in the JSONL
385
+ // at debug, off the console. Its outcome reaches the agent through the
386
+ // returned content, and the harness reports its own gates separately.
387
+ origin: "agent-tool",
388
+ });
389
+ const body = `exit ${result.exitCode}\n${result.output}`;
390
+ // Tool-layer I/O bound, not the model-facing cap: `maxBytes` shapes what
391
+ // the model is told and belongs to the session's truncation policy, which
392
+ // spills the cut. Bounded here so a runaway command cannot be buffered
393
+ // without limit, and cut on a codepoint boundary so the returned body
394
+ // never carries a replacement character.
395
+ return { content: cutToByteCap(body, ctx.readCeiling ?? READ_CEILING), isError: !result.success };
396
+ },
397
+ };
398
+ }
@@ -0,0 +1,146 @@
1
+ /**
2
+ * `callTool`'s branch bodies, extracted from `runtime.ts` for the A13
3
+ * complexity drain (docs/plans/STATUS-complexity-drain.md).
4
+ *
5
+ * Each helper is one free function taking a single options object; the
6
+ * closure-bound collaborators (`logCall`, `runTool`, the session-wide
7
+ * `signal`) arrive BY REFERENCE and are read at call time, so the
8
+ * `_codingToolDeps` seam stays defined in `runtime.ts` exactly as the barrel
9
+ * (`src/tools/index.ts`) re-exports it. This file imports `runtime.ts`
10
+ * TYPE-ONLY — a runtime import would cycle back to the factory.
11
+ *
12
+ * One asymmetry is preserved on purpose: the denial-path breach warn below and the
13
+ * rejected-guard warn (US-004) call the module-level `getSafeLogger` import
14
+ * directly, while the ledger `log` in `runtime.ts` reads
15
+ * `_codingToolDeps.getLogger()`. Both behaved that way before the extraction;
16
+ * the seam stub in the mirror suites has never covered either warn.
17
+ */
18
+ import { type CommandGuard, type CommandShadow, openShadowTap } from "#src/command-safety/index";
19
+ import { type AskResolver } from "#src/permissions/index";
20
+ import type { SandboxRecord } from "../sandbox/index.ts";
21
+ import type { CodingTool } from "./registry.ts";
22
+ import type { CodingToolOutcome, ToolCallContext } from "./runtime.ts";
23
+ import { type ToolPolicy } from "./types.ts";
24
+ type PolicyVerdict = ReturnType<ToolPolicy["check"]>;
25
+ /** The verdict shape the ask and deny branches see: the policy said no. */
26
+ type DeniedVerdict = Extract<PolicyVerdict, {
27
+ allowed: false;
28
+ }>;
29
+ /** Per-call audit data a tool's result carries into the ledger. */
30
+ export interface CallAudit {
31
+ executed?: readonly string[];
32
+ target?: "package" | "repoRoot";
33
+ /** Exec only: forwarded to the command shadow; never written to the ledger. */
34
+ cwd?: string;
35
+ approval?: {
36
+ decidedBy: string;
37
+ remembered: boolean;
38
+ latencyMs: number;
39
+ };
40
+ sandbox?: SandboxRecord;
41
+ exitCode?: number;
42
+ }
43
+ /** The per-call log wrapper `callTool` builds; settles the shadow tap too. */
44
+ export type LogCallFn = (tool: string, outcome: CodingToolOutcome["kind"] | "denied:ask", resultBytes: number, input: Record<string, unknown>, context: ToolCallContext | undefined, breach?: boolean, reason?: string, routineErrors?: boolean, audit?: CallAudit, resultBytesPreTruncation?: number) => void;
45
+ /** Executes a permitted call and records its outcome. */
46
+ export type RunToolFn = (target: CodingTool, callInput: Record<string, unknown>, resolvedPaths: readonly string[], approval?: {
47
+ decidedBy: string;
48
+ remembered: boolean;
49
+ latencyMs: number;
50
+ }) => Promise<CodingToolOutcome>;
51
+ export interface PolicyIdentity {
52
+ readonly policyIdentity: string;
53
+ readonly argvField: string | undefined;
54
+ readonly hasArgv: boolean;
55
+ }
56
+ /**
57
+ * A call carrying the tool's declared argv field (RunCommand's `Exec`
58
+ * branch) is checked, and ledgered, under the `Exec` identity rather
59
+ * than the tool's own name. Left as `name`, an `Exec(...)` grant would
60
+ * never be consulted — the call would run under RunCommand's own grant
61
+ * (often a wildcard for its declared commands), making the allowlist
62
+ * decorative. The tool's registered name is unaffected; this changes
63
+ * only which identity the policy and ledger see for THIS call.
64
+ */
65
+ export declare function resolvePolicyIdentity(name: string, tool: CodingTool, input: Record<string, unknown>): PolicyIdentity;
66
+ /**
67
+ * P5: observe the command now (not awaited), settled from the caller's
68
+ * logCall below. Undefined whenever the runtime has no shadow configured.
69
+ */
70
+ export declare function openCallShadowTap(p: {
71
+ shadow: CommandShadow | undefined;
72
+ identity: string;
73
+ tool: CodingTool;
74
+ input: Record<string, unknown>;
75
+ hasArgv: boolean;
76
+ argvField: string | undefined;
77
+ root: string;
78
+ stage: string | undefined;
79
+ storyId: string | undefined;
80
+ callId: string | undefined;
81
+ scopeId: string | undefined;
82
+ context: ToolCallContext | undefined;
83
+ verdict: PolicyVerdict;
84
+ }): ReturnType<typeof openShadowTap> | undefined;
85
+ /**
86
+ * US-004: the guard's flag-for-review route for an ALLOWED command.
87
+ *
88
+ * Returns the ask-shaped denial the flagged call routes through
89
+ * `resolveAskOutcome`, and undefined in every other case — no guard
90
+ * configured, an identity other than `Bash`/`Exec`, or an unflagged
91
+ * assessment — so the caller runs the tool exactly as it did before the guard
92
+ * existed. The guard is total by contract (US-003); a rejection, or a resolved
93
+ * decision the type does not actually hold, means that contract broke, so the
94
+ * call runs unguarded rather than being refused, and the failure is logged once
95
+ * per broken call.
96
+ */
97
+ export declare function resolveGuardDenial(p: {
98
+ identity: string;
99
+ tool: CodingTool;
100
+ input: Record<string, unknown>;
101
+ argvField: string | undefined;
102
+ guard: CommandGuard | undefined;
103
+ root: string;
104
+ tempConfined: boolean;
105
+ resolvedPaths: readonly string[];
106
+ }): Promise<DeniedVerdict | undefined>;
107
+ /**
108
+ * The ask branch: a call the policy gates matched an ask rule, so an
109
+ * AskResolver decides. US-003: build the AskControl from the per-call
110
+ * context. The turn's abort signal is forwarded verbatim, and onWaiting is
111
+ * wired so the resolver can tell the turn loop a human prompt is pending.
112
+ */
113
+ export declare function resolveAskOutcome(p: {
114
+ identity: string;
115
+ tool: CodingTool;
116
+ input: Record<string, unknown>;
117
+ context: ToolCallContext | undefined;
118
+ verdict: DeniedVerdict;
119
+ /** The runtime-level signal, falling back behind the per-call one. */
120
+ runtimeSignal: AbortSignal | undefined;
121
+ askResolver: AskResolver;
122
+ stage: string | undefined;
123
+ storyId: string | undefined;
124
+ root: string;
125
+ logCall: LogCallFn;
126
+ runTool: RunToolFn;
127
+ }): Promise<CodingToolOutcome>;
128
+ /**
129
+ * The deny branch: a final policy refusal, sharpened where possible with a
130
+ * redirect naming an advertised tool that serves the call's intent.
131
+ */
132
+ export declare function resolveDenialOutcome(p: {
133
+ name: string;
134
+ identity: string;
135
+ tool: CodingTool;
136
+ input: Record<string, unknown>;
137
+ context: ToolCallContext | undefined;
138
+ verdict: DeniedVerdict;
139
+ argvField: string | undefined;
140
+ /** What `advertised()` actually returned; a redirect names only these. */
141
+ advertisedNames: ReadonlySet<string>;
142
+ declaredCommands: ReadonlySet<string> | undefined;
143
+ root: string;
144
+ logCall: LogCallFn;
145
+ }): CodingToolOutcome;
146
+ export {};