@wrongstack/core 0.265.1 → 0.268.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 (75) hide show
  1. package/dist/{agent-bridge-DrkBxszZ.d.ts → agent-bridge-UhojbpWx.d.ts} +1 -1
  2. package/dist/{agent-subagent-runner-DM2pP-B6.d.ts → agent-subagent-runner-Bvtf1o9K.d.ts} +25 -7
  3. package/dist/{brain-BXd_61kQ.d.ts → brain-69wzMKp1.d.ts} +73 -1
  4. package/dist/{compactor-B8pOf45Y.d.ts → compactor-CBQAJoDc.d.ts} +19 -1
  5. package/dist/{config-BMCj_XDs.d.ts → config-VKfOZ-6X.d.ts} +122 -3
  6. package/dist/{context-MRk5PhNv.d.ts → context-C0U8B9NF.d.ts} +88 -1
  7. package/dist/coordination/index.d.ts +57 -161
  8. package/dist/coordination/index.js +471 -177
  9. package/dist/coordination/index.js.map +1 -1
  10. package/dist/defaults/index.d.ts +26 -25
  11. package/dist/defaults/index.js +1818 -844
  12. package/dist/defaults/index.js.map +1 -1
  13. package/dist/execution/index.d.ts +72 -16
  14. package/dist/execution/index.js +1270 -265
  15. package/dist/execution/index.js.map +1 -1
  16. package/dist/execution/prompt-enhancer.d.ts +1 -1
  17. package/dist/extension/index.d.ts +7 -6
  18. package/dist/global-mailbox-KByEFFBa.d.ts +663 -0
  19. package/dist/{goal-preamble-DvHDSKSe.d.ts → goal-preamble-CrYjmdw4.d.ts} +28 -11
  20. package/dist/{goal-store-DtLMySNb.d.ts → goal-store-Y_zdLZ3q.d.ts} +1 -1
  21. package/dist/hq/index.d.ts +195 -0
  22. package/dist/hq/index.js +1884 -0
  23. package/dist/hq/index.js.map +1 -0
  24. package/dist/index-BfaS-f_m.d.ts +82 -0
  25. package/dist/{index-B-ch8K9C.d.ts → index-CtQnmkaS.d.ts} +8 -8
  26. package/dist/{index-CEDeNodM.d.ts → index-gCv830d7.d.ts} +5 -5
  27. package/dist/index.d.ts +124 -47
  28. package/dist/index.js +5600 -2662
  29. package/dist/index.js.map +1 -1
  30. package/dist/infrastructure/index.d.ts +6 -6
  31. package/dist/infrastructure/index.js +117 -19
  32. package/dist/infrastructure/index.js.map +1 -1
  33. package/dist/kernel/index.d.ts +10 -9
  34. package/dist/kernel/index.js.map +1 -1
  35. package/dist/{pipeline-DPDxH_7m.d.ts → mailbox-types-Ct2hJq0P.d.ts} +1 -244
  36. package/dist/{mcp-servers-2x4w6Jn9.d.ts → mcp-servers-HT3Fi7Bl.d.ts} +10 -4
  37. package/dist/models/index.d.ts +5 -5
  38. package/dist/models/index.js +33 -3
  39. package/dist/models/index.js.map +1 -1
  40. package/dist/{models-registry-DmJlKuNp.d.ts → models-registry-Bvcl3Vaa.d.ts} +1 -1
  41. package/dist/{multi-agent-coordinator-DyCkCZnU.d.ts → multi-agent-coordinator-BACjsmkC.d.ts} +1 -1
  42. package/dist/{null-fleet-bus-CG9QY2aP.d.ts → null-fleet-bus-DA7fvhUg.d.ts} +14 -9
  43. package/dist/observability/index.d.ts +2 -2
  44. package/dist/{parallel-eternal-engine-Jw9uhEoT.d.ts → parallel-eternal-engine-Ci71gYu_.d.ts} +11 -15
  45. package/dist/{path-resolver-Dy2ej-gE.d.ts → path-resolver-O1IJnmKE.d.ts} +4 -3
  46. package/dist/{permission-B9SB45lp.d.ts → permission-Bd-57Lbl.d.ts} +1 -1
  47. package/dist/{permission-policy-CkjSXabK.d.ts → permission-policy-uNXC6Kge.d.ts} +2 -3
  48. package/dist/pipeline-BDNvENyV.d.ts +245 -0
  49. package/dist/{plan-templates-CzD9GnAU.d.ts → plan-templates-EMsalEtN.d.ts} +5 -5
  50. package/dist/{llm-selector-C0tfTCUe.d.ts → provider-model-resolve-CEb9x886.d.ts} +40 -3
  51. package/dist/{provider-runner-DMa70ODu.d.ts → provider-runner-DWJbpo70.d.ts} +3 -3
  52. package/dist/{retry-policy-CN0khdlj.d.ts → retry-policy-C3s_lvdK.d.ts} +1 -1
  53. package/dist/sdd/index.d.ts +9 -8
  54. package/dist/sdd/index.js +44 -14
  55. package/dist/sdd/index.js.map +1 -1
  56. package/dist/{secret-vault-B2yw84VT.d.ts → secret-vault-Cgduf5xL.d.ts} +2 -2
  57. package/dist/security/index.d.ts +5 -67
  58. package/dist/security/index.js +129 -99
  59. package/dist/security/index.js.map +1 -1
  60. package/dist/{selector-CzHh_igB.d.ts → selector-47LBnBVk.d.ts} +1 -1
  61. package/dist/{session-event-bridge-BUI6Jf-4.d.ts → session-event-bridge-Cw7oqmW2.d.ts} +1 -1
  62. package/dist/{session-reader-CMgdMSRP.d.ts → session-reader-DD4v2Obw.d.ts} +1 -1
  63. package/dist/storage/index.d.ts +14 -12
  64. package/dist/storage/index.js +144 -120
  65. package/dist/storage/index.js.map +1 -1
  66. package/dist/tools/index.d.ts +4 -2
  67. package/dist/tools/index.js +166 -31
  68. package/dist/tools/index.js.map +1 -1
  69. package/dist/types/index.d.ts +20 -19
  70. package/dist/types/index.js +1358 -476
  71. package/dist/types/index.js.map +1 -1
  72. package/dist/utils/index.d.ts +472 -405
  73. package/dist/utils/index.js +2321 -1193
  74. package/dist/utils/index.js.map +1 -1
  75. package/package.json +5 -1
@@ -1,4 +1,4 @@
1
- import { S as SecretScrubber } from './permission-B9SB45lp.js';
1
+ import { S as SecretScrubber } from './permission-Bd-57Lbl.js';
2
2
  import { L as Logger } from './logger-B63L5bTg.js';
3
3
  import { R as RotatableSecretVault, S as SecretVault } from './secret-vault-BAKpgFw_.js';
4
4
 
@@ -107,4 +107,4 @@ declare function rotateConfigKeys(configPath: string, vault: RotatableSecretVaul
107
107
  file: string;
108
108
  }>;
109
109
 
110
- export { DefaultSecretScrubber as D, type SecretVaultOptions as S, DefaultSecretVault as a, rotateConfigKeys as b, decryptConfigSecrets as d, encryptConfigSecrets as e, isSecretField as i, migratePlaintextSecrets as m, rewriteConfigEncrypted as r };
110
+ export { DefaultSecretVault as D, type SecretVaultOptions as S, DefaultSecretScrubber as a, rotateConfigKeys as b, decryptConfigSecrets as d, encryptConfigSecrets as e, isSecretField as i, migratePlaintextSecrets as m, rewriteConfigEncrypted as r };
@@ -1,70 +1,8 @@
1
- export { D as DefaultSecretScrubber, a as DefaultSecretVault, S as SecretVaultOptions, d as decryptConfigSecrets, e as encryptConfigSecrets, i as isSecretField, m as migratePlaintextSecrets, r as rewriteConfigEncrypted, b as rotateConfigKeys } from '../secret-vault-B2yw84VT.js';
2
- export { A as AutoApprovePermissionPolicy, D as DefaultPermissionPolicy, P as PermissionPolicyOptions } from '../permission-policy-CkjSXabK.js';
3
- import '../permission-B9SB45lp.js';
4
- import '../context-MRk5PhNv.js';
1
+ export { a as DefaultSecretScrubber, D as DefaultSecretVault, S as SecretVaultOptions, d as decryptConfigSecrets, e as encryptConfigSecrets, i as isSecretField, m as migratePlaintextSecrets, r as rewriteConfigEncrypted, b as rotateConfigKeys } from '../secret-vault-Cgduf5xL.js';
2
+ export { A as AutoApprovePermissionPolicy, D as DefaultPermissionPolicy, P as PermissionPolicyOptions } from '../permission-policy-uNXC6Kge.js';
3
+ export { D as DANGEROUS_FOR_SUBAGENTS, T as ToolCapabilities, a as ToolCapability, g as getDangerousCapabilities, h as hasCapability, b as hasDangerousCapabilityForSubagents } from '../index-BfaS-f_m.js';
4
+ import '../permission-Bd-57Lbl.js';
5
+ import '../context-C0U8B9NF.js';
5
6
  import '../logger-B63L5bTg.js';
6
7
  import '../secret-vault-BAKpgFw_.js';
7
8
  import '../input-reader-E-ffP2ee.js';
8
-
9
- /**
10
- * Well-known tool capabilities used for authorization decisions.
11
- *
12
- * These are the preferred values for `Tool.capabilities`.
13
- * New capabilities should be added here with clear documentation.
14
- *
15
- * Philosophy (2026-06+):
16
- * - Prefer capabilities over exact tool name matching.
17
- * - Subagent guards and future policies should primarily key off capabilities.
18
- * - Name-based denylists are legacy and will be phased down.
19
- */
20
- declare const ToolCapabilities: {
21
- /** Can execute arbitrary commands in the user's shell (the `bash` tool). */
22
- readonly SHELL_ARBITRARY: "shell.arbitrary";
23
- /** Can execute a restricted set of commands (the `exec` tool). */
24
- readonly SHELL_RESTRICTED: "shell.restricted";
25
- /** Can read files inside the project (and possibly outside via symlinks if not guarded). */
26
- readonly FS_READ: "fs.read";
27
- /** Can write / modify / delete files inside the project. */
28
- readonly FS_WRITE: "fs.write";
29
- /** Can write files outside the current project root (very high risk). */
30
- readonly FS_WRITE_OUTSIDE_PROJECT: "fs.write.outside-project";
31
- /** Can perform outbound network requests. */
32
- readonly NET_OUTBOUND: "net.outbound";
33
- /** Proxies tools from external MCP servers (unknown capability). */
34
- readonly MCP_PROXY: "mcp.proxy";
35
- /** Can spawn or manage subagents / multi-agent tasks. */
36
- readonly SUBAGENT_SPAWN: "subagent.spawn";
37
- /** Can mutate global or session configuration / trust state. */
38
- readonly CONFIG_MUTATE: "config.mutate";
39
- /** Can install packages or run package managers with side effects. */
40
- readonly PACKAGE_INSTALL: "package.install";
41
- };
42
- type ToolCapability = (typeof ToolCapabilities)[keyof typeof ToolCapabilities];
43
- /**
44
- * Set of capabilities that are considered dangerous for subagents by default.
45
- * Subagents should not receive these capabilities unless the leader explicitly
46
- * allows the specific tool at spawn time.
47
- */
48
- declare const DANGEROUS_FOR_SUBAGENTS: readonly ToolCapability[];
49
- /**
50
- * Check if a tool (or its capabilities array) includes any dangerous capability
51
- * for subagent execution.
52
- */
53
- declare function hasDangerousCapabilityForSubagents(toolOrCaps: {
54
- capabilities?: readonly string[] | undefined;
55
- } | readonly string[] | undefined): boolean;
56
- /**
57
- * Check if a tool declares a specific capability (or any of the provided ones).
58
- */
59
- declare function hasCapability(toolOrCaps: {
60
- capabilities?: readonly string[] | undefined;
61
- } | readonly string[] | undefined, capability: ToolCapability | ToolCapability[]): boolean;
62
- /**
63
- * Returns the intersection of a tool's capabilities with the dangerous set.
64
- * Useful for logging and audit trails.
65
- */
66
- declare function getDangerousCapabilities(toolOrCaps: {
67
- capabilities?: readonly string[] | undefined;
68
- } | readonly string[] | undefined): ToolCapability[];
69
-
70
- export { DANGEROUS_FOR_SUBAGENTS, ToolCapabilities, type ToolCapability, getDangerousCapabilities, hasCapability, hasDangerousCapabilityForSubagents };
@@ -230,24 +230,68 @@ async function renameWithRetry(from, to) {
230
230
  throw lastErr;
231
231
  }
232
232
 
233
- // src/utils/error.ts
234
- function toErrorMessage(err) {
235
- return err instanceof Error ? err.message : String(err);
233
+ // src/utils/deep-merge.ts
234
+ var FORBIDDEN_PROTO_KEYS = /* @__PURE__ */ new Set([
235
+ "__proto__",
236
+ "constructor",
237
+ "prototype",
238
+ "__defineGetter__",
239
+ "__defineSetter__",
240
+ "__lookupGetter__",
241
+ "__lookupSetter__"
242
+ ]);
243
+ function isPrimitiveArray(a) {
244
+ return a.every((v) => v === null || typeof v !== "object" && typeof v !== "function");
236
245
  }
237
-
238
- // src/utils/safe-json.ts
239
- function safeParse(input, maxBytes = 5e6) {
240
- if (input.length > maxBytes) {
241
- return { ok: false, error: `Input exceeds limit (${maxBytes} bytes)` };
246
+ function deepMerge(base, patch, options = {}) {
247
+ const {
248
+ conflictResolution = "prefer-patch",
249
+ arrayMode = "replace",
250
+ protectProto = true,
251
+ onNonPrimitiveArrayReplace
252
+ } = options;
253
+ if (typeof base !== "object" || base === null) {
254
+ return conflictResolution === "prefer-patch" ? patch : base;
242
255
  }
243
- try {
244
- return { ok: true, value: JSON.parse(input) };
245
- } catch (err) {
246
- return {
247
- ok: false,
248
- error: toErrorMessage(err)
249
- };
256
+ if (typeof patch !== "object" || patch === null) {
257
+ return conflictResolution === "prefer-patch" ? patch : base;
250
258
  }
259
+ if (Array.isArray(base) && Array.isArray(patch)) {
260
+ if (arrayMode === "concat-primitives" && isPrimitiveArray(base) && isPrimitiveArray(patch)) {
261
+ return [.../* @__PURE__ */ new Set([...base, ...patch])];
262
+ }
263
+ return conflictResolution === "prefer-patch" ? patch : base;
264
+ }
265
+ if (Array.isArray(base) || Array.isArray(patch)) {
266
+ return conflictResolution === "prefer-patch" ? patch : base;
267
+ }
268
+ const baseObj = base;
269
+ const patchObj = patch;
270
+ const out = { ...baseObj };
271
+ for (const [k, v] of Object.entries(patchObj)) {
272
+ if (protectProto && FORBIDDEN_PROTO_KEYS.has(k)) continue;
273
+ const existing = out[k];
274
+ if (v !== null && typeof v === "object" && !Array.isArray(v) && existing !== null && typeof existing === "object" && !Array.isArray(existing)) {
275
+ out[k] = deepMerge(existing, v, options);
276
+ } else if (Array.isArray(v) && Array.isArray(existing)) {
277
+ if (onNonPrimitiveArrayReplace && !isPrimitiveArray(v)) {
278
+ onNonPrimitiveArrayReplace(k, existing.length, v.length);
279
+ }
280
+ out[k] = deepMerge(existing, v, options);
281
+ } else if (v !== void 0) {
282
+ if (onNonPrimitiveArrayReplace && Array.isArray(v) && !isPrimitiveArray(v)) {
283
+ const existingLen = Array.isArray(existing) ? existing.length : 0;
284
+ onNonPrimitiveArrayReplace(k, existingLen, v.length);
285
+ }
286
+ out[k] = v;
287
+ }
288
+ }
289
+ return out;
290
+ }
291
+
292
+ // src/utils/error.ts
293
+ function toErrorMessage(err) {
294
+ return err instanceof Error ? err.message : String(err);
251
295
  }
252
296
 
253
297
  // src/utils/expect-defined.ts
@@ -336,63 +380,54 @@ function matchAny(patterns, input) {
336
380
  return patterns.some((p) => matchGlob(p, input));
337
381
  }
338
382
 
339
- // src/utils/deep-merge.ts
340
- var FORBIDDEN_PROTO_KEYS = /* @__PURE__ */ new Set([
341
- "__proto__",
342
- "constructor",
343
- "prototype",
344
- "__defineGetter__",
345
- "__defineSetter__",
346
- "__lookupGetter__",
347
- "__lookupSetter__"
348
- ]);
349
- function isPrimitiveArray(a) {
350
- return a.every((v) => v === null || typeof v !== "object" && typeof v !== "function");
351
- }
352
- function deepMerge(base, patch, options = {}) {
353
- const {
354
- conflictResolution = "prefer-patch",
355
- arrayMode = "replace",
356
- protectProto = true,
357
- onNonPrimitiveArrayReplace
358
- } = options;
359
- if (typeof base !== "object" || base === null) {
360
- return conflictResolution === "prefer-patch" ? patch : base;
383
+ // src/utils/safe-json.ts
384
+ function safeParse(input, maxBytes = 5e6) {
385
+ if (input.length > maxBytes) {
386
+ return { ok: false, error: `Input exceeds limit (${maxBytes} bytes)` };
361
387
  }
362
- if (typeof patch !== "object" || patch === null) {
363
- return conflictResolution === "prefer-patch" ? patch : base;
388
+ try {
389
+ return { ok: true, value: JSON.parse(input) };
390
+ } catch (err) {
391
+ return {
392
+ ok: false,
393
+ error: toErrorMessage(err)
394
+ };
364
395
  }
365
- if (Array.isArray(base) && Array.isArray(patch)) {
366
- if (arrayMode === "concat-primitives" && isPrimitiveArray(base) && isPrimitiveArray(patch)) {
367
- return [.../* @__PURE__ */ new Set([...base, ...patch])];
396
+ }
397
+
398
+ // src/utils/tool-subject.ts
399
+ var GLOB_METACHARACTERS = /[*?[\]]/g;
400
+ function escapeGlobSubject(value) {
401
+ return value.replace(GLOB_METACHARACTERS, (char) => `\\${char}`);
402
+ }
403
+ function normalizePathSubject(value) {
404
+ return escapeGlobSubject(value.replace(/\\/g, "/"));
405
+ }
406
+ function isPathSubjectKey(subjectKey) {
407
+ return subjectKey === "path" || subjectKey === "file" || subjectKey === "files";
408
+ }
409
+ function subjectForToolInput(toolName, input, subjectKey) {
410
+ if (!input || typeof input !== "object") return void 0;
411
+ const obj = input;
412
+ if (subjectKey) {
413
+ const value = obj[subjectKey];
414
+ if (typeof value === "string") {
415
+ return isPathSubjectKey(subjectKey) ? normalizePathSubject(value) : escapeGlobSubject(value);
368
416
  }
369
- return conflictResolution === "prefer-patch" ? patch : base;
370
417
  }
371
- if (Array.isArray(base) || Array.isArray(patch)) {
372
- return conflictResolution === "prefer-patch" ? patch : base;
418
+ if (toolName === "bash" && typeof obj.command === "string") {
419
+ return escapeGlobSubject(obj.command);
373
420
  }
374
- const baseObj = base;
375
- const patchObj = patch;
376
- const out = { ...baseObj };
377
- for (const [k, v] of Object.entries(patchObj)) {
378
- if (protectProto && FORBIDDEN_PROTO_KEYS.has(k)) continue;
379
- const existing = out[k];
380
- if (v !== null && typeof v === "object" && !Array.isArray(v) && existing !== null && typeof existing === "object" && !Array.isArray(existing)) {
381
- out[k] = deepMerge(existing, v, options);
382
- } else if (Array.isArray(v) && Array.isArray(existing)) {
383
- if (onNonPrimitiveArrayReplace && !isPrimitiveArray(v)) {
384
- onNonPrimitiveArrayReplace(k, existing.length, v.length);
385
- }
386
- out[k] = deepMerge(existing, v, options);
387
- } else if (v !== void 0) {
388
- if (onNonPrimitiveArrayReplace && Array.isArray(v) && !isPrimitiveArray(v)) {
389
- const existingLen = Array.isArray(existing) ? existing.length : 0;
390
- onNonPrimitiveArrayReplace(k, existingLen, v.length);
391
- }
392
- out[k] = v;
393
- }
421
+ if (typeof obj.path === "string") {
422
+ return normalizePathSubject(obj.path);
394
423
  }
395
- return out;
424
+ if (typeof obj.url === "string") {
425
+ return escapeGlobSubject(obj.url);
426
+ }
427
+ if (typeof obj.name === "string") {
428
+ return escapeGlobSubject(obj.name);
429
+ }
430
+ return void 0;
396
431
  }
397
432
 
398
433
  // src/types/errors.ts
@@ -788,8 +823,13 @@ async function rotateConfigKeys(configPath, vault, logger) {
788
823
  warn(`[secret-vault] Config file ${configPath} is not valid JSON \u2014 skipping rotation`);
789
824
  return { rotated: 0, oldVersion: vault.keyVersion, newVersion: vault.keyVersion, file: configPath };
790
825
  }
791
- const counter = { n: 0 };
826
+ const counter = { n: 0, failed: [] };
792
827
  const decrypted = walkDecryptCount(parsed, vault, counter);
828
+ if (counter.failed.length > 0) {
829
+ throw new Error(
830
+ `[secret-vault] Aborting key rotation: ${counter.failed.length} field(s) could not be decrypted with the current key and would be permanently lost on rotation: ${counter.failed.join(", ")}. Restore or remove these fields before rotating.`
831
+ );
832
+ }
793
833
  if (counter.n === 0) {
794
834
  const { oldVersion: oldVersion2, newVersion: newVersion2 } = vault.rotateKey();
795
835
  log(`[secret-vault] Key rotated (v${oldVersion2} \u2192 v${newVersion2}) \u2014 no encrypted fields to re-encrypt`);
@@ -802,23 +842,27 @@ async function rotateConfigKeys(configPath, vault, logger) {
802
842
  log(`[secret-vault] Key rotated (v${oldVersion} \u2192 v${newVersion}) \u2014 re-encrypted ${counter.n} field(s)`);
803
843
  return { rotated: counter.n, oldVersion, newVersion, file: configPath };
804
844
  }
805
- function walkDecryptCount(node, vault, counter) {
845
+ function walkDecryptCount(node, vault, counter, pathPrefix = "") {
806
846
  if (node === null || node === void 0) return node;
807
847
  if (typeof node !== "object") return node;
808
848
  if (Array.isArray(node)) {
809
- return node.map((item) => walkDecryptCount(item, vault, counter));
849
+ return node.map(
850
+ (item, i) => walkDecryptCount(item, vault, counter, `${pathPrefix}[${i}]`)
851
+ );
810
852
  }
811
853
  const out = /* @__PURE__ */ Object.create(null);
812
854
  for (const [k, v] of Object.entries(node)) {
855
+ const keyPath = pathPrefix ? `${pathPrefix}.${k}` : k;
813
856
  if (typeof v === "string" && vault.isEncrypted(v)) {
814
857
  try {
815
858
  out[k] = vault.decrypt(v);
816
859
  counter.n++;
817
860
  } catch {
861
+ counter.failed.push(keyPath);
818
862
  out[k] = v;
819
863
  }
820
864
  } else if (typeof v === "object" && v !== null) {
821
- out[k] = walkDecryptCount(v, vault, counter);
865
+ out[k] = walkDecryptCount(v, vault, counter, keyPath);
822
866
  } else {
823
867
  out[k] = v;
824
868
  }
@@ -930,6 +974,14 @@ var DANGEROUS_FOR_SUBAGENTS = [
930
974
  ToolCapabilities.CONFIG_MUTATE,
931
975
  ToolCapabilities.PACKAGE_INSTALL
932
976
  ];
977
+ [
978
+ ToolCapabilities.FS_READ,
979
+ ToolCapabilities.FS_WRITE,
980
+ ToolCapabilities.NET_OUTBOUND,
981
+ ToolCapabilities.SHELL_ARBITRARY,
982
+ ToolCapabilities.SHELL_RESTRICTED,
983
+ ToolCapabilities.PACKAGE_INSTALL
984
+ ];
933
985
  function hasDangerousCapabilityForSubagents(toolOrCaps) {
934
986
  if (!toolOrCaps) return false;
935
987
  const input = toolOrCaps;
@@ -1150,7 +1202,7 @@ var DefaultPermissionPolicy = class {
1150
1202
  if (!this.loaded) await this.reload();
1151
1203
  const namespaceEntry = this.findNamespaceEntry(tool.name);
1152
1204
  const entry = this.policy[tool.name] ?? namespaceEntry;
1153
- const subject = this.subjectFor(tool.name, input, tool.subjectKey);
1205
+ const subject = subjectForToolInput(tool.name, input, tool.subjectKey);
1154
1206
  const cacheKey = `${tool.name}::${subject ?? tool.name}`;
1155
1207
  if (tool.name !== "write") {
1156
1208
  const cached = this._evalCache.get(cacheKey);
@@ -1332,32 +1384,6 @@ var DefaultPermissionPolicy = class {
1332
1384
  this.sessionAllowed.set(`${rule.tool}::${rule.pattern}`, true);
1333
1385
  this._evalCache.clear();
1334
1386
  }
1335
- subjectFor(toolName, input, subjectKey) {
1336
- if (!input || typeof input !== "object") return void 0;
1337
- const obj = input;
1338
- const globChars = /[*?[\]]/g;
1339
- const escapeGlob = (s) => s.replace(globChars, (c) => `\\${c}`);
1340
- const normalizePath = (s) => escapeGlob(s.replace(/\\/g, "/"));
1341
- if (subjectKey) {
1342
- const v = obj[subjectKey];
1343
- if (typeof v === "string") {
1344
- return subjectKey === "path" || subjectKey === "file" || subjectKey === "files" ? normalizePath(v) : escapeGlob(v);
1345
- }
1346
- }
1347
- if (toolName === "bash" && typeof obj.command === "string") {
1348
- return escapeGlob(obj.command);
1349
- }
1350
- if (typeof obj.path === "string") {
1351
- return normalizePath(obj.path);
1352
- }
1353
- if (typeof obj.url === "string") {
1354
- return escapeGlob(obj.url);
1355
- }
1356
- if (typeof obj.name === "string") {
1357
- return escapeGlob(obj.name);
1358
- }
1359
- return void 0;
1360
- }
1361
1387
  findNamespaceEntry(toolName) {
1362
1388
  for (const { pattern, value } of this.wildcardEntries) {
1363
1389
  if (matchGlob(pattern, toolName)) return value;
@@ -1380,9 +1406,13 @@ var AutoApprovePermissionPolicy = class _AutoApprovePermissionPolicy {
1380
1406
  const caps = tool.capabilities ?? [];
1381
1407
  const hasAllowedCap = caps.some((c) => this.allowedCapabilities.includes(c));
1382
1408
  const isMcp = _AutoApprovePermissionPolicy.isMcpTool(tool.name);
1383
- const blocked = tool.permission === "deny" || isMcp || !hasAllowedCap;
1409
+ const mcpProxyAllowed = this.allowedCapabilities.includes(ToolCapabilities.MCP_PROXY);
1410
+ const dangerousNotAllowed = getDangerousCapabilities(tool).filter(
1411
+ (c) => !this.allowedCapabilities.includes(c)
1412
+ );
1413
+ const blocked = tool.permission === "deny" || isMcp && !mcpProxyAllowed || !hasAllowedCap || dangerousNotAllowed.length > 0;
1384
1414
  if (blocked) {
1385
- const reason = isMcp ? `MCP tool ${tool.name} is not auto-approved for subagents \u2014 ask the leader to allow it explicitly` : tool.permission === "deny" ? "tool default deny" : `tool lacks allowed capability (has: ${caps.join(", ") || "none"}, allowed: ${this.allowedCapabilities.join(", ")})`;
1415
+ const reason = isMcp && !mcpProxyAllowed ? `MCP tool ${tool.name} is not auto-approved for subagents \u2014 ask the leader to allow mcp.proxy explicitly` : tool.permission === "deny" ? "tool default deny" : dangerousNotAllowed.length > 0 ? `tool requires un-granted dangerous capability (needs: ${dangerousNotAllowed.join(", ")}, allowed: ${this.allowedCapabilities.join(", ")})` : `tool lacks allowed capability (has: ${caps.join(", ") || "none"}, allowed: ${this.allowedCapabilities.join(", ")})`;
1386
1416
  return {
1387
1417
  permission: "deny",
1388
1418
  source: "subagent_guard",