@shield-agent/kya 0.32.7 → 0.33.1

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 (306) hide show
  1. package/.cursor-plugin/plugin.json +1 -1
  2. package/.mcp.json +1 -1
  3. package/LIMITATIONS.md +2 -2
  4. package/README.md +232 -17
  5. package/amp/settings.example.json +1 -1
  6. package/claude/claude_desktop_config.example.json +1 -1
  7. package/cline/cline_mcp_settings.example.json +1 -1
  8. package/copilot/mcp-config.example.json +1 -1
  9. package/data/iocs.json +17 -0
  10. package/dist/cli.d.ts +1 -1
  11. package/dist/cli.d.ts.map +1 -1
  12. package/dist/cli.js +237 -53
  13. package/dist/cli.js.map +1 -1
  14. package/dist/client.d.ts +2 -0
  15. package/dist/client.d.ts.map +1 -1
  16. package/dist/client.js +1 -1
  17. package/dist/client.js.map +1 -1
  18. package/dist/commands/connect.d.ts +1 -1
  19. package/dist/commands/connect.d.ts.map +1 -1
  20. package/dist/commands/connect.js +11 -3
  21. package/dist/commands/connect.js.map +1 -1
  22. package/dist/commands/dash.d.ts.map +1 -1
  23. package/dist/commands/dash.js +25 -1
  24. package/dist/commands/dash.js.map +1 -1
  25. package/dist/commands/doctor.d.ts +8 -0
  26. package/dist/commands/doctor.d.ts.map +1 -0
  27. package/dist/commands/doctor.js +26 -0
  28. package/dist/commands/doctor.js.map +1 -0
  29. package/dist/commands/eval-tool.d.ts +3 -0
  30. package/dist/commands/eval-tool.d.ts.map +1 -1
  31. package/dist/commands/eval-tool.js +2 -1
  32. package/dist/commands/eval-tool.js.map +1 -1
  33. package/dist/commands/export.d.ts +33 -0
  34. package/dist/commands/export.d.ts.map +1 -0
  35. package/dist/commands/export.js +121 -0
  36. package/dist/commands/export.js.map +1 -0
  37. package/dist/commands/hook.d.ts.map +1 -1
  38. package/dist/commands/hook.js +135 -26
  39. package/dist/commands/hook.js.map +1 -1
  40. package/dist/commands/hosted-hook.d.ts +8 -1
  41. package/dist/commands/hosted-hook.d.ts.map +1 -1
  42. package/dist/commands/hosted-hook.js +15 -5
  43. package/dist/commands/hosted-hook.js.map +1 -1
  44. package/dist/commands/login.d.ts +34 -0
  45. package/dist/commands/login.d.ts.map +1 -0
  46. package/dist/commands/login.js +74 -0
  47. package/dist/commands/login.js.map +1 -0
  48. package/dist/commands/map.d.ts +21 -0
  49. package/dist/commands/map.d.ts.map +1 -0
  50. package/dist/commands/map.js +76 -0
  51. package/dist/commands/map.js.map +1 -0
  52. package/dist/commands/notify-flush.d.ts.map +1 -1
  53. package/dist/commands/notify-flush.js +7 -1
  54. package/dist/commands/notify-flush.js.map +1 -1
  55. package/dist/commands/posture.d.ts +21 -0
  56. package/dist/commands/posture.d.ts.map +1 -0
  57. package/dist/commands/posture.js +177 -0
  58. package/dist/commands/posture.js.map +1 -0
  59. package/dist/commands/receipt-serve.d.ts +7 -0
  60. package/dist/commands/receipt-serve.d.ts.map +1 -1
  61. package/dist/commands/receipt-serve.js +50 -0
  62. package/dist/commands/receipt-serve.js.map +1 -1
  63. package/dist/commands/start.d.ts.map +1 -1
  64. package/dist/commands/start.js +5 -1
  65. package/dist/commands/start.js.map +1 -1
  66. package/dist/commands/team.d.ts.map +1 -1
  67. package/dist/commands/team.js +30 -11
  68. package/dist/commands/team.js.map +1 -1
  69. package/dist/commands/wire-hooks.d.ts +5 -1
  70. package/dist/commands/wire-hooks.d.ts.map +1 -1
  71. package/dist/commands/wire-hooks.js +23 -8
  72. package/dist/commands/wire-hooks.js.map +1 -1
  73. package/dist/commands/wrap.d.ts +38 -1
  74. package/dist/commands/wrap.d.ts.map +1 -1
  75. package/dist/commands/wrap.js +82 -6
  76. package/dist/commands/wrap.js.map +1 -1
  77. package/dist/config.d.ts +2 -0
  78. package/dist/config.d.ts.map +1 -1
  79. package/dist/config.js.map +1 -1
  80. package/dist/cta.d.ts +23 -0
  81. package/dist/cta.d.ts.map +1 -0
  82. package/dist/cta.js +86 -0
  83. package/dist/cta.js.map +1 -0
  84. package/dist/daily-slot.d.ts +2 -0
  85. package/dist/daily-slot.d.ts.map +1 -0
  86. package/dist/daily-slot.js +29 -0
  87. package/dist/daily-slot.js.map +1 -0
  88. package/dist/dash/dash.d.ts.map +1 -1
  89. package/dist/dash/dash.js +10 -0
  90. package/dist/dash/dash.js.map +1 -1
  91. package/dist/dash/entitlement.d.ts +1 -1
  92. package/dist/dash/entitlement.d.ts.map +1 -1
  93. package/dist/dash/entitlement.js +1 -0
  94. package/dist/dash/entitlement.js.map +1 -1
  95. package/dist/dash/input.d.ts +1 -1
  96. package/dist/dash/input.d.ts.map +1 -1
  97. package/dist/dash/input.js +3 -0
  98. package/dist/dash/input.js.map +1 -1
  99. package/dist/dash/render.js +1 -1
  100. package/dist/dash/render.js.map +1 -1
  101. package/dist/dash/screens/free.js +1 -1
  102. package/dist/dash/screens/free.js.map +1 -1
  103. package/dist/device-id.d.ts +5 -0
  104. package/dist/device-id.d.ts.map +1 -0
  105. package/dist/device-id.js +78 -0
  106. package/dist/device-id.js.map +1 -0
  107. package/dist/fs-atomic.d.ts +15 -3
  108. package/dist/fs-atomic.d.ts.map +1 -1
  109. package/dist/fs-atomic.js +31 -14
  110. package/dist/fs-atomic.js.map +1 -1
  111. package/dist/gate/config-gen.d.ts +26 -2
  112. package/dist/gate/config-gen.d.ts.map +1 -1
  113. package/dist/gate/config-gen.js +53 -4
  114. package/dist/gate/config-gen.js.map +1 -1
  115. package/dist/gate/otlp-receiver.d.ts.map +1 -1
  116. package/dist/gate/otlp-receiver.js +3 -1
  117. package/dist/gate/otlp-receiver.js.map +1 -1
  118. package/dist/guard-pack.d.ts +58 -0
  119. package/dist/guard-pack.d.ts.map +1 -0
  120. package/dist/guard-pack.js +753 -0
  121. package/dist/guard-pack.js.map +1 -0
  122. package/dist/ioc/exec.d.ts +19 -0
  123. package/dist/ioc/exec.d.ts.map +1 -0
  124. package/dist/ioc/exec.js +49 -0
  125. package/dist/ioc/exec.js.map +1 -0
  126. package/dist/ioc/format.d.ts +4 -0
  127. package/dist/ioc/format.d.ts.map +1 -0
  128. package/dist/ioc/format.js +23 -0
  129. package/dist/ioc/format.js.map +1 -0
  130. package/dist/ioc/list.d.ts +29 -0
  131. package/dist/ioc/list.d.ts.map +1 -0
  132. package/dist/ioc/list.js +25 -0
  133. package/dist/ioc/list.js.map +1 -0
  134. package/dist/ioc/result.d.ts +18 -0
  135. package/dist/ioc/result.d.ts.map +1 -0
  136. package/dist/ioc/result.js +26 -0
  137. package/dist/ioc/result.js.map +1 -0
  138. package/dist/ioc/scan.d.ts +21 -0
  139. package/dist/ioc/scan.d.ts.map +1 -0
  140. package/dist/ioc/scan.js +247 -0
  141. package/dist/ioc/scan.js.map +1 -0
  142. package/dist/ioc/spawn.d.ts +26 -0
  143. package/dist/ioc/spawn.d.ts.map +1 -0
  144. package/dist/ioc/spawn.js +52 -0
  145. package/dist/ioc/spawn.js.map +1 -0
  146. package/dist/login/credentials.d.ts +17 -0
  147. package/dist/login/credentials.d.ts.map +1 -0
  148. package/dist/login/credentials.js +64 -0
  149. package/dist/login/credentials.js.map +1 -0
  150. package/dist/login/device-flow.d.ts +44 -0
  151. package/dist/login/device-flow.d.ts.map +1 -0
  152. package/dist/login/device-flow.js +205 -0
  153. package/dist/login/device-flow.js.map +1 -0
  154. package/dist/map/build.d.ts +58 -0
  155. package/dist/map/build.d.ts.map +1 -0
  156. package/dist/map/build.js +439 -0
  157. package/dist/map/build.js.map +1 -0
  158. package/dist/map/heat.d.ts +44 -0
  159. package/dist/map/heat.d.ts.map +1 -0
  160. package/dist/map/heat.js +96 -0
  161. package/dist/map/heat.js.map +1 -0
  162. package/dist/map/load.d.ts +38 -0
  163. package/dist/map/load.d.ts.map +1 -0
  164. package/dist/map/load.js +38 -0
  165. package/dist/map/load.js.map +1 -0
  166. package/dist/map/page.d.ts +90 -0
  167. package/dist/map/page.d.ts.map +1 -0
  168. package/dist/map/page.js +374 -0
  169. package/dist/map/page.js.map +1 -0
  170. package/dist/map/target-class.d.ts +22 -0
  171. package/dist/map/target-class.d.ts.map +1 -0
  172. package/dist/map/target-class.js +151 -0
  173. package/dist/map/target-class.js.map +1 -0
  174. package/dist/map/types.d.ts +102 -0
  175. package/dist/map/types.d.ts.map +1 -0
  176. package/dist/map/types.js +3 -0
  177. package/dist/map/types.js.map +1 -0
  178. package/dist/mcp/protocol.d.ts.map +1 -1
  179. package/dist/mcp/protocol.js +16 -5
  180. package/dist/mcp/protocol.js.map +1 -1
  181. package/dist/never-code.d.ts +7 -0
  182. package/dist/never-code.d.ts.map +1 -0
  183. package/dist/never-code.js +9 -0
  184. package/dist/never-code.js.map +1 -0
  185. package/dist/never-list-input.d.ts +92 -0
  186. package/dist/never-list-input.d.ts.map +1 -0
  187. package/dist/never-list-input.js +1889 -0
  188. package/dist/never-list-input.js.map +1 -0
  189. package/dist/notify/dispatch.d.ts +4 -0
  190. package/dist/notify/dispatch.d.ts.map +1 -1
  191. package/dist/notify/dispatch.js +3 -1
  192. package/dist/notify/dispatch.js.map +1 -1
  193. package/dist/offline-evaluate.d.ts +42 -5
  194. package/dist/offline-evaluate.d.ts.map +1 -1
  195. package/dist/offline-evaluate.js +96 -9
  196. package/dist/offline-evaluate.js.map +1 -1
  197. package/dist/otel/exporter.d.ts +15 -2
  198. package/dist/otel/exporter.d.ts.map +1 -1
  199. package/dist/otel/exporter.js +52 -6
  200. package/dist/otel/exporter.js.map +1 -1
  201. package/dist/otel/map-attrs-optin.d.ts +39 -0
  202. package/dist/otel/map-attrs-optin.d.ts.map +1 -0
  203. package/dist/otel/map-attrs-optin.js +109 -0
  204. package/dist/otel/map-attrs-optin.js.map +1 -0
  205. package/dist/otel.d.ts +8 -2
  206. package/dist/otel.d.ts.map +1 -1
  207. package/dist/otel.js +32 -16
  208. package/dist/otel.js.map +1 -1
  209. package/dist/parse-args.d.ts +2 -0
  210. package/dist/parse-args.d.ts.map +1 -1
  211. package/dist/parse-args.js +4 -2
  212. package/dist/parse-args.js.map +1 -1
  213. package/dist/posture/card.d.ts +26 -0
  214. package/dist/posture/card.d.ts.map +1 -0
  215. package/dist/posture/card.js +46 -0
  216. package/dist/posture/card.js.map +1 -0
  217. package/dist/posture/collect.d.ts +19 -0
  218. package/dist/posture/collect.d.ts.map +1 -0
  219. package/dist/posture/collect.js +182 -0
  220. package/dist/posture/collect.js.map +1 -0
  221. package/dist/posture/send.d.ts +24 -0
  222. package/dist/posture/send.d.ts.map +1 -0
  223. package/dist/posture/send.js +162 -0
  224. package/dist/posture/send.js.map +1 -0
  225. package/dist/posture/spawn.d.ts +20 -0
  226. package/dist/posture/spawn.d.ts.map +1 -0
  227. package/dist/posture/spawn.js +33 -0
  228. package/dist/posture/spawn.js.map +1 -0
  229. package/dist/posture/store.d.ts +34 -0
  230. package/dist/posture/store.d.ts.map +1 -0
  231. package/dist/posture/store.js +107 -0
  232. package/dist/posture/store.js.map +1 -0
  233. package/dist/posture/validate.d.ts +33 -0
  234. package/dist/posture/validate.d.ts.map +1 -0
  235. package/dist/posture/validate.js +232 -0
  236. package/dist/posture/validate.js.map +1 -0
  237. package/dist/project-policy.d.ts +23 -0
  238. package/dist/project-policy.d.ts.map +1 -0
  239. package/dist/project-policy.js +95 -0
  240. package/dist/project-policy.js.map +1 -0
  241. package/dist/receipt/daemon.d.ts +9 -9
  242. package/dist/receipt/daemon.d.ts.map +1 -1
  243. package/dist/receipt/daemon.js +26 -11
  244. package/dist/receipt/daemon.js.map +1 -1
  245. package/dist/receipt/embeddings.d.ts +29 -7
  246. package/dist/receipt/embeddings.d.ts.map +1 -1
  247. package/dist/receipt/embeddings.js +282 -33
  248. package/dist/receipt/embeddings.js.map +1 -1
  249. package/dist/receipt/gate-page.d.ts.map +1 -1
  250. package/dist/receipt/gate-page.js +5 -22
  251. package/dist/receipt/gate-page.js.map +1 -1
  252. package/dist/receipt/live-server.d.ts +8 -0
  253. package/dist/receipt/live-server.d.ts.map +1 -1
  254. package/dist/receipt/live-server.js +136 -4
  255. package/dist/receipt/live-server.js.map +1 -1
  256. package/dist/receipt/render-receipt.d.ts +7 -1
  257. package/dist/receipt/render-receipt.d.ts.map +1 -1
  258. package/dist/receipt/render-receipt.js +101 -13
  259. package/dist/receipt/render-receipt.js.map +1 -1
  260. package/dist/receipt/search.d.ts +5 -0
  261. package/dist/receipt/search.d.ts.map +1 -1
  262. package/dist/receipt/search.js +23 -2
  263. package/dist/receipt/search.js.map +1 -1
  264. package/dist/receipt/semantic-setup.d.ts +21 -0
  265. package/dist/receipt/semantic-setup.d.ts.map +1 -0
  266. package/dist/receipt/semantic-setup.js +111 -0
  267. package/dist/receipt/semantic-setup.js.map +1 -0
  268. package/dist/receipt/semantic-status.d.ts +7 -0
  269. package/dist/receipt/semantic-status.d.ts.map +1 -0
  270. package/dist/receipt/semantic-status.js +26 -0
  271. package/dist/receipt/semantic-status.js.map +1 -0
  272. package/dist/sdk/govern.d.ts.map +1 -1
  273. package/dist/sdk/govern.js +7 -3
  274. package/dist/sdk/govern.js.map +1 -1
  275. package/dist/telemetry.d.ts.map +1 -1
  276. package/dist/telemetry.js +3 -23
  277. package/dist/telemetry.js.map +1 -1
  278. package/dist/trail-map-fields.d.ts +10 -0
  279. package/dist/trail-map-fields.d.ts.map +1 -0
  280. package/dist/trail-map-fields.js +53 -0
  281. package/dist/trail-map-fields.js.map +1 -0
  282. package/dist/trail-summary.d.ts.map +1 -1
  283. package/dist/trail-summary.js +11 -3
  284. package/dist/trail-summary.js.map +1 -1
  285. package/dist/trail.d.ts +13 -1
  286. package/dist/trail.d.ts.map +1 -1
  287. package/dist/trail.js +38 -1
  288. package/dist/trail.js.map +1 -1
  289. package/droid/README.md +1 -1
  290. package/droid/mcp.example.json +1 -1
  291. package/gemini/settings.example.json +1 -1
  292. package/grok/README.md +1 -1
  293. package/kilo/kilo.example.json +1 -1
  294. package/kimi/mcp.example.json +1 -1
  295. package/kiro/mcp.example.json +1 -1
  296. package/manifest.json +1 -1
  297. package/mastracode/mcp.example.json +1 -1
  298. package/mcp.json +1 -1
  299. package/openai/codex.config.example.toml +1 -1
  300. package/opencode/opencode.example.json +1 -1
  301. package/package.json +8 -7
  302. package/qwen/settings.example.json +1 -1
  303. package/server.json +2 -2
  304. package/vendor/cytoscape/LICENSE +19 -0
  305. package/vendor/cytoscape/README.md +7 -0
  306. package/vendor/cytoscape/cytoscape.min.js +31 -0
@@ -0,0 +1,26 @@
1
+ /**
2
+ * kya doctor - local checks. `--iocs` runs the IoC scan now and stores the result; without it the
3
+ * last stored result is shown. Advisory: exit code is 0 whatever the findings.
4
+ */
5
+ import { iocEnabled } from "../ioc/spawn.js";
6
+ import { iocLines } from "../ioc/format.js";
7
+ import { readIocResult } from "../ioc/result.js";
8
+ import { runIocScanAndStore } from "../ioc/scan.js";
9
+ import { optInHint } from "../otel/map-attrs-optin.js";
10
+ export async function runDoctor(log, opts) {
11
+ // OTLP map-attribute opt-in that a check refuses: one line on stderr, so stdout (and --json) stays the same.
12
+ const hint = opts.warn ? optInHint(opts.cwd) : undefined;
13
+ if (hint)
14
+ opts.warn(hint);
15
+ const result = opts.iocs ? await runIocScanAndStore(opts.env) : readIocResult(opts.env);
16
+ const enabled = iocEnabled(opts.env);
17
+ if (opts.json) {
18
+ log(JSON.stringify({ iocs: { enabled, ran: opts.iocs, result: result ?? null } }, null, 2));
19
+ }
20
+ else {
21
+ for (const line of iocLines(result, enabled))
22
+ log(line);
23
+ }
24
+ return 0;
25
+ }
26
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAEvD,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,GAA2B,EAC3B,IAAwJ;IAExJ,6GAA6G;IAC7G,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACzD,IAAI,IAAI;QAAE,IAAI,CAAC,IAAK,CAAC,IAAI,CAAC,CAAC;IAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxF,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,IAAI,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9F,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import type { ResolvedConfig } from "../config.js";
2
2
  import { KyaHttpClient, type PolicyEvaluateResponse } from "../client.js";
3
+ import type { GuardContext } from "../guard-pack.js";
3
4
  import type { ParsedArgs } from "../parse-args.js";
4
5
  export interface EvalToolResult {
5
6
  readonly response: PolicyEvaluateResponse;
@@ -15,6 +16,8 @@ export declare function runEvalTool(config: ResolvedConfig, input: {
15
16
  approvalStatus?: string;
16
17
  sandboxId?: string;
17
18
  offline?: boolean;
19
+ /** Guard pack context (cwd, home, env). Defaults to the process cwd and environment. */
20
+ guard?: GuardContext;
18
21
  }, client?: KyaHttpClient): Promise<EvalToolResult>;
19
22
  export declare function evalToolInputFromArgs(parsed: ParsedArgs): {
20
23
  toolId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"eval-tool.d.ts","sourceRoot":"","sources":["../../src/commands/eval-tool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAEL,aAAa,EACb,KAAK,sBAAsB,EAC5B,MAAM,cAAc,CAAC;AAKtB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,CAAC;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE;IACL,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,EACD,MAAM,CAAC,EAAE,aAAa,GACrB,OAAO,CAAC,cAAc,CAAC,CAwDzB;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,UAAU,GAAG;IACzD,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CAClB,CA8BA;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAc9D"}
1
+ {"version":3,"file":"eval-tool.d.ts","sourceRoot":"","sources":["../../src/commands/eval-tool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAEL,aAAa,EACb,KAAK,sBAAsB,EAC5B,MAAM,cAAc,CAAC;AAGtB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAIrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,CAAC;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAsB,WAAW,CAC/B,MAAM,EAAE,cAAc,EACtB,KAAK,EAAE;IACL,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wFAAwF;IACxF,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB,EACD,MAAM,CAAC,EAAE,aAAa,GACrB,OAAO,CAAC,cAAc,CAAC,CA8DzB;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,UAAU,GAAG;IACzD,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CAClB,CA8BA;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAc9D"}
@@ -1,6 +1,7 @@
1
1
  import { buildEvaluateFromToolArgs, KyaHttpClient, } from "../client.js";
2
2
  import { UsageError } from "../errors.js";
3
3
  import { evaluateOffline } from "../offline-evaluate.js";
4
+ import { loadProjectPolicy } from "../project-policy.js";
4
5
  import { deriveWireChangeFields } from "../diff-preview.js";
5
6
  import { findSampleTool } from "../sample-tools.js";
6
7
  import { flagBool, flagString } from "../parse-args.js";
@@ -27,7 +28,7 @@ export async function runEvalTool(config, input, client) {
27
28
  ? { ...req, actionClass, dataClass: sample?.dataClass }
28
29
  : req;
29
30
  if (input.offline || config.offline) {
30
- const response = evaluateOffline(request, config.host);
31
+ const response = evaluateOffline(request, config.host, input.args, loadProjectPolicy(config.cwd), input.guard);
31
32
  return {
32
33
  response,
33
34
  toolId,
@@ -1 +1 @@
1
- {"version":3,"file":"eval-tool.js","sourceRoot":"","sources":["../../src/commands/eval-tool.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"eval-tool.js","sourceRoot":"","sources":["../../src/commands/eval-tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { type ParsedArgs } from "../parse-args.js";
2
+ import type { TrailEventLike } from "../map/types.js";
3
+ export declare const EXPORT_FORMATS: readonly ["agent-flow"];
4
+ export type ExportFormat = (typeof EXPORT_FORMATS)[number];
5
+ export interface ExportOptions {
6
+ readonly format: ExportFormat;
7
+ readonly days: number;
8
+ readonly session?: string;
9
+ readonly out?: string;
10
+ /** Replace an existing --out file. */
11
+ readonly force: boolean;
12
+ }
13
+ export declare function exportOptionsFromArgs(parsed: ParsedArgs): ExportOptions;
14
+ export interface AgentFlowEvent {
15
+ time: number;
16
+ type: "agent_spawn" | "tool_call_start" | "tool_call_end";
17
+ payload: Record<string, string>;
18
+ }
19
+ /** A third-party MCP tool name can be any length. A longer one is replaced by its hash: a cut could keep a secret-shaped prefix. */
20
+ export declare const TOOL_MAX = 200;
21
+ export declare function toolLabel(toolId: string): string;
22
+ /** JSON.stringify keeps U+2028 and U+2029 raw. Readers that split lines on them (readline) would break the line. */
23
+ export declare function jsonLine(value: unknown): string;
24
+ /**
25
+ * Pure mapper. Rows are ordered by time, then by file order, so the same trail gives the same bytes.
26
+ * One `agent_spawn` per session at its first row, then a start and an end event per row at the same time.
27
+ */
28
+ export declare function toAgentFlow(events: readonly TrailEventLike[], salt: string): AgentFlowEvent[];
29
+ export declare function runExport(opts: ExportOptions, io: {
30
+ log: (line: string) => void;
31
+ error: (line: string) => void;
32
+ }, cwd: string, env: NodeJS.ProcessEnv): Promise<number>;
33
+ //# sourceMappingURL=export.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../src/commands/export.ts"],"names":[],"mappings":"AAWA,OAAO,EAAwB,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAIzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAItD,eAAO,MAAM,cAAc,yBAA0B,CAAC;AACtD,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,UAAU,GAAG,aAAa,CAevE;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,GAAG,iBAAiB,GAAG,eAAe,CAAC;IAC1D,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAGD,oIAAoI;AACpI,eAAO,MAAM,QAAQ,MAAM,CAAC;AAE5B,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,oHAAoH;AACpH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAE/C;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,CA+B7F;AAGD,wBAAsB,SAAS,CAC7B,IAAI,EAAE,aAAa,EACnB,EAAE,EAAE;IAAE,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,EAClE,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,CAAC,UAAU,GACrB,OAAO,CAAC,MAAM,CAAC,CAgCjB"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * `kya export --format agent-flow`: the local trail as an agent-flow JSONL event log. Local only. Never changes a verdict.
3
+ * Each line is `{"time": <s since the first row>, "type": ..., "payload": {...}}`. The payload holds only a hashed session,
4
+ * the tool id, the verdict, the reason code, the target class, the device id and the mode. No args, hashes or paths.
5
+ */
6
+ import { createHash, randomBytes } from "node:crypto";
7
+ import { dirname, resolve } from "node:path";
8
+ import { installSalt } from "../device-id.js";
9
+ import { UsageError } from "../errors.js";
10
+ import { writeFileSync } from "node:fs";
11
+ import { ensureOutDir, projectWritePath, underRoot, writeOutFile } from "../fs-atomic.js";
12
+ import { flagBool, flagString } from "../parse-args.js";
13
+ import { sessionHash, targetOf } from "../map/build.js";
14
+ import { loadTrailEvents } from "../map/load.js";
15
+ import { scanMapOutput } from "../map/page.js";
16
+ import { trailPath } from "../trail.js";
17
+ import { daysFromArgs } from "./map.js";
18
+ export const EXPORT_FORMATS = ["agent-flow"];
19
+ export function exportOptionsFromArgs(parsed) {
20
+ const format = parsed.flags["format"];
21
+ if (typeof format !== "string" || !EXPORT_FORMATS.includes(format)) {
22
+ throw new UsageError(`--format must be one of: ${EXPORT_FORMATS.join(", ")} (for example --format agent-flow)`);
23
+ }
24
+ const days = daysFromArgs(parsed);
25
+ if (parsed.flags["session"] === true)
26
+ throw new UsageError("--session needs a session id");
27
+ if (parsed.flags["out"] === true)
28
+ throw new UsageError("--out needs a file path, for example --out flow.jsonl");
29
+ return {
30
+ format: format,
31
+ days,
32
+ session: flagString(parsed.flags, "session"),
33
+ out: flagString(parsed.flags, "out"),
34
+ force: flagBool(parsed.flags, "force"),
35
+ };
36
+ }
37
+ const DEVICE_ID = /^[0-9a-f]{16}$/;
38
+ /** A third-party MCP tool name can be any length. A longer one is replaced by its hash: a cut could keep a secret-shaped prefix. */
39
+ export const TOOL_MAX = 200;
40
+ export function toolLabel(toolId) {
41
+ return toolId.length <= TOOL_MAX ? toolId : `tool:${createHash("sha256").update(toolId, "utf8").digest("hex").slice(0, 16)}`;
42
+ }
43
+ /** JSON.stringify keeps U+2028 and U+2029 raw. Readers that split lines on them (readline) would break the line. */
44
+ export function jsonLine(value) {
45
+ return JSON.stringify(value).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
46
+ }
47
+ /**
48
+ * Pure mapper. Rows are ordered by time, then by file order, so the same trail gives the same bytes.
49
+ * One `agent_spawn` per session at its first row, then a start and an end event per row at the same time.
50
+ */
51
+ export function toAgentFlow(events, salt) {
52
+ const rows = events
53
+ .map((e, i) => ({ e, i, ms: Date.parse(e.ts) }))
54
+ .filter((r) => Number.isFinite(r.ms))
55
+ .sort((a, b) => a.ms - b.ms || a.i - b.i);
56
+ if (rows.length === 0)
57
+ return [];
58
+ const t0 = rows[0].ms;
59
+ const seen = new Set();
60
+ const out = [];
61
+ for (const { e, ms } of rows) {
62
+ const time = (ms - t0) / 1000;
63
+ const agent = sessionHash(salt, e.product ?? "unknown", e.sessionId);
64
+ const device = typeof e.deviceId === "string" && DEVICE_ID.test(e.deviceId) ? { deviceId: e.deviceId } : {};
65
+ if (!seen.has(agent)) {
66
+ seen.add(agent);
67
+ out.push({ time, type: "agent_spawn", payload: { name: agent, sessionId: agent, ...device } });
68
+ }
69
+ const call = {
70
+ agent,
71
+ sessionId: agent,
72
+ tool: toolLabel(e.toolId),
73
+ verdict: e.verdict,
74
+ reasonCode: e.reasonCode,
75
+ targetClass: targetOf(e).cls,
76
+ mode: e.mode,
77
+ ...device,
78
+ };
79
+ out.push({ time, type: "tool_call_start", payload: call });
80
+ out.push({ time, type: "tool_call_end", payload: call });
81
+ }
82
+ return out;
83
+ }
84
+ export async function runExport(opts, io, cwd, env) {
85
+ const salt = installSalt(env) ?? randomBytes(16).toString("hex");
86
+ const { events } = await loadTrailEvents({ path: trailPath(cwd, env), days: opts.days, now: new Date(), session: opts.session });
87
+ const lines = toAgentFlow(events, salt).map(jsonLine);
88
+ if (lines.length === 0) {
89
+ io.error(`No events in the last ${opts.days} days. Nothing to export.`);
90
+ return 0;
91
+ }
92
+ const body = `${lines.join("\n")}\n`;
93
+ scanMapOutput(body);
94
+ if (opts.out === undefined) {
95
+ io.log(body.trimEnd());
96
+ return 0;
97
+ }
98
+ const target = resolve(cwd, opts.out);
99
+ // The project root already exists. ensureOutDir would check the root's parent and refuse it.
100
+ if (resolve(dirname(target)) !== resolve(cwd))
101
+ ensureOutDir(dirname(target), cwd);
102
+ if (opts.force) {
103
+ // Atomic replace, owner read and write only, also when the old file was wider. A link at the target is replaced, not followed.
104
+ writeOutFile(target, body, cwd, 0o600);
105
+ }
106
+ else {
107
+ // Exclusive create: no window between a check and the write, and an existing file or symlink is never replaced.
108
+ const dest = underRoot(target, cwd) ? projectWritePath(target, cwd) : target;
109
+ try {
110
+ writeFileSync(dest, body, { flag: "wx", mode: 0o600 });
111
+ }
112
+ catch (err) {
113
+ if (err.code === "EEXIST")
114
+ throw new UsageError(`${target} exists. Pass --force to replace it.`);
115
+ throw err;
116
+ }
117
+ }
118
+ io.error(`${lines.length} lines written to ${target}`);
119
+ return 0;
120
+ }
121
+ //# sourceMappingURL=export.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export.js","sourceRoot":"","sources":["../../src/commands/export.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../src/commands/hook.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAO3D,OAAO,EAAoH,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEzK,sFAAsF;AACtF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,4FAA4F;IAC5F,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,4EAA4E;IAC5E,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC,iDAAiD;IACjD,QAAQ,CAAC,KAAK,CAAC,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,qGAAqG;IACrG,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,8GAA8G;IAC9G,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACvF,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,CAAC,EAAE,iBAAiB,CAAC;CACpC;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,gGAAgG;IAChG,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC9B;AAwND,wBAAsB,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CA4GnE"}
1
+ {"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../src/commands/hook.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAW3D,OAAO,EAAoH,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEzK,sFAAsF;AACtF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,4FAA4F;IAC5F,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,4EAA4E;IAC5E,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC,iDAAiD;IACjD,QAAQ,CAAC,KAAK,CAAC,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,qGAAqG;IACrG,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,8GAA8G;IAC9G,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACvF,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,CAAC,EAAE,iBAAiB,CAAC;CACpC;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,gGAAgG;IAChG,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC9B;AAyRD,wBAAsB,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CA2HnE"}
@@ -3,7 +3,7 @@
3
3
  * (Claude Code, Codex, Grok, Kimi Code; Gemini CLI BeforeTool). Default: offline local evaluate only, no
4
4
  * network, sub-second, fail-open on any internal error unless --fail-closed.
5
5
  * DENY (local never-list) blocks; REQUIRE_APPROVE records advisory unless
6
- * --strict. With --plane-config (beta) it evaluates on the hosted plane and
6
+ * --strict. With --plane-config (preview) it evaluates on the hosted plane and
7
7
  * fails closed (runHostedHook below; --plane-shadow records without blocking).
8
8
  */
9
9
  import { createHash } from "node:crypto";
@@ -12,8 +12,12 @@ import { isAbsolute, join } from "node:path";
12
12
  import { configFilePath, globalConfigDir, resolveConfig } from "../config.js";
13
13
  import { runEvalTool } from "./eval-tool.js";
14
14
  import { appendTrail, defaultSessionId, hostToProduct } from "../trail.js";
15
+ import { trailMapFields } from "../trail-map-fields.js";
15
16
  import { deriveWireChangeFields } from "../diff-preview.js";
16
17
  import { matchesNeverList } from "../offline-evaluate.js";
18
+ import { neverListInputMatch } from "../never-list-input.js";
19
+ import { GUARD_DEFAULTS, guardContextFrom, guardHint, guardPackMatch, readGuardConfig } from "../guard-pack.js";
20
+ import { isNeverCode } from "../never-code.js";
17
21
  import { maybeSpawnNotifyFlush } from "../notify/dispatch.js";
18
22
  import { computeArgsHash } from "../hash.js";
19
23
  import { evaluateHosted, hostedDecision, hostedEnvProblem, loadPlaneConfig, PlaneError, scrubNetworkEnv } from "./hosted-hook.js";
@@ -54,7 +58,23 @@ function geminiMcpToolId(raw) {
54
58
  const isBeforeTool = (event) => /^BeforeTool$/i.test(event ?? "");
55
59
  /** Gemini CLI reads the decision from stdout JSON (`decision`), not hookSpecificOutput: `--host gemini` or a BeforeTool payload. */
56
60
  const geminiShape = (input, p) => input.host.trim().toLowerCase() === "gemini" || isBeforeTool(p?.event);
57
- /** Accept snake_case (Claude/Kimi) and camelCase (Grok) envelopes. */
61
+ /**
62
+ * Copilot CLI camelCase preToolUse sends `toolArgs` as a JSON string. Parse it so the
63
+ * input rules and the trail see an object; a bad string stays a string (the rules then
64
+ * fail open, as for any unparseable input). No size cap: the whole payload was already
65
+ * parsed above, and a cap here would let padding turn a long command into an allow.
66
+ */
67
+ function parseToolArgs(v) {
68
+ if (typeof v !== "string")
69
+ return v;
70
+ try {
71
+ return JSON.parse(v);
72
+ }
73
+ catch {
74
+ return v;
75
+ }
76
+ }
77
+ /** Accept snake_case (Claude/Kimi) and camelCase (Grok, Copilot) envelopes. */
58
78
  function parsePayload(stdinText) {
59
79
  let raw;
60
80
  try {
@@ -87,11 +107,27 @@ function parsePayload(stdinText) {
87
107
  toolUseId: (typeof p.tool_use_id === "string" && p.tool_use_id) ||
88
108
  (typeof p.toolUseId === "string" && p.toolUseId) ||
89
109
  undefined,
90
- toolInput: p.tool_input ?? p.toolInput,
110
+ toolInput: p.tool_input ?? p.toolInput ?? parseToolArgs(p.toolArgs),
91
111
  usage: readUsageShape(p.usage) ?? readUsageShape(toolResponse?.usage),
92
112
  };
93
113
  }
94
114
  const ALLOW = { exitCode: 0, stdout: "", stderr: "" };
115
+ /**
116
+ * Deny text. An input-rule hit names its rule id; the never-list cannot be overridden. A guard pack
117
+ * hit names its rule id and says what to do instead. It does not say where the allowlist lives: that file
118
+ * is writable by the agent, so the text points at the docs for the person. Never carries command text,
119
+ * a path or a matched secret.
120
+ */
121
+ function denyReason(toolName, reasonCode, ruleId) {
122
+ if (reasonCode === "NEVER_EVENT" && ruleId) {
123
+ return `KYA denied ${toolName}: NEVER_EVENT (rule ${ruleId}; never-list rules cannot be overridden)`;
124
+ }
125
+ if (isNeverCode(reasonCode) && reasonCode !== "NEVER_EVENT" && ruleId) {
126
+ const hint = guardHint(ruleId);
127
+ return `KYA denied ${toolName}: ${reasonCode} (${ruleId}).${hint ? ` ${hint}` : ""} Ask the user; see docs/guard-pack.md.`;
128
+ }
129
+ return `KYA denied ${toolName}: ${reasonCode}`;
130
+ }
95
131
  function deny(reason, gemini = false) {
96
132
  // Gemini parses stdout JSON whatever the exit code, and a JSON body without `decision` means allow.
97
133
  const body = gemini
@@ -181,7 +217,7 @@ function withTimeout(p, ms) {
181
217
  * deduped by the tool_use_id claim: the other hook copy may have recorded an
182
218
  * ALLOW, and the trail must also show that this copy blocked the call.
183
219
  */
184
- function auditedDeny(reason, reasonCode, input, payload, dedupe = false) {
220
+ function auditedDeny(reason, reasonCode, input, payload, dedupe = false, ruleId) {
185
221
  try {
186
222
  // Only for NEVER_EVENT: every hook copy reaches the same never-list verdict,
187
223
  // so the claim only collapses duplicate rows/notifies and never the verdict.
@@ -198,17 +234,50 @@ function auditedDeny(reason, reasonCode, input, payload, dedupe = false) {
198
234
  verdict: "DENY",
199
235
  reasonCode,
200
236
  mode: "offline",
201
- neverEvent: reasonCode === "NEVER_EVENT",
237
+ neverEvent: isNeverCode(reasonCode),
238
+ ...(ruleId ? { neverRule: ruleId } : {}),
239
+ ...trailMapFields(payload?.toolName ?? "unknown", payload?.toolInput, trailCwd, input.env),
202
240
  };
203
241
  try {
204
242
  appendTrail(trailCwd, ev, input.env);
205
243
  }
206
244
  catch { /* audit is best effort */ }
207
- maybeSpawnNotifyFlush({ env: input.env, cwd: trailCwd, event: ev });
245
+ maybeSpawnNotifyFlush({ env: input.env, cwd: trailCwd, event: ev, projectDir: trailCwd });
208
246
  }
209
247
  catch { /* never block the deny itself */ }
210
248
  return deny(reason, geminiShape(input, payload));
211
249
  }
250
+ /** cwd and env for the guard pack: the host's cwd when it sent an absolute one, else the hook's. */
251
+ function guardContextFor(payload, input) {
252
+ const c = payload?.cwd?.trim();
253
+ return guardContextFrom(c && isAbsolute(c) ? c : input.cwd, input.env);
254
+ }
255
+ /**
256
+ * A malformed guard config falls back to the defaults. Say so once an hour in the trail, so a person
257
+ * who edited `~/.kya/config.json` and sees no effect can find out why. Never throws.
258
+ */
259
+ function noteGuardConfigProblem(ctx, input, payload) {
260
+ try {
261
+ const { problem } = readGuardConfig(ctx.home);
262
+ if (!problem)
263
+ return;
264
+ const hour = new Date().toISOString().slice(0, 13);
265
+ if (!claimToolUse(`guard-config:${hour}`, undefined, input.env))
266
+ return;
267
+ appendTrail(payload?.cwd?.trim() || input.cwd, {
268
+ ts: new Date().toISOString(),
269
+ sessionId: payload?.sessionId ?? defaultSessionId(input.env),
270
+ host: "ide",
271
+ product: hostToProduct(input.host),
272
+ toolId: "kya:guard-config",
273
+ verdict: "ALLOW",
274
+ reasonCode: "GUARD_CONFIG_INVALID",
275
+ mode: "offline",
276
+ summary: `guard config ignored (${problem}); defaults in force`,
277
+ }, input.env);
278
+ }
279
+ catch { /* best effort */ }
280
+ }
212
281
  // Non-PreToolUse hook events that legitimately carry no gate decision.
213
282
  const OTHER_EVENT = /^(post[_-]?tool[_-]?use.*|stop|subagent[_-]?(start|stop)|permission[_-]?request|elicitation.*|session[_-]?(start|end)|user[_-]?prompt[_-]?submit|notification|pre[_-]?compact)$/i;
214
283
  export async function runHook(input) {
@@ -248,8 +317,10 @@ export async function runHook(input) {
248
317
  config = resolve({ host: "ide" });
249
318
  }
250
319
  const cfg = config;
320
+ const guardCtx = guardContextFor(payload, input);
321
+ noteGuardConfigProblem(guardCtx, input, payload);
251
322
  const evaluate = input.evaluate ??
252
- (async (toolId, args) => (await runEvalTool(cfg, { toolId, args, offline: true })).response);
323
+ (async (toolId, args) => (await runEvalTool(cfg, { toolId, args, offline: true, guard: guardCtx })).response);
253
324
  const evaluating = Promise.resolve().then(() => evaluate(toolName, payload?.toolInput ?? {}));
254
325
  const response = input.failClosed
255
326
  ? await withTimeout(evaluating, input.evalTimeoutMs ?? 4000)
@@ -261,9 +332,12 @@ export async function runHook(input) {
261
332
  // payload.cwd is host-supplied and only feeds the project-basename stamp;
262
333
  // the trail path itself comes from env/KYA_HOME - no traversal risk.
263
334
  const trailCwd = payload.cwd?.trim() || input.cwd;
335
+ // Map fields come from the raw input, before the secret strip below: a never deny or a secret read keeps its class.
336
+ const mapFields = trailMapFields(toolName, payload.toolInput ?? {}, trailCwd, input.env);
264
337
  // Wire change fields (summary, diffPreview, targetPath) feed the receipt's
265
338
  // Changes tab; redaction + opt-out live inside deriveWireChangeFields.
266
- const changeFields = deriveWireChangeFields(toolName, payload.toolInput ?? {}, input.env);
339
+ // A secret-shaped write is denied because its text is a secret: no preview of that text reaches the trail.
340
+ const changeFields = response.reasonCode === "NEVER_SECRET_WRITE" ? undefined : deriveWireChangeFields(toolName, payload.toolInput ?? {}, input.env);
267
341
  const trailEvent = {
268
342
  ts: new Date().toISOString(),
269
343
  sessionId: payload.sessionId ?? defaultSessionId(input.env),
@@ -273,8 +347,10 @@ export async function runHook(input) {
273
347
  verdict: response.verdict,
274
348
  reasonCode: response.reasonCode ?? "",
275
349
  mode: "offline",
276
- neverEvent: response.reasonCode === "NEVER_EVENT",
350
+ neverEvent: isNeverCode(response.reasonCode),
351
+ ...(response.ruleId ? { neverRule: response.ruleId } : {}),
277
352
  argsHash: response.argsHash,
353
+ ...mapFields,
278
354
  ...(changeFields ?? {}),
279
355
  ...(payload.usage?.tokensIn !== undefined ? { tokensIn: payload.usage.tokensIn } : {}),
280
356
  ...(payload.usage?.tokensOut !== undefined ? { tokensOut: payload.usage.tokensOut } : {}),
@@ -289,14 +365,14 @@ export async function runHook(input) {
289
365
  }
290
366
  // Webhooks + OTLP export ride a detached helper; the hook never waits on
291
367
  // the network. No-op unless a sink is configured.
292
- maybeSpawnNotifyFlush({ env: input.env, cwd: trailCwd, event: trailEvent });
368
+ maybeSpawnNotifyFlush({ env: input.env, cwd: trailCwd, event: trailEvent, projectDir: trailCwd });
293
369
  }
294
370
  }
295
371
  catch {
296
372
  /* observe path never breaks the gate */
297
373
  }
298
374
  if (response.verdict === "DENY") {
299
- return { ...deny(`KYA denied ${toolName}: ${response.reasonCode}`, geminiShape(input, payload)), firstSeen };
375
+ return { ...deny(denyReason(toolName, response.reasonCode, response.ruleId), geminiShape(input, payload)), firstSeen };
300
376
  }
301
377
  if (input.strict && response.verdict === "REQUIRE_APPROVE") {
302
378
  return { ...deny(`KYA strict mode: ${toolName} requires approval (${response.reasonCode})`, geminiShape(input, payload)), firstSeen };
@@ -311,8 +387,16 @@ export async function runHook(input) {
311
387
  // --fail-closed (hosted): enforcement must not silently lapse.
312
388
  try {
313
389
  // A never-list tool is logged as such in both modes (hosted counts stay right).
314
- if (payload?.toolName && matchesNeverList(payload.toolName)) {
315
- return auditedDeny(`KYA denied ${payload.toolName}: NEVER_EVENT`, "NEVER_EVENT", input, payload, true);
390
+ if (payload?.toolName) {
391
+ const inputHit = neverListInputMatch(payload.toolName, payload.toolInput, undefined, payload.cwd?.trim() || input.cwd);
392
+ if (inputHit || matchesNeverList(payload.toolName)) {
393
+ return auditedDeny(denyReason(payload.toolName, "NEVER_EVENT", inputHit?.rule), "NEVER_EVENT", input, payload, true, inputHit?.rule);
394
+ }
395
+ // Guard pack with its defaults: the fallback never reads config, so a broken or hostile one cannot lift a deny here.
396
+ const guardHit = guardPackMatch(payload.toolName, payload.toolInput, guardContextFor(payload, input), GUARD_DEFAULTS);
397
+ if (guardHit) {
398
+ return auditedDeny(denyReason(payload.toolName, guardHit.code, guardHit.rule), guardHit.code, input, payload, true, guardHit.rule);
399
+ }
316
400
  }
317
401
  }
318
402
  catch { /* fall through */ }
@@ -325,8 +409,10 @@ export async function runHook(input) {
325
409
  /** Env that steers the OSS hook and is ignored in hosted mode (design T2/T3). */
326
410
  const HOSTED_IGNORED_ENV = ["KYA_OFFLINE", "KYA_BASE_URL", "KYA_API_KEY", "SHIELD_API_KEY", "KYA_AGENT_ID", "KYA_HOME", "KYA_HOST", "KYA_NOTIFY_WEBHOOK", "KYA_OTLP_EXPORT_ENDPOINT"];
327
411
  /**
328
- * Hosted mode. Order: payload, local never-list, env and config checks, plane
329
- * call, then a raise-only merge in which the local never-list always wins.
412
+ * Hosted mode. Order: payload, local never-list, local guard pack, env and config checks, plane
413
+ * call, then a raise-only merge in which the local never-list, then the guard pack, always win.
414
+ * The guard pack has the same rules, codes and user-level config as the local hook; only the
415
+ * failure stance differs (hosted fails closed).
330
416
  * Every failure is a deny (fail-closed) unless --plane-shadow, which records
331
417
  * the would-be verdict and allows. Nothing here reads resolveConfig, the repo's
332
418
  * .kya/config.json or KYA_* env, so none of them can downgrade this path.
@@ -350,6 +436,8 @@ async function runHostedHook(input, plane) {
350
436
  stderrNotes.push("KYA hosted mode: KYA_* env and the project .kya/config.json are ignored");
351
437
  // Crash path state: unknown until the local never-list has been evaluated below.
352
438
  hostedDecision.neverList = "unknown";
439
+ hostedDecision.code = undefined;
440
+ hostedDecision.rule = undefined;
353
441
  let payload;
354
442
  let verdict;
355
443
  let response;
@@ -367,15 +455,28 @@ async function runHostedHook(input, plane) {
367
455
  }
368
456
  const toolName = payload?.toolName;
369
457
  let neverListed = false;
370
- // The local never-list runs first, before any env, config or plane code, and is stored so a
371
- // crash later can never lower it (crashDecision). A throw leaves it "unknown", which denies.
458
+ let neverRule;
459
+ let guardHit;
460
+ // The local never-list and the guard pack run first, before any env, config or plane code, and
461
+ // are stored so a crash later can never lower them (crashDecision). A throw leaves it "unknown",
462
+ // which denies. The guard config is the user-level file under the hosted $HOME only.
372
463
  try {
373
464
  if (toolName) {
374
- neverListed = matchesNeverList(toolName);
375
- hostedDecision.neverList = neverListed ? "deny" : "clear";
465
+ neverRule = neverListInputMatch(toolName, payload?.toolInput, undefined, payload?.cwd?.trim() || input.cwd)?.rule;
466
+ neverListed = matchesNeverList(toolName) || neverRule !== undefined;
467
+ if (!neverListed) {
468
+ const ctx = guardContextFor(payload, input);
469
+ guardHit = guardPackMatch(toolName, payload?.toolInput, ctx, readGuardConfig(ctx.home).config);
470
+ if (homeOk)
471
+ noteGuardConfigProblem(ctx, { ...input, env: stateEnv }, payload);
472
+ }
473
+ hostedDecision.neverList = neverListed || guardHit ? "deny" : "clear";
474
+ hostedDecision.code = neverListed ? "NEVER_EVENT" : guardHit?.code;
475
+ hostedDecision.rule = neverListed ? neverRule : guardHit?.rule;
376
476
  }
377
477
  }
378
478
  catch { /* stays unknown */ }
479
+ const localDeny = neverListed || guardHit !== undefined;
379
480
  if (!payload || !toolName) {
380
481
  verdict = {
381
482
  verdict: "DENY",
@@ -413,6 +514,7 @@ async function runHostedHook(input, plane) {
413
514
  now: plane.now,
414
515
  sleep: plane.sleep,
415
516
  random: plane.random,
517
+ withholdChange: guardHit?.code === "NEVER_SECRET_WRITE",
416
518
  });
417
519
  }
418
520
  catch (e) {
@@ -422,7 +524,10 @@ async function runHostedHook(input, plane) {
422
524
  }
423
525
  // Raise-only merge: the local never-list beats any plane answer or failure.
424
526
  if (neverListed) {
425
- verdict = { verdict: "DENY", reasonCode: "NEVER_EVENT", reason: `KYA denied ${toolName}: NEVER_EVENT`, dedupe: true };
527
+ verdict = { verdict: "DENY", reasonCode: "NEVER_EVENT", reason: denyReason(toolName, "NEVER_EVENT", neverRule), dedupe: true, ruleId: neverRule };
528
+ }
529
+ else if (guardHit) {
530
+ verdict = { verdict: "DENY", reasonCode: guardHit.code, reason: denyReason(toolName, guardHit.code, guardHit.rule), dedupe: true, ruleId: guardHit.rule };
426
531
  }
427
532
  else if (failure || !response) {
428
533
  const f = failure ?? { code: "FAIL_CLOSED", message: "internal error" };
@@ -442,9 +547,9 @@ async function runHostedHook(input, plane) {
442
547
  }
443
548
  const blocks = verdict.verdict === "DENY" ||
444
549
  (input.strict && verdict.verdict === "REQUIRE_APPROVE");
445
- // Shadow never blocks, except the LOCAL never-list. Keyed to the local evaluation, never to the
446
- // plane's reason code: the plane answers NEVER_EVENT for every registered DENY-tier tool.
447
- const enforce = blocks && (!plane.shadow || neverListed);
550
+ // Shadow never blocks, except the LOCAL never-list and guard pack. Keyed to the local evaluation,
551
+ // never to the plane's reason code: the plane answers NEVER_EVENT for every registered DENY-tier tool.
552
+ const enforce = blocks && (!plane.shadow || localDeny);
448
553
  let firstSeen = true;
449
554
  try {
450
555
  firstSeen = recordHostedRow(input, stateEnv, homeOk, home, payload, verdict, response, plane.shadow, configIgnored);
@@ -482,7 +587,8 @@ function recordHostedRow(input, stateEnv, homeOk, home, payload, verdict, respon
482
587
  let changeFields;
483
588
  try {
484
589
  argsHash ??= payload?.toolName ? computeArgsHash(payload.toolInput ?? {}) : undefined;
485
- changeFields = payload?.toolName ? deriveWireChangeFields(toolName, payload.toolInput ?? {}, input.env) : undefined;
590
+ // A secret-shaped write is denied because its text is a secret: no preview of that text reaches the trail.
591
+ changeFields = payload?.toolName && verdict.reasonCode !== "NEVER_SECRET_WRITE" ? deriveWireChangeFields(toolName, payload.toolInput ?? {}, input.env) : undefined;
486
592
  }
487
593
  catch { /* row without hash or preview */ }
488
594
  const ev = {
@@ -494,8 +600,10 @@ function recordHostedRow(input, stateEnv, homeOk, home, payload, verdict, respon
494
600
  verdict: verdict.verdict,
495
601
  reasonCode: verdict.reasonCode,
496
602
  mode: input.strict ? "hold" : "observe",
497
- neverEvent: verdict.reasonCode === "NEVER_EVENT",
603
+ neverEvent: isNeverCode(verdict.reasonCode),
604
+ ...(verdict.ruleId ? { neverRule: verdict.ruleId } : {}),
498
605
  ...(argsHash ? { argsHash } : {}),
606
+ ...trailMapFields(toolName, payload?.toolInput, payload?.cwd?.trim() || input.cwd, stateEnv),
499
607
  ...(changeFields ?? {}),
500
608
  ...(payload?.usage?.tokensIn !== undefined ? { tokensIn: payload.usage.tokensIn } : {}),
501
609
  ...(payload?.usage?.tokensOut !== undefined ? { tokensOut: payload.usage.tokensOut } : {}),
@@ -507,7 +615,8 @@ function recordHostedRow(input, stateEnv, homeOk, home, payload, verdict, respon
507
615
  }
508
616
  catch { /* best effort */ }
509
617
  // cwd = home: only the user-level notify config applies, never a repo's sinks.
510
- maybeSpawnNotifyFlush({ env: stateEnv, cwd: home, event: ev });
618
+ // projectDir is the call's project, so the map-attribute opt-in check sees the repo even though cwd is home.
619
+ maybeSpawnNotifyFlush({ env: stateEnv, cwd: home, event: ev, projectDir: payload?.cwd?.trim() || input.cwd });
511
620
  return true;
512
621
  }
513
622
  //# sourceMappingURL=hook.js.map