@wrongstack/core 0.283.1 → 0.284.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 (78) hide show
  1. package/dist/{compactor-BxddyCFu.d.ts → compactor-DQLL4HTo.d.ts} +1 -1
  2. package/dist/{config-DkCbA3Bw.d.ts → config-MRqn1V-u.d.ts} +130 -22
  3. package/dist/coordination/index.d.ts +43 -20
  4. package/dist/coordination/index.js +1744 -912
  5. package/dist/coordination/index.js.map +1 -1
  6. package/dist/{default-config-Buho8yge.d.ts → default-config-B79_gJYv.d.ts} +7 -0
  7. package/dist/defaults/index.d.ts +25 -29
  8. package/dist/defaults/index.js +2546 -7396
  9. package/dist/defaults/index.js.map +1 -1
  10. package/dist/{director-state-B_GPa78Q.d.ts → director-state-CMS_bMs4.d.ts} +2 -0
  11. package/dist/{events-KmxSmvho.d.ts → events-Bgnh43r9.d.ts} +27 -10
  12. package/dist/execution/index.d.ts +15 -16
  13. package/dist/execution/index.js +534 -140
  14. package/dist/execution/index.js.map +1 -1
  15. package/dist/execution/prompt-enhancer.d.ts +1 -1
  16. package/dist/extension/index.d.ts +6 -6
  17. package/dist/{global-mailbox-rWVt8YlO.d.ts → global-mailbox-sZwyI6CS.d.ts} +13 -2
  18. package/dist/{goal-store-8owBXJT2.d.ts → goal-store-Datpp-ar.d.ts} +1 -1
  19. package/dist/hq/index.d.ts +6 -6
  20. package/dist/hq/index.js +58 -7
  21. package/dist/hq/index.js.map +1 -1
  22. package/dist/{index-BhCteHAF.d.ts → index--Gm41aBJ.d.ts} +26 -11
  23. package/dist/{index-BEFWNZYs.d.ts → index-CbyuOE5y.d.ts} +5 -1
  24. package/dist/index.d.ts +50 -1015
  25. package/dist/index.js +21028 -27775
  26. package/dist/index.js.map +1 -1
  27. package/dist/infrastructure/index.d.ts +9 -7
  28. package/dist/infrastructure/index.js +7 -2
  29. package/dist/infrastructure/index.js.map +1 -1
  30. package/dist/kernel/index.d.ts +11 -11
  31. package/dist/kernel/index.js.map +1 -1
  32. package/dist/{mcp-servers-BUx9A_AQ.d.ts → mcp-servers-DEV4s6Ks.d.ts} +3 -3
  33. package/dist/models/index.d.ts +4 -4
  34. package/dist/models/index.js +18 -3
  35. package/dist/models/index.js.map +1 -1
  36. package/dist/{agent-subagent-runner-BsuWhB28.d.ts → multi-agent-coordinator-4RCRZKjN.d.ts} +417 -9
  37. package/dist/{null-fleet-bus-D4e9R7Qc.d.ts → null-fleet-bus-CFoNVQEK.d.ts} +53 -12
  38. package/dist/observability/index.d.ts +3 -3
  39. package/dist/{parallel-eternal-engine-iY2uxocj.d.ts → parallel-eternal-engine-HUrtePLd.d.ts} +4 -5
  40. package/dist/{permission-B6YAtNFz.d.ts → permission-ByDKXEcG.d.ts} +1 -1
  41. package/dist/{pipeline-ixSFe5jg.d.ts → pipeline-DGDyIohT.d.ts} +28 -7
  42. package/dist/{provider-model-resolve-DIxKL_T-.d.ts → provider-model-resolve-o2hHLs79.d.ts} +3 -3
  43. package/dist/{provider-runner-oQhDaZmH.d.ts → provider-runner-ChL-kVg6.d.ts} +3 -3
  44. package/dist/{retry-policy-V67lBOJz.d.ts → retry-policy-CQ7KwXJa.d.ts} +2 -2
  45. package/dist/{secret-vault-D7jeyXUQ.d.ts → secret-vault-DxohkUBc.d.ts} +3 -2
  46. package/dist/security/index.d.ts +4 -4
  47. package/dist/security/index.js +232 -2
  48. package/dist/security/index.js.map +1 -1
  49. package/dist/{selector-Bx2HgUkU.d.ts → selector-D8O6B_Rm.d.ts} +1 -1
  50. package/dist/{session-event-bridge-Bkp7ORfc.d.ts → session-event-bridge-D_z_mBwk.d.ts} +3 -3
  51. package/dist/{session-reader-B-Fi9L6I.d.ts → session-reader-7Esxrkpw.d.ts} +1 -1
  52. package/dist/storage/index.d.ts +77 -39
  53. package/dist/storage/index.js +1223 -288
  54. package/dist/storage/index.js.map +1 -1
  55. package/dist/tasking/index.d.ts +124 -0
  56. package/dist/tasking/index.js +492 -0
  57. package/dist/tasking/index.js.map +1 -0
  58. package/dist/{todos-checkpoint-BwCrj4Cb.d.ts → todos-checkpoint-FY7PjmMx.d.ts} +13 -4
  59. package/dist/{tool-LVSLiE1s.d.ts → tool-BNlnIJvo.d.ts} +216 -17
  60. package/dist/{tool-executor-kElSEgO0.d.ts → tool-executor-CckSCM5E.d.ts} +12 -15
  61. package/dist/tools/index.d.ts +2 -2
  62. package/dist/tools/index.js.map +1 -1
  63. package/dist/types/index.d.ts +94 -19
  64. package/dist/types/index.js +76 -12
  65. package/dist/types/index.js.map +1 -1
  66. package/dist/utils/index.d.ts +44 -10
  67. package/dist/utils/index.js +106 -17
  68. package/dist/utils/index.js.map +1 -1
  69. package/dist/{worktree-manager-BjyAW30D.d.ts → worktree-manager-DzwxKE35.d.ts} +1 -1
  70. package/instructions/coordination/subagent-baseline.md +5 -0
  71. package/instructions/llm/autonomy-brain.md +3 -2
  72. package/instructions/system.md +4 -0
  73. package/package.json +10 -3
  74. package/dist/multi-agent-coordinator-CrjeTB9i.d.ts +0 -357
  75. package/dist/sdd/index.d.ts +0 -1993
  76. package/dist/sdd/index.js +0 -9500
  77. package/dist/sdd/index.js.map +0 -1
  78. package/dist/spec-TBi3Jr6T.d.ts +0 -78
@@ -1,8 +1,7 @@
1
- import { A as Agent, a as AgentFactory } from './agent-subagent-runner-BsuWhB28.js';
2
- import { B as BrainArbiter, E as EventBus } from './events-KmxSmvho.js';
3
- import { C as Compactor } from './compactor-BxddyCFu.js';
4
- import { J as JournalEntry } from './goal-store-8owBXJT2.js';
5
- import { D as DispatchClassifier, a as DefaultMultiAgentCoordinator } from './multi-agent-coordinator-CrjeTB9i.js';
1
+ import { A as Agent, a as AgentFactory, D as DispatchClassifier, b as DefaultMultiAgentCoordinator } from './multi-agent-coordinator-4RCRZKjN.js';
2
+ import { B as BrainArbiter, E as EventBus } from './events-Bgnh43r9.js';
3
+ import { C as Compactor } from './compactor-DQLL4HTo.js';
4
+ import { J as JournalEntry } from './goal-store-Datpp-ar.js';
6
5
 
7
6
  /**
8
7
  * Design Studio — curated frontend/mobile UI design kits.
@@ -1,4 +1,4 @@
1
- import { f as Permission, g as Tool, d as Context } from './tool-LVSLiE1s.js';
1
+ import { f as Permission, g as Tool, d as Context } from './tool-BNlnIJvo.js';
2
2
 
3
3
  interface TrustPolicy {
4
4
  [toolNameOrPattern: string]: {
@@ -1,6 +1,6 @@
1
- import { g as Tool, s as TextBlock, i as ContentBlock } from './tool-LVSLiE1s.js';
1
+ import { g as Tool, s as TextBlock, i as ContentBlock } from './tool-BNlnIJvo.js';
2
2
  import { a as MailboxAgentStatus } from './mailbox-types-BGZWrYTJ.js';
3
- import { H as HookEvent, f as HookMatcher, I as InProcessHook, S as ShellHook, g as HookEntry, T as ToolResultRenderMode } from './config-DkCbA3Bw.js';
3
+ import { H as HookEvent, f as HookMatcher, I as InProcessHook, g as HookRegistrationOptions, S as ShellHook, h as HttpHook, C as ConfiguredHook, i as HookEntry, T as ToolResultRenderMode } from './config-MRqn1V-u.js';
4
4
 
5
5
  /** Model capabilities relevant to prompt composition. */
6
6
  interface ModelCapabilities {
@@ -31,10 +31,29 @@ interface BuildContext {
31
31
  */
32
32
  onlineAgents?: MailboxAgentStatus[] | undefined;
33
33
  }
34
+ /**
35
+ * Stability regions for the system prompt.
36
+ *
37
+ * `core` and `session` form the provider-cache prefix and must remain byte-for-byte
38
+ * stable after the first request in a session. `volatile` is appended at request
39
+ * time and may change between turns without rewriting that prefix.
40
+ */
41
+ interface SystemPromptRegions {
42
+ readonly core: readonly TextBlock[];
43
+ readonly session: readonly TextBlock[];
44
+ readonly volatile: readonly TextBlock[];
45
+ }
46
+ declare function flattenSystemPromptRegions(regions: SystemPromptRegions): TextBlock[];
34
47
  interface SystemPromptBuilder {
35
48
  build(ctx: BuildContext): Promise<TextBlock[]>;
49
+ /** Region-aware build used by hosts that enforce prompt-prefix stability. */
50
+ buildRegions?(ctx: BuildContext): Promise<SystemPromptRegions>;
36
51
  }
37
52
 
53
+ interface LoadConfiguredHooksOptions {
54
+ /** Load only trusted hooks that remain active under `--no-hooks`. */
55
+ policyOnly?: boolean | undefined;
56
+ }
38
57
  /**
39
58
  * Registry of lifecycle hooks (both in-process and shell). One instance is
40
59
  * shared per session: the boot path loads `config.hooks` as shell entries and
@@ -44,14 +63,16 @@ interface SystemPromptBuilder {
44
63
  declare class HookRegistry {
45
64
  private readonly entries;
46
65
  /** Register an in-process hook. Returns an unsubscribe function. */
47
- registerInProcess(event: HookEvent, matcher: HookMatcher | undefined, hook: InProcessHook, owner?: string | undefined): () => void;
66
+ registerInProcess(event: HookEvent, matcher: HookMatcher | undefined, hook: InProcessHook, owner?: string | undefined, options?: HookRegistrationOptions): () => void;
48
67
  /**
49
68
  * Register a single shell hook. The hook is owned by the runtime (no plugin
50
69
  * name) — it survives plugin uninstalls. Returns an unsubscribe function.
51
70
  */
52
71
  registerShell(event: HookEvent, hook: ShellHook): () => void;
53
- /** Bulk-load shell hooks from a `config.hooks` map. */
54
- loadShellHooks(hooks: Partial<Record<HookEvent, ShellHook[]>> | undefined): void;
72
+ /** Register a native HTTP hook. */
73
+ registerHttp(event: HookEvent, hook: HttpHook): () => void;
74
+ /** Bulk-load command/HTTP hooks from a `config.hooks` map. */
75
+ loadShellHooks(hooks: Partial<Record<HookEvent, ConfiguredHook[]>> | undefined, options?: LoadConfiguredHooksOptions): void;
55
76
  /**
56
77
  * Atomically replace the shell-hook set: drop every currently-registered
57
78
  * shell entry, then load the supplied `config.hooks` map. In-process
@@ -65,7 +86,7 @@ declare class HookRegistry {
65
86
  * with the same map yields the same registry state (callers should still
66
87
  * guard at the change-detection layer to avoid wasted work).
67
88
  */
68
- replaceShellHooks(hooks: Partial<Record<HookEvent, ShellHook[]>> | undefined): void;
89
+ replaceShellHooks(hooks: Partial<Record<HookEvent, ConfiguredHook[]>> | undefined, options?: LoadConfiguredHooksOptions): void;
69
90
  /** All entries registered for an event, in registration order. */
70
91
  list(event: HookEvent): readonly HookEntry[];
71
92
  /** True when any entry is registered for the event. */
@@ -307,4 +328,4 @@ declare class Pipeline<T> {
307
328
  private ensureUnique;
308
329
  }
309
330
 
310
- export { type BuildContext as B, Container as C, type Decorator as D, type Factory as F, HookRegistry as H, type MiddlewareHandler as M, type NextFn as N, Pipeline as P, type ReadonlyPipeline as R, type SystemPromptBuilder as S, type Token as T, type Renderer as a, type Middleware as b, type ModelCapabilities as c, type BindOptions as d, type PipelineOptions as e, hookMatcherMatches as h };
331
+ export { type BuildContext as B, Container as C, type Decorator as D, type Factory as F, HookRegistry as H, type MiddlewareHandler as M, type NextFn as N, Pipeline as P, type ReadonlyPipeline as R, type SystemPromptBuilder as S, type Token as T, type Renderer as a, type Middleware as b, type ModelCapabilities as c, type SystemPromptRegions as d, type BindOptions as e, type PipelineOptions as f, flattenSystemPromptRegions as g, hookMatcherMatches as h };
@@ -1,7 +1,7 @@
1
- import { P as Provider, M as Message } from './tool-LVSLiE1s.js';
2
- import { M as MessageSelector, S as SelectorResult } from './selector-Bx2HgUkU.js';
1
+ import { P as Provider, M as Message } from './tool-BNlnIJvo.js';
2
+ import { M as MessageSelector, S as SelectorResult } from './selector-D8O6B_Rm.js';
3
3
  import { M as ModeStore, a as ModeConfig, b as Mode } from './mode-CZlO9iU1.js';
4
- import { M as ModelsRegistry, c as ModelsDevPayload, d as ResolvedProvider, R as ResolvedModel, W as WireFamily, e as ModelsDevModel } from './config-DkCbA3Bw.js';
4
+ import { M as ModelsRegistry, c as ModelsDevPayload, d as ResolvedProvider, R as ResolvedModel, W as WireFamily, e as ModelsDevModel } from './config-MRqn1V-u.js';
5
5
 
6
6
  /**
7
7
  * Offline **floor** for the ChatGPT "Sign in with ChatGPT" (`openai-codex`)
@@ -1,8 +1,8 @@
1
- import { E as EventBus } from './events-KmxSmvho.js';
1
+ import { E as EventBus } from './events-Bgnh43r9.js';
2
2
  import { L as Logger } from './logger-B63L5bTg.js';
3
3
  import { T as Tracer } from './observability-D-HZN_mF.js';
4
- import { P as Provider, c as Request, d as Context, e as Response } from './tool-LVSLiE1s.js';
5
- import { R as RetryPolicy } from './retry-policy-V67lBOJz.js';
4
+ import { P as Provider, c as Request, d as Context, e as Response } from './tool-BNlnIJvo.js';
5
+ import { R as RetryPolicy } from './retry-policy-CQ7KwXJa.js';
6
6
 
7
7
  /**
8
8
  * Options passed to a ProviderRunner when calling the provider.
@@ -1,4 +1,4 @@
1
- import { d as Context, e as Response, h as ProviderError } from './tool-LVSLiE1s.js';
1
+ import { d as Context, e as Response, h as ProviderError } from './tool-BNlnIJvo.js';
2
2
 
3
3
  type RecoveryDecision = {
4
4
  /**
@@ -32,7 +32,7 @@ interface ErrorHandler {
32
32
  */
33
33
  recover(err: unknown, ctx: Context): Promise<RecoveryDecision | null>;
34
34
  classify(err: unknown): {
35
- kind: 'rate_limit' | 'overloaded' | 'server' | 'client' | 'network' | 'abort' | 'context_overflow' | 'unknown';
35
+ kind: 'rate_limit' | 'overloaded' | 'server' | 'client' | 'network' | 'abort' | 'context_overflow' | 'content_filter' | 'unknown';
36
36
  retryable: boolean;
37
37
  };
38
38
  }
@@ -1,6 +1,6 @@
1
- import { g as Tool, d as Context } from './tool-LVSLiE1s.js';
1
+ import { g as Tool, d as Context } from './tool-BNlnIJvo.js';
2
2
  import { I as InputReader } from './input-reader-E-ffP2ee.js';
3
- import { P as PermissionPolicy, a as PermissionDecision } from './permission-B6YAtNFz.js';
3
+ import { P as PermissionPolicy, a as PermissionDecision } from './permission-ByDKXEcG.js';
4
4
  import { S as SecretScrubber } from './secret-scrubber-3MHDDAtm.js';
5
5
  import { L as Logger } from './logger-B63L5bTg.js';
6
6
  import { R as RotatableSecretVault, S as SecretVault } from './secret-vault-BAKpgFw_.js';
@@ -102,6 +102,7 @@ declare class DefaultPermissionPolicy implements PermissionPolicy {
102
102
  evaluate(tool: Tool, input: unknown, ctx: Context): Promise<PermissionDecision>;
103
103
  private isDestructiveByCapability;
104
104
  private isDestructiveYoloCall;
105
+ private isSensitiveReadCall;
105
106
  trust(rule: {
106
107
  tool: string;
107
108
  pattern: string;
@@ -1,8 +1,8 @@
1
- export { A as AutoApprovePermissionPolicy, a as DefaultPermissionPolicy, b as DefaultSecretScrubber, D as DefaultSecretVault, P as PermissionPolicyOptions, S as SecretVaultOptions, d as decryptConfigSecrets, e as encryptConfigSecrets, i as isSecretField, m as migratePlaintextSecrets, r as rewriteConfigEncrypted, c as rotateConfigKeys } from '../secret-vault-D7jeyXUQ.js';
2
- export { D as DANGEROUS_FOR_SUBAGENTS, T as ToolCapabilities, a as ToolCapability, g as getDangerousCapabilities, h as hasCapability, b as hasDangerousCapabilityForSubagents } from '../index-BEFWNZYs.js';
3
- import '../tool-LVSLiE1s.js';
1
+ export { A as AutoApprovePermissionPolicy, a as DefaultPermissionPolicy, b as DefaultSecretScrubber, D as DefaultSecretVault, P as PermissionPolicyOptions, S as SecretVaultOptions, d as decryptConfigSecrets, e as encryptConfigSecrets, i as isSecretField, m as migratePlaintextSecrets, r as rewriteConfigEncrypted, c as rotateConfigKeys } from '../secret-vault-DxohkUBc.js';
2
+ export { D as DANGEROUS_FOR_SUBAGENTS, T as ToolCapabilities, a as ToolCapability, g as getDangerousCapabilities, h as hasCapability, b as hasDangerousCapabilityForSubagents } from '../index-CbyuOE5y.js';
3
+ import '../tool-BNlnIJvo.js';
4
4
  import '../input-reader-E-ffP2ee.js';
5
- import '../permission-B6YAtNFz.js';
5
+ import '../permission-ByDKXEcG.js';
6
6
  import '../secret-scrubber-3MHDDAtm.js';
7
7
  import '../logger-B63L5bTg.js';
8
8
  import '../secret-vault-BAKpgFw_.js';
@@ -1131,6 +1131,10 @@ var ToolCapabilities = {
1131
1131
  SUBAGENT_SPAWN: "subagent.spawn",
1132
1132
  /** Can inspect fleet/subagent coordination state without mutating it. */
1133
1133
  COORDINATION_FLEET_READ: "coordination.fleet.read",
1134
+ /** Can publish attributed, schema-checked events onto the fleet bus. */
1135
+ COORDINATION_FLEET_EMIT: "coordination.fleet.emit",
1136
+ /** Can submit a task-local structured result to the parent Director. */
1137
+ COORDINATION_RESULT_SUBMIT: "coordination.result.submit",
1134
1138
  /** Can read or write inter-agent mailbox messages. */
1135
1139
  COORDINATION_MAIL: "coordination.mail",
1136
1140
  /** Can schedule, inspect, or cancel in-session cron jobs. */
@@ -1167,7 +1171,8 @@ var DANGEROUS_FOR_SUBAGENTS = [
1167
1171
  ToolCapabilities.PACKAGE_INSTALL,
1168
1172
  // Read-only fleet visibility (fleet_status) — peer awareness has no blast
1169
1173
  // radius and every fleet worker should coordinate around its peers.
1170
- ToolCapabilities.COORDINATION_FLEET_READ
1174
+ ToolCapabilities.COORDINATION_FLEET_READ,
1175
+ ToolCapabilities.COORDINATION_RESULT_SUBMIT
1171
1176
  ];
1172
1177
  function hasDangerousCapabilityForSubagents(toolOrCaps) {
1173
1178
  if (!toolOrCaps) return false;
@@ -1239,6 +1244,11 @@ var CATASTROPHIC_PATTERNS = [
1239
1244
  /:\(\)\s*\{\s*:\|:&\s*\}\s*;/
1240
1245
  // classic fork bomb
1241
1246
  ];
1247
+ var HIGH_IMPACT_PATTERNS = [
1248
+ /\b(?:curl|wget|fetch|httpie|http|irm|iwr|Invoke-WebRequest|Invoke-RestMethod)\b[\s\S]{0,300}\|\s*(?:sudo\s+)?(?:sh|bash|zsh|fish|pwsh|powershell|iex|Invoke-Expression)\b/i,
1249
+ /\b(?:powershell|pwsh)(?:\.exe)?\b[\s\S]{0,120}-(?:enc|encodedcommand)\b/i,
1250
+ /\b(?:shutdown|reboot)\b/i
1251
+ ];
1242
1252
  var CATASTROPHIC_POSIX_ROOTS = /* @__PURE__ */ new Set([
1243
1253
  "/etc",
1244
1254
  "/usr",
@@ -1286,6 +1296,121 @@ function pathLooksInsideProject(rawPath, projectRoot) {
1286
1296
  function tokenizeShell(command) {
1287
1297
  return command.match(/"[^"]*"|'[^']*'|\S+/g)?.map((token) => token.replace(/^['"]|['"]$/g, "")) ?? [];
1288
1298
  }
1299
+ function commandSegment(tokens, start) {
1300
+ const out = [];
1301
+ for (let i = start; i < tokens.length; i++) {
1302
+ const token = tokens[i];
1303
+ if (token === void 0 || SHELL_OPERATORS.has(token)) break;
1304
+ out.push(token);
1305
+ }
1306
+ return out;
1307
+ }
1308
+ function hasShortFlag(args, letters) {
1309
+ const seen = /* @__PURE__ */ new Set();
1310
+ for (const arg of args) {
1311
+ if (!arg.startsWith("-") || arg.startsWith("--")) continue;
1312
+ for (const ch of arg.replace(/^-+/, "")) seen.add(ch.toLowerCase());
1313
+ }
1314
+ return letters.split("").every((letter) => seen.has(letter));
1315
+ }
1316
+ function hasRecursiveForceDelete(command, projectRoot) {
1317
+ const tokens = tokenizeShell(command);
1318
+ for (let i = 0; i < tokens.length; i++) {
1319
+ const token = tokens[i]?.toLowerCase();
1320
+ if (!token) continue;
1321
+ if (token === "rm" || token === "rmdir") {
1322
+ const args = commandSegment(tokens, i + 1);
1323
+ const recursiveForce = hasShortFlag(args, "rf") || args.some((arg) => arg === "--recursive") && args.some((arg) => arg === "--force");
1324
+ if (recursiveForce) {
1325
+ const targets = args.filter((arg) => !arg.startsWith("-") && !SHELL_OPERATORS.has(arg));
1326
+ if (targets.length > 0 && targets.every((target) => target.trim().length === 0)) {
1327
+ continue;
1328
+ }
1329
+ if (targets.length === 0) return true;
1330
+ if (targets.some(isCatastrophicDeleteTarget)) return true;
1331
+ if (targets.some((target) => !pathLooksInsideProject(target, projectRoot))) return true;
1332
+ }
1333
+ }
1334
+ if (token === "remove-item" || token === "ri") {
1335
+ const args = commandSegment(tokens, i + 1).map((arg) => arg.toLowerCase());
1336
+ const recurse = args.some((arg) => arg === "-recurse" || arg === "-r");
1337
+ const force = args.some((arg) => arg === "-force" || arg === "-f");
1338
+ if (recurse && force && !args.includes("-whatif")) {
1339
+ const targets = args.filter((arg) => !arg.startsWith("-") && !SHELL_OPERATORS.has(arg));
1340
+ if (targets.length === 0) return true;
1341
+ if (targets.some(isCatastrophicDeleteTarget)) return true;
1342
+ if (targets.some((target) => !pathLooksInsideProject(target, projectRoot))) return true;
1343
+ }
1344
+ }
1345
+ if (token === "rd" || token === "rmdir") {
1346
+ const args = commandSegment(tokens, i + 1).map((arg) => arg.toLowerCase());
1347
+ if (args.includes("/s")) {
1348
+ const targets = args.filter((arg) => !arg.startsWith("-") && !arg.startsWith("/") && !SHELL_OPERATORS.has(arg));
1349
+ if (targets.length === 0) return true;
1350
+ if (targets.some(isCatastrophicDeleteTarget)) return true;
1351
+ if (targets.some((target) => !pathLooksInsideProject(target, projectRoot))) return true;
1352
+ }
1353
+ }
1354
+ }
1355
+ return false;
1356
+ }
1357
+ function hasGitHistoryRewrite(command) {
1358
+ const tokens = tokenizeShell(command).map((token) => token.toLowerCase());
1359
+ for (let i = 0; i < tokens.length; i++) {
1360
+ if (tokens[i] !== "git") continue;
1361
+ const args = commandSegment(tokens, i + 1);
1362
+ if (args.includes("reset") && args.some((arg) => arg === "--hard" || arg.startsWith("--hard="))) {
1363
+ return true;
1364
+ }
1365
+ const cleanIdx = args.indexOf("clean");
1366
+ if (cleanIdx >= 0) {
1367
+ const cleanArgs = args.slice(cleanIdx + 1);
1368
+ if (cleanArgs.some((arg) => arg === "-f" || arg === "--force" || /^-[a-z]*f[a-z]*$/i.test(arg))) {
1369
+ return true;
1370
+ }
1371
+ }
1372
+ const pushIdx = args.indexOf("push");
1373
+ if (pushIdx >= 0) {
1374
+ const pushArgs = args.slice(pushIdx + 1);
1375
+ if (pushArgs.some(
1376
+ (arg) => arg === "-f" || arg === "--force" || arg === "--force-with-lease" || arg.startsWith("--force=") || arg.startsWith("--force-with-lease=")
1377
+ )) {
1378
+ return true;
1379
+ }
1380
+ }
1381
+ }
1382
+ return false;
1383
+ }
1384
+ function hasExternalPublish(command) {
1385
+ const tokens = tokenizeShell(command).map((token) => token.toLowerCase());
1386
+ for (let i = 0; i < tokens.length; i++) {
1387
+ const cmd = tokens[i];
1388
+ if (!cmd) continue;
1389
+ const args = commandSegment(tokens, i + 1);
1390
+ if (["npm", "pnpm", "yarn", "bun"].includes(cmd) && (args.includes("publish") || args.includes("deploy"))) {
1391
+ return true;
1392
+ }
1393
+ if (cmd === "cargo" && (args.includes("publish") || args.includes("yank"))) return true;
1394
+ if ((cmd === "docker" || cmd === "podman") && args.includes("push")) return true;
1395
+ if (cmd === "kubectl") {
1396
+ const deleteIdx = args.indexOf("delete");
1397
+ if (deleteIdx >= 0 && (args[deleteIdx + 1] === "namespace" || args[deleteIdx + 1] === "ns")) {
1398
+ return true;
1399
+ }
1400
+ if (args.includes("drain")) return true;
1401
+ }
1402
+ }
1403
+ return false;
1404
+ }
1405
+ function hasFindExec(command) {
1406
+ const tokens = tokenizeShell(command).map((token) => token.toLowerCase());
1407
+ for (let i = 0; i < tokens.length; i++) {
1408
+ if (tokens[i] !== "find") continue;
1409
+ const args = commandSegment(tokens, i + 1);
1410
+ if (args.some((arg) => arg === "-exec" || arg === "-ok" || arg === "-execdir")) return true;
1411
+ }
1412
+ return false;
1413
+ }
1289
1414
  function isCatastrophicDeleteTarget(rawTarget) {
1290
1415
  const t = rawTarget.replace(/^['"]|['"]$/g, "").trim();
1291
1416
  if (!t) return false;
@@ -1340,11 +1465,16 @@ function hasCatastrophicDelete(command) {
1340
1465
  }
1341
1466
  return false;
1342
1467
  }
1343
- function isClearlyDestructiveBashCommand(command, _projectRoot) {
1468
+ function isClearlyDestructiveBashCommand(command, projectRoot) {
1344
1469
  const trimmed = command.trim();
1345
1470
  if (!trimmed) return false;
1471
+ if (hasRecursiveForceDelete(trimmed, projectRoot)) return true;
1472
+ if (hasGitHistoryRewrite(trimmed)) return true;
1473
+ if (hasExternalPublish(trimmed)) return true;
1474
+ if (hasFindExec(trimmed)) return true;
1346
1475
  if (hasCatastrophicDelete(trimmed)) return true;
1347
1476
  if (CATASTROPHIC_PATTERNS.some((pattern) => pattern.test(trimmed))) return true;
1477
+ if (HIGH_IMPACT_PATTERNS.some((pattern) => pattern.test(trimmed))) return true;
1348
1478
  return false;
1349
1479
  }
1350
1480
 
@@ -1361,6 +1491,64 @@ function shellCommandLineFromInput(input) {
1361
1491
  const renderedArgs = args.filter((arg) => typeof arg === "string").map((arg) => /\s/.test(arg) ? `"${arg.replace(/"/g, '\\"')}"` : arg);
1362
1492
  return [command, ...renderedArgs].join(" ");
1363
1493
  }
1494
+ var SENSITIVE_READ_PATHS = [
1495
+ /(?:^|[\\/])\.env(?:[.\w-]*)?$/i,
1496
+ /(?:^|[\\/])\.npmrc$/i,
1497
+ /(?:^|[\\/])\.pypirc$/i,
1498
+ /(?:^|[\\/])\.netrc$/i,
1499
+ /(?:^|[\\/])id_(?:rsa|dsa|ecdsa|ed25519)$/i,
1500
+ /(?:^|[\\/])\.aws[\\/]credentials$/i,
1501
+ /(?:^|[\\/])\.kube[\\/]config$/i,
1502
+ /(?:^|[\\/])(?:secrets?|tokens?|credentials?|private[_-]?keys?)$/i,
1503
+ /(?:^|[\\/])[^\\/]*(?:secret|token|credential|private[_-]?key)[^\\/]*(?:\.json|\.ya?ml|\.toml|\.ini|\.txt|\.env|\.properties|\.key|\.pem)$/i
1504
+ ];
1505
+ var SHELL_READ_VERBS = /* @__PURE__ */ new Set([
1506
+ "cat",
1507
+ "type",
1508
+ "get-content",
1509
+ "gc",
1510
+ "more",
1511
+ "less",
1512
+ "head",
1513
+ "tail",
1514
+ "grep",
1515
+ "rg",
1516
+ "sed",
1517
+ "awk",
1518
+ "findstr",
1519
+ "select-string",
1520
+ "strings",
1521
+ "cp",
1522
+ "copy",
1523
+ "scp"
1524
+ ]);
1525
+ function stripShellQuotes(value) {
1526
+ return value.replace(/^['"]|['"]$/g, "");
1527
+ }
1528
+ function pathLooksSensitive(rawPath) {
1529
+ const normalized = stripShellQuotes(rawPath).replace(/\\/g, "/");
1530
+ return SENSITIVE_READ_PATHS.some((pattern) => pattern.test(normalized));
1531
+ }
1532
+ function inputPathLooksSensitive(input) {
1533
+ if (!input || typeof input !== "object") return false;
1534
+ const obj = input;
1535
+ for (const key of ["path", "file", "file_path", "filePath", "target", "targetPath"]) {
1536
+ const value = obj[key];
1537
+ if (typeof value === "string" && pathLooksSensitive(value)) return true;
1538
+ }
1539
+ return false;
1540
+ }
1541
+ function shellCommandReadsSensitivePath(command) {
1542
+ const tokens = command.match(/"[^"]*"|'[^']*'|\S+/g)?.map((token) => stripShellQuotes(token).toLowerCase()) ?? [];
1543
+ for (let i = 0; i < tokens.length; i++) {
1544
+ const token = tokens[i];
1545
+ if (!token) continue;
1546
+ if (!SHELL_READ_VERBS.has(token)) continue;
1547
+ const rest = tokens.slice(i + 1);
1548
+ if (rest.some((arg) => pathLooksSensitive(arg))) return true;
1549
+ }
1550
+ return false;
1551
+ }
1364
1552
  var DefaultPermissionPolicy = class {
1365
1553
  policy = {};
1366
1554
  loaded = false;
@@ -1543,6 +1731,34 @@ var DefaultPermissionPolicy = class {
1543
1731
  this._evalCache.set(cacheKey, decision);
1544
1732
  return decision;
1545
1733
  }
1734
+ if (!this.yolo && this.isSensitiveReadCall(tool, input)) {
1735
+ if (this.promptDelegate) {
1736
+ const userDecision = await this.promptDelegate(tool, input, subject ?? tool.name);
1737
+ if (userDecision === "always") {
1738
+ await this.trust({ tool: tool.name, pattern: subject ?? tool.name });
1739
+ return {
1740
+ permission: "auto",
1741
+ source: "user",
1742
+ reason: "user always-allowed sensitive read"
1743
+ };
1744
+ }
1745
+ if (userDecision === "deny") {
1746
+ await this.deny({ tool: tool.name, pattern: subject ?? tool.name });
1747
+ return { permission: "deny", source: "user", reason: "user denied sensitive read" };
1748
+ }
1749
+ return {
1750
+ permission: userDecision === "yes" ? "auto" : "deny",
1751
+ source: "user",
1752
+ reason: "sensitive read user decision"
1753
+ };
1754
+ }
1755
+ return {
1756
+ permission: "confirm",
1757
+ source: "default",
1758
+ riskTier: "standard",
1759
+ reason: "sensitive file read needs explicit approval"
1760
+ };
1761
+ }
1546
1762
  if (this.yolo) {
1547
1763
  const decision = { permission: "auto", source: "yolo" };
1548
1764
  this._evalCache.set(cacheKey, decision);
@@ -1627,6 +1843,20 @@ var DefaultPermissionPolicy = class {
1627
1843
  }
1628
1844
  return tool.riskTier === "destructive";
1629
1845
  }
1846
+ isSensitiveReadCall(tool, input) {
1847
+ const isReadTool = hasCapability(tool, ToolCapabilities.FS_READ) || tool.name === "read" || tool.name === "grep" || tool.name === "glob" || tool.name === "tree";
1848
+ if (isReadTool && inputPathLooksSensitive(input)) return true;
1849
+ const hasShellCap = hasCapability(tool, [
1850
+ ToolCapabilities.SHELL_ARBITRARY,
1851
+ ToolCapabilities.SHELL_RESTRICTED,
1852
+ ToolCapabilities.SHELL_EXEC
1853
+ ]);
1854
+ if (!hasShellCap && tool.name !== "bash" && tool.name !== "shell" && tool.name !== "exec") {
1855
+ return false;
1856
+ }
1857
+ const command = shellCommandLineFromInput(input);
1858
+ return command ? shellCommandReadsSensitivePath(command) : false;
1859
+ }
1630
1860
  async trust(rule) {
1631
1861
  if (!this.loaded) await this.reload();
1632
1862
  const entry = this.policy[rule.tool] ?? {};