@wrongstack/core 0.300.0 → 0.301.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 (144) hide show
  1. package/dist/chronicle/index.d.ts +2 -0
  2. package/dist/chronicle/index.js +297 -10
  3. package/dist/chronicle/project-server.js +253 -15
  4. package/dist/chronicle/sqlite-compaction.d.ts +20 -0
  5. package/dist/chronicle/sqlite-journal.d.ts +57 -0
  6. package/dist/coordination/agents/capability-manifest.d.ts +7 -0
  7. package/dist/coordination/agents/index.d.ts +3 -2
  8. package/dist/coordination/agents/index.js +818 -570
  9. package/dist/coordination/agents/project-agent-identity.d.ts +6 -6
  10. package/dist/coordination/agents/role-skills.d.ts +1 -1
  11. package/dist/coordination/agents/types.d.ts +6 -0
  12. package/dist/coordination/director.d.ts +2 -2
  13. package/dist/coordination/index.js +6778 -6438
  14. package/dist/coordination/mail-tools.d.ts +3 -3
  15. package/dist/coordination/mailbox-project-server.js +3 -4
  16. package/dist/coordination/mailbox-types.d.ts +6 -0
  17. package/dist/core/agent-response.d.ts +5 -1
  18. package/dist/core/agent-tools.d.ts +3 -0
  19. package/dist/core/context.d.ts +20 -0
  20. package/dist/core/index.d.ts +8 -7
  21. package/dist/core/index.js +893 -284
  22. package/dist/core/instruction-template.d.ts +6 -3
  23. package/dist/core/next-steps-slot.d.ts +88 -0
  24. package/dist/core/system-prompt-builder.d.ts +5 -3
  25. package/dist/core/system-prompt-memory-skills.d.ts +1 -0
  26. package/dist/core/system-prompt-skill-bodies.d.ts +3 -3
  27. package/dist/defaults/index.js +9796 -8897
  28. package/dist/design/index.js +11 -3
  29. package/dist/execution/auto-compaction-middleware.d.ts +17 -0
  30. package/dist/execution/autonomy-brain.d.ts +8 -2
  31. package/dist/execution/brain-runtime.d.ts +3 -1
  32. package/dist/execution/compaction-core.d.ts +41 -2
  33. package/dist/execution/council-brain.d.ts +37 -2
  34. package/dist/execution/council-orchestrator.d.ts +2 -2
  35. package/dist/execution/index.d.ts +11 -10
  36. package/dist/execution/index.js +5178 -4077
  37. package/dist/execution/tool-executor.d.ts +4 -1
  38. package/dist/execution/topic-shift-advisor.d.ts +53 -0
  39. package/dist/extension/index.js +8 -2
  40. package/dist/extension/registry.d.ts +8 -1
  41. package/dist/goal/index.js +11 -3
  42. package/dist/hooks/index.js +42 -9
  43. package/dist/hooks/runner.d.ts +12 -1
  44. package/dist/hq/index.js +41 -17
  45. package/dist/hq/publisher.d.ts +21 -3
  46. package/dist/index.d.ts +21 -20
  47. package/dist/index.js +10887 -8053
  48. package/dist/infrastructure/index.js +108 -21
  49. package/dist/kernel/events/session-events.d.ts +13 -0
  50. package/dist/kernel/events/tool-events.d.ts +3 -3
  51. package/dist/models/index.d.ts +1 -0
  52. package/dist/models/index.js +17 -0
  53. package/dist/models/provider-credentials.d.ts +54 -0
  54. package/dist/plugin/index.d.ts +1 -0
  55. package/dist/plugin/index.js +2024 -502
  56. package/dist/plugins/auto-review-plugin.d.ts +3 -0
  57. package/dist/plugins/cloud-config-sync-plugin.d.ts +22 -0
  58. package/dist/plugins/review-claim-registry.d.ts +23 -8
  59. package/dist/plugins/review-types.d.ts +2 -0
  60. package/dist/registry/index.js +109 -74
  61. package/dist/registry/tool-registry.d.ts +15 -0
  62. package/dist/security/capabilities.d.ts +2 -0
  63. package/dist/security/index.d.ts +1 -1
  64. package/dist/security/index.js +9 -2
  65. package/dist/security/readonly-permission-policy.d.ts +20 -0
  66. package/dist/session-registry-atomic-file.d.ts +32 -5
  67. package/dist/skills/frontmatter.d.ts +6 -0
  68. package/dist/skills/index.js +22 -5
  69. package/dist/storage/cloud-config-sync/sanitize.d.ts +54 -0
  70. package/dist/storage/cloud-config-sync.d.ts +87 -0
  71. package/dist/storage/index.d.ts +1 -0
  72. package/dist/storage/index.js +854 -66
  73. package/dist/tools/index.d.ts +1 -1
  74. package/dist/tools/index.js +511 -234
  75. package/dist/tools/one-shot-llm-tool.d.ts +1 -0
  76. package/dist/tools/plugin-manager.d.ts +27 -0
  77. package/dist/types/config/mcp-features.d.ts +18 -11
  78. package/dist/types/config/root.d.ts +8 -1
  79. package/dist/types/config/runtime.d.ts +20 -6
  80. package/dist/types/config/skills-fleet-brain.d.ts +12 -4
  81. package/dist/types/config/tools.d.ts +16 -0
  82. package/dist/types/context-window.d.ts +1 -0
  83. package/dist/types/hooks.d.ts +14 -0
  84. package/dist/types/index.d.ts +2 -2
  85. package/dist/types/index.js +1 -0
  86. package/dist/types/multi-agent.d.ts +2 -0
  87. package/dist/types/one-shot-llm.d.ts +16 -0
  88. package/dist/types/provider.d.ts +16 -0
  89. package/dist/types/runtime-capability-manifest.d.ts +168 -0
  90. package/dist/types/skill.d.ts +5 -0
  91. package/dist/types/system-prompt.d.ts +3 -1
  92. package/dist/types/tool-executor.d.ts +8 -1
  93. package/dist/utils/context-breakdown.d.ts +8 -2
  94. package/dist/utils/index.d.ts +1 -1
  95. package/dist/utils/index.js +141 -31
  96. package/dist/utils/regex-guard.d.ts +16 -2
  97. package/dist/utils/sage-output-block.d.ts +7 -10
  98. package/dist/utils/wstack-paths.d.ts +11 -3
  99. package/instructions/agents/browser.md +1 -4
  100. package/instructions/agents/e2e.md +17 -15
  101. package/instructions/agents/ios.md +3 -3
  102. package/instructions/agents/search.md +1 -1
  103. package/instructions/autonomy/goal-preamble.md +4 -4
  104. package/instructions/coordination/director-preamble.md +2 -3
  105. package/instructions/coordination/subagent-baseline.md +3 -1
  106. package/instructions/leader-after-task.md +12 -0
  107. package/instructions/llm/chimera-review.md +1 -1
  108. package/instructions/modes/audit-lite.md +1 -1
  109. package/instructions/sections/tool/common-patterns.md +18 -2
  110. package/instructions/sections/tool/mailbox-compact.md +1 -1
  111. package/instructions/sections/tool/mailbox-full.md +1 -1
  112. package/instructions/system-lite.md +10 -0
  113. package/instructions/system-pro.md +23 -14
  114. package/instructions/system.md +22 -13
  115. package/package.json +3 -3
  116. package/skills/api-design/SKILL.md +3 -0
  117. package/skills/audit-log/SKILL.md +2 -0
  118. package/skills/auto-review/SKILL.md +6 -1
  119. package/skills/bug-hunter/SKILL.md +4 -1
  120. package/skills/chimera/SKILL.md +3 -0
  121. package/skills/data-governance/SKILL.md +3 -0
  122. package/skills/design-system/SKILL.md +5 -2
  123. package/skills/docker-deploy/SKILL.md +2 -0
  124. package/skills/git-flow/SKILL.md +2 -0
  125. package/skills/mailbox-bridge/SKILL.md +3 -0
  126. package/skills/mnemosyne/SKILL.md +2 -0
  127. package/skills/multi-agent/SKILL.md +4 -1
  128. package/skills/node-modern/SKILL.md +4 -1
  129. package/skills/observability/SKILL.md +3 -0
  130. package/skills/output-standards/SKILL.md +2 -0
  131. package/skills/plugin-author/SKILL.md +4 -1
  132. package/skills/prompt-engineering/SKILL.md +3 -1
  133. package/skills/react-modern/SKILL.md +6 -3
  134. package/skills/refactor-planner/SKILL.md +2 -0
  135. package/skills/research-web/SKILL.md +3 -0
  136. package/skills/sdd/SKILL.md +3 -1
  137. package/skills/security-scanner/SKILL.md +3 -0
  138. package/skills/skill-creator/SKILL.md +2 -0
  139. package/skills/tech-stack/SKILL.md +3 -0
  140. package/skills/testing/SKILL.md +4 -1
  141. package/skills/typescript-strict/SKILL.md +4 -1
  142. package/skills/wrongstack-kanban/SKILL.md +6 -3
  143. package/skills/wrongstack-mailbox/SKILL.md +4 -1
  144. package/skills/wrongstack-mailbox-mcp/SKILL.md +10 -8
@@ -627,9 +627,7 @@ var CouncilOrchestrator = class {
627
627
  profileCache = /* @__PURE__ */ new WeakMap();
628
628
  constructor(opts) {
629
629
  if (!opts.caller && !opts.seatCaller && !opts.judgeCaller) {
630
- throw new Error(
631
- "CouncilOrchestrator: provide `caller`, `seatCaller`, or `judgeCaller`."
632
- );
630
+ throw new Error("CouncilOrchestrator: provide `caller`, `seatCaller`, or `judgeCaller`.");
633
631
  }
634
632
  this.caller = opts.caller;
635
633
  this.personas = opts.personas ?? DEFAULT_COUNCIL_PERSONA_REGISTRY;
@@ -809,7 +807,7 @@ var CouncilOrchestrator = class {
809
807
  persona: seat.persona,
810
808
  status: "invalid",
811
809
  ...metadata,
812
- error: parsed.error
810
+ error: withTruncationNote(parsed.error, result, profile.voterMaxTokens)
813
811
  };
814
812
  }
815
813
  return {
@@ -1098,7 +1096,14 @@ var CouncilOrchestrator = class {
1098
1096
  }
1099
1097
  return { ok: false, error: result.error };
1100
1098
  }
1101
- return parseJudge(result.text, question, this.refusalOptionId);
1099
+ const judged = parseJudge(result.text, question, this.refusalOptionId);
1100
+ if (!judged.ok) {
1101
+ return {
1102
+ ok: false,
1103
+ error: withTruncationNote(judged.error, result, profile.judgeMaxTokens)
1104
+ };
1105
+ }
1106
+ return judged;
1102
1107
  }
1103
1108
  /**
1104
1109
  * Resolve the effective LLM caller for a call. Voter seats (defined
@@ -1206,7 +1211,10 @@ function parseCouncilResponse(text, question, refusalOptionId, opts) {
1206
1211
  error: `${roleLabel} returned an empty or missing ${opts.freeTextField}.`
1207
1212
  };
1208
1213
  }
1209
- return { ok: true, value: { [opts.freeTextField]: freeText, ...rationale ? { rationale } : {} } };
1214
+ return {
1215
+ ok: true,
1216
+ value: { [opts.freeTextField]: freeText, ...rationale ? { rationale } : {} }
1217
+ };
1210
1218
  }
1211
1219
  function divergentStances(valid) {
1212
1220
  const seen = /* @__PURE__ */ new Set();
@@ -1250,6 +1258,10 @@ function parseJudge(text, question, refusalOptionId) {
1250
1258
  }
1251
1259
  };
1252
1260
  }
1261
+ function withTruncationNote(error, result, maxTokens) {
1262
+ if (result.stopReason !== "max_tokens") return error;
1263
+ return `${error} (response truncated at maxTokens=${maxTokens} \u2014 reasoning models may need a larger budget)`;
1264
+ }
1253
1265
  function parseObject(text) {
1254
1266
  const trimmed = text.trim();
1255
1267
  const first = trimmed.indexOf("{");
@@ -2291,59 +2303,6 @@ function fallbackProfileChain(config, profileName) {
2291
2303
  }
2292
2304
  var DEFAULT_PRIMARY_COOLDOWN_MAX_MS = 10 * 6e4;
2293
2305
 
2294
- // src/coordination/agents/types.ts
2295
- var HOUR = 60 * 60 * 1e3;
2296
- var LIGHT_BUDGET = {
2297
- timeoutMs: 3 * HOUR,
2298
- maxIterations: 3e3,
2299
- maxToolCalls: 8e3
2300
- };
2301
- var MEDIUM_BUDGET = {
2302
- timeoutMs: 5 * HOUR,
2303
- maxIterations: 5e3,
2304
- maxToolCalls: 14e3
2305
- };
2306
- var HEAVY_BUDGET = {
2307
- timeoutMs: 10 * HOUR,
2308
- maxIterations: 8e3,
2309
- maxToolCalls: 2e4
2310
- };
2311
- var TOOLS = {
2312
- /** Pure read/inspect — safe for analysis and review agents. */
2313
- read: ["read", "grep", "glob", "search", "tree", "mailbox"],
2314
- /** Read + structured inspection (logs, diffs, json, dependency audit). */
2315
- inspect: ["read", "grep", "glob", "search", "tree", "json", "diff", "logs", "audit", "mailbox"],
2316
- /** Read + edit (no shell). For agents that write code/docs but don't run it. */
2317
- write: ["read", "grep", "glob", "search", "tree", "write", "edit", "replace", "patch", "mailbox"],
2318
- /** Full build loop: edit + run (lint/format/typecheck/test/bash). */
2319
- build: [
2320
- "read",
2321
- "grep",
2322
- "glob",
2323
- "search",
2324
- "tree",
2325
- "write",
2326
- "edit",
2327
- "replace",
2328
- "patch",
2329
- "bash",
2330
- "exec",
2331
- "lint",
2332
- "format",
2333
- "typecheck",
2334
- "test",
2335
- "mailbox"
2336
- ],
2337
- /** Version control. */
2338
- vcs: ["read", "grep", "glob", "git", "diff"],
2339
- /** Dependency management + CVE audit. */
2340
- deps: ["read", "grep", "glob", "install", "outdated", "audit", "json", "mailbox"],
2341
- /** Documentation authoring. */
2342
- docs: ["read", "grep", "glob", "search", "tree", "write", "edit", "document", "mailbox"],
2343
- /** Web research. */
2344
- research: ["read", "grep", "glob", "search", "fetch", "mailbox"]
2345
- };
2346
-
2347
2306
  // src/coordination/agents/agent-prompts.ts
2348
2307
  import { readFileSync as readFileSync6, statSync as statSync3 } from "node:fs";
2349
2308
  import * as path6 from "node:path";
@@ -2366,6 +2325,9 @@ function canonicalProjectRoot(absRoot) {
2366
2325
  const commonDirFile = path2.join(gitDir, "commondir");
2367
2326
  if (!fs.statSync(commonDirFile).isFile()) return checkoutRoot;
2368
2327
  const commonDir = path2.resolve(gitDir, fs.readFileSync(commonDirFile, "utf8").trim());
2328
+ const worktreesDir = path2.dirname(gitDir);
2329
+ if (path2.basename(worktreesDir).toLowerCase() !== "worktrees") return checkoutRoot;
2330
+ if (path2.resolve(worktreesDir, "..") !== commonDir) return checkoutRoot;
2369
2331
  if (path2.basename(commonDir).toLowerCase() !== ".git") return checkoutRoot;
2370
2332
  return path2.dirname(commonDir);
2371
2333
  } catch {
@@ -2388,7 +2350,7 @@ function safeProfileName(name) {
2388
2350
  const safe = (name ?? "").replace(/[/\\:]/g, "_").replace(/\.\./g, "_").trim();
2389
2351
  return safe || "default";
2390
2352
  }
2391
- function activeProfileName(globalRoot) {
2353
+ function bootstrapProfileName(globalRoot) {
2392
2354
  try {
2393
2355
  const parsed = JSON.parse(fs.readFileSync(path2.join(globalRoot, "config.json"), "utf8"));
2394
2356
  return safeProfileName(
@@ -2406,7 +2368,7 @@ function wstackGlobalRoot() {
2406
2368
  function resolveWstackPaths(opts) {
2407
2369
  const globalRoot = opts.globalRoot ?? (opts.userHome ? path2.join(opts.userHome, ".wrongstack") : wstackGlobalRoot());
2408
2370
  const homeDir = opts.userHome ?? os.homedir();
2409
- const profileName = safeProfileName(opts.profileName ?? activeProfileName(globalRoot));
2371
+ const profileName = safeProfileName(opts.profileName ?? bootstrapProfileName(globalRoot));
2410
2372
  const profileDir = path2.join(globalRoot, "profiles", profileName);
2411
2373
  const hash = projectHash(opts.projectRoot);
2412
2374
  const slug = projectSlug(opts.projectRoot);
@@ -2476,7 +2438,12 @@ function resolveWstackPaths(opts) {
2476
2438
  projectRequirementIntakes: path2.join(projectDir, "requirement-intakes"),
2477
2439
  syncConfig: path2.join(profileDir, "sync.json"),
2478
2440
  configHistoryDir: path2.join(globalRoot, "config-history"),
2479
- projectStatus: (projectHash2) => path2.join(globalRoot, "projects", projectHash2, "status.json")
2441
+ projectStatus: (statusProjectSlug) => {
2442
+ if (!/^[a-z0-9](?:[a-z0-9-]{0,39})-[a-f0-9]{6}$/.test(statusProjectSlug)) {
2443
+ throw new Error(`Invalid project slug: ${statusProjectSlug}`);
2444
+ }
2445
+ return path2.join(globalRoot, "projects", statusProjectSlug, "status.json");
2446
+ }
2480
2447
  };
2481
2448
  }
2482
2449
 
@@ -2521,6 +2488,8 @@ var ToolCapabilities = {
2521
2488
  NET_OUTBOUND: "net.outbound",
2522
2489
  /** Can mutate in-memory session todos only. */
2523
2490
  SESSION_TODO: "session.todo",
2491
+ /** Can park after-task `<nextsteps>` suggestions for the current turn. */
2492
+ SESSION_NEXTSTEPS: "session.nextsteps",
2524
2493
  /** Can mutate in-memory session mode only. */
2525
2494
  SESSION_MODE: "session.mode",
2526
2495
  /** Can inspect registered tool metadata. */
@@ -2582,6 +2551,334 @@ var WIDE_SUBAGENT_CAPABILITIES = [
2582
2551
  ToolCapabilities.COORDINATION_FLEET_READ,
2583
2552
  ToolCapabilities.COORDINATION_RESULT_SUBMIT
2584
2553
  ];
2554
+ function getDangerousCapabilities(toolOrCaps) {
2555
+ if (!toolOrCaps) return [];
2556
+ const input = toolOrCaps;
2557
+ const caps = Array.isArray(toolOrCaps) ? toolOrCaps : input.capabilities ?? [];
2558
+ return caps.filter(
2559
+ (c) => DANGEROUS_FOR_SUBAGENTS.includes(c)
2560
+ );
2561
+ }
2562
+
2563
+ // src/types/runtime-capability-manifest.ts
2564
+ var PLAYWRIGHT_ALIASES = {
2565
+ playwright_navigate: "browser_navigate",
2566
+ playwright_screenshot: "browser_screenshot",
2567
+ playwright_click: "browser_click",
2568
+ playwright_type: "browser_type",
2569
+ playwright_evaluate: "browser_evaluate",
2570
+ playwright_select_option: "browser_select",
2571
+ playwright_hover: "browser_hover",
2572
+ playwright_fill_form: "browser_type",
2573
+ playwright_wait_for: "browser_wait",
2574
+ playwright_press_key: "browser_press",
2575
+ playwright_drag: "browser_drag"
2576
+ };
2577
+ var RUNTIME_CAPABILITY_MANIFEST = [
2578
+ {
2579
+ id: "filesystem.read",
2580
+ pack: "core",
2581
+ exposure: "direct",
2582
+ tools: ["read", "grep", "glob", "tree"]
2583
+ },
2584
+ {
2585
+ id: "code.inspect",
2586
+ pack: "core",
2587
+ exposure: "direct",
2588
+ tools: [
2589
+ "codebase-stats",
2590
+ "codebase-search",
2591
+ "codebase-incoming-calls",
2592
+ "codebase-outgoing-calls",
2593
+ "codebase-index",
2594
+ "dead-code-scan",
2595
+ "diff",
2596
+ "json",
2597
+ "logs"
2598
+ ]
2599
+ },
2600
+ {
2601
+ id: "filesystem.write",
2602
+ pack: "development",
2603
+ exposure: "direct",
2604
+ tools: ["write", "edit", "replace", "patch"]
2605
+ },
2606
+ {
2607
+ id: "execution.shell",
2608
+ pack: "development",
2609
+ exposure: "direct",
2610
+ tools: ["bash", "exec", "language", "language_info", "language_package"]
2611
+ },
2612
+ {
2613
+ id: "verification.run",
2614
+ pack: "development",
2615
+ exposure: "direct",
2616
+ tools: ["lint", "format", "typecheck", "test", "e2e_plan"]
2617
+ },
2618
+ {
2619
+ id: "version-control.manage",
2620
+ pack: "development",
2621
+ exposure: "direct",
2622
+ tools: ["git"]
2623
+ },
2624
+ {
2625
+ id: "dependencies.manage",
2626
+ pack: "development",
2627
+ exposure: "on-demand",
2628
+ tools: ["install", "outdated", "audit"]
2629
+ },
2630
+ {
2631
+ id: "documentation.author",
2632
+ pack: "development",
2633
+ exposure: "on-demand",
2634
+ tools: ["document", "design", "scaffold"]
2635
+ },
2636
+ {
2637
+ id: "web.research",
2638
+ pack: "core",
2639
+ exposure: "direct",
2640
+ tools: ["search", "fetch"]
2641
+ },
2642
+ {
2643
+ id: "work.plan",
2644
+ pack: "core",
2645
+ exposure: "direct",
2646
+ tools: ["todo", "plan", "task", "kanban", "nextsteps"]
2647
+ },
2648
+ {
2649
+ id: "coordination.mailbox",
2650
+ pack: "fleet",
2651
+ exposure: "direct",
2652
+ tools: ["mailbox", "mail_send", "mail_inbox", "fleet_status"]
2653
+ },
2654
+ {
2655
+ id: "fleet.delegate",
2656
+ pack: "fleet",
2657
+ exposure: "on-demand",
2658
+ tools: [
2659
+ "delegate",
2660
+ "spawn_subagent",
2661
+ "assign_task",
2662
+ "kanban_queue",
2663
+ "await_tasks",
2664
+ "ask_subagent",
2665
+ "ask_result",
2666
+ "roll_up",
2667
+ "quality_gate",
2668
+ "terminate_subagent",
2669
+ "terminate_all",
2670
+ "work_complete",
2671
+ "collab_debug",
2672
+ "fleet_emit",
2673
+ "fleet"
2674
+ ]
2675
+ },
2676
+ {
2677
+ id: "reasoning.oneshot",
2678
+ pack: "core",
2679
+ exposure: "on-demand",
2680
+ tools: ["llm", "council"]
2681
+ },
2682
+ {
2683
+ id: "memory.manage",
2684
+ pack: "memory",
2685
+ exposure: "on-demand",
2686
+ tools: ["remember", "search_memory", "find_related_memories", "forget"]
2687
+ },
2688
+ {
2689
+ id: "memory.curate",
2690
+ pack: "memory",
2691
+ exposure: "on-demand",
2692
+ tools: [
2693
+ "memory_candidates",
2694
+ "memory_update",
2695
+ "memory_delete",
2696
+ "memory_recover",
2697
+ "memory_backfill_recoverable",
2698
+ "memory_for_file",
2699
+ "memory_for_path",
2700
+ "memory_search",
2701
+ "memory_graph",
2702
+ "memory_gather_batch",
2703
+ "memory_verify",
2704
+ "memory_hygiene"
2705
+ ]
2706
+ },
2707
+ {
2708
+ id: "browser.interact",
2709
+ pack: "browser",
2710
+ exposure: "on-demand",
2711
+ tools: [
2712
+ "browser_open",
2713
+ "browser_status",
2714
+ "browser_list",
2715
+ "browser_navigate",
2716
+ "browser_snapshot",
2717
+ "browser_screenshot",
2718
+ "browser_click",
2719
+ "browser_type",
2720
+ "browser_select",
2721
+ "browser_press",
2722
+ "browser_hover",
2723
+ "browser_drag",
2724
+ "browser_wait",
2725
+ "browser_evaluate",
2726
+ "browser_upload",
2727
+ "browser_close"
2728
+ ],
2729
+ aliases: PLAYWRIGHT_ALIASES
2730
+ },
2731
+ {
2732
+ id: "mcp.dynamic",
2733
+ pack: "mcp",
2734
+ exposure: "on-demand",
2735
+ tools: ["mcp_use"]
2736
+ },
2737
+ {
2738
+ id: "automation.manage",
2739
+ pack: "admin",
2740
+ exposure: "on-demand",
2741
+ tools: ["cron_schedule", "cron_list", "cron_cancel", "watch_start", "watch_list", "watch_stop"]
2742
+ },
2743
+ {
2744
+ id: "context.pin",
2745
+ pack: "admin",
2746
+ exposure: "on-demand",
2747
+ tools: ["pin_add", "pin_list", "pin_remove"]
2748
+ },
2749
+ {
2750
+ id: "quality.analyze",
2751
+ pack: "development",
2752
+ exposure: "on-demand",
2753
+ tools: ["dead_code_scan", "detect_duplicate_code", "secret_scanner_test", "error_lens_history"]
2754
+ },
2755
+ {
2756
+ id: "release.manage",
2757
+ pack: "development",
2758
+ exposure: "on-demand",
2759
+ tools: ["git_autocommit", "semver_current", "semver_bump", "semver_changelog"]
2760
+ },
2761
+ {
2762
+ id: "messaging.telegram",
2763
+ pack: "fleet",
2764
+ exposure: "on-demand",
2765
+ tools: ["telegram_send", "telegram_read", "telegram_approve"]
2766
+ },
2767
+ {
2768
+ id: "tools.discover",
2769
+ pack: "admin",
2770
+ exposure: "direct",
2771
+ tools: ["tool_search", "tool_use", "tool_help", "batch_tool_use"]
2772
+ },
2773
+ {
2774
+ id: "runtime.admin",
2775
+ pack: "admin",
2776
+ exposure: "internal",
2777
+ tools: ["set_working_dir", "context_manager", "mode", "skill", "mcp_control"]
2778
+ }
2779
+ ];
2780
+ var CAPABILITY_BY_ID = new Map(
2781
+ RUNTIME_CAPABILITY_MANIFEST.map((definition) => [definition.id, definition])
2782
+ );
2783
+ var CAPABILITY_BY_TOOL = /* @__PURE__ */ new Map();
2784
+ var TOOL_ALIASES = /* @__PURE__ */ new Map();
2785
+ for (const definition of RUNTIME_CAPABILITY_MANIFEST) {
2786
+ for (const tool of definition.tools) {
2787
+ CAPABILITY_BY_TOOL.set(tool, definition.id);
2788
+ }
2789
+ for (const [alias, tool] of Object.entries(definition.aliases ?? {})) {
2790
+ TOOL_ALIASES.set(alias, tool);
2791
+ }
2792
+ }
2793
+ function toolsForRuntimeCapabilities(capabilityIds) {
2794
+ return [
2795
+ ...new Set(
2796
+ capabilityIds.flatMap((id) => {
2797
+ const definition = CAPABILITY_BY_ID.get(id);
2798
+ if (!definition) throw new Error(`Unknown runtime capability: "${id}"`);
2799
+ return definition.tools;
2800
+ })
2801
+ )
2802
+ ];
2803
+ }
2804
+ function normalizeRuntimeToolName(name) {
2805
+ return TOOL_ALIASES.get(name) ?? name;
2806
+ }
2807
+ function runtimeCapabilityForTool(name) {
2808
+ return CAPABILITY_BY_TOOL.get(normalizeRuntimeToolName(name));
2809
+ }
2810
+ function inferRuntimeCapabilities(toolNames) {
2811
+ const ids = /* @__PURE__ */ new Set();
2812
+ for (const rawName of toolNames) {
2813
+ const id = runtimeCapabilityForTool(rawName);
2814
+ if (id) ids.add(id);
2815
+ }
2816
+ return [...ids];
2817
+ }
2818
+
2819
+ // src/coordination/agents/project-agent-consolidation.ts
2820
+ import {
2821
+ existsSync,
2822
+ mkdirSync,
2823
+ readFileSync as readFileSync3,
2824
+ rmSync
2825
+ } from "node:fs";
2826
+ import * as path4 from "node:path";
2827
+
2828
+ // src/coordination/agents/project-agent-learning-entries.ts
2829
+ function splitLearnedEntries(body) {
2830
+ return body.split(/\n---\n+/).map((entry) => entry.trim()).map(
2831
+ (entry) => entry.replace(/^# Learned wisdom for .+$/im, "").replace(/<!--[\s\S]*?-->/g, "").trim()
2832
+ ).filter(Boolean);
2833
+ }
2834
+
2835
+ // src/coordination/agents/project-agent-paths.ts
2836
+ import * as path3 from "node:path";
2837
+ var AGENT_ROLE_PATTERN = /^[a-z0-9][a-z0-9._-]{0,95}$/i;
2838
+ function assertProjectAgentRole(role) {
2839
+ const normalized = role.trim();
2840
+ if (!AGENT_ROLE_PATTERN.test(normalized) || normalized === "." || normalized === ".." || normalized.includes("/") || normalized.includes("\\")) {
2841
+ throw new Error(`Invalid project agent role: "${role}".`);
2842
+ }
2843
+ return normalized;
2844
+ }
2845
+ function agentsDir(projectRoot) {
2846
+ const root = projectRoot ?? process.cwd();
2847
+ return path3.join(root, ".wrongstack", "agents");
2848
+ }
2849
+ function roleDir(role, projectRoot) {
2850
+ return path3.join(agentsDir(projectRoot), assertProjectAgentRole(role));
2851
+ }
2852
+ function learningPolicyPath(role, projectRoot) {
2853
+ return path3.join(roleDir(role, projectRoot), "learning.json");
2854
+ }
2855
+
2856
+ // src/coordination/agents/project-agent-consolidation.ts
2857
+ function consolidationPath(role, projectRoot) {
2858
+ return path4.join(roleDir(role, projectRoot), "consolidated.md");
2859
+ }
2860
+ function consolidationMetaPath(role, projectRoot) {
2861
+ return path4.join(roleDir(role, projectRoot), "consolidation.json");
2862
+ }
2863
+ function loadProjectAgentConsolidated(role, projectRoot) {
2864
+ try {
2865
+ return readFileSync3(consolidationPath(role, projectRoot), "utf8").trim();
2866
+ } catch {
2867
+ return "";
2868
+ }
2869
+ }
2870
+ function loadConsolidationMetadata(role, projectRoot) {
2871
+ try {
2872
+ const raw = readFileSync3(consolidationMetaPath(role, projectRoot), "utf8");
2873
+ const parsed = JSON.parse(raw);
2874
+ if (typeof parsed === "object" && parsed !== null && typeof parsed.consolidatedAt === "string" && typeof parsed.sourceEntryCount === "number") {
2875
+ return parsed;
2876
+ }
2877
+ return void 0;
2878
+ } catch {
2879
+ return void 0;
2880
+ }
2881
+ }
2585
2882
 
2586
2883
  // src/coordination/agents/project-agent-knowledge-manifests.ts
2587
2884
  var BUILT_IN_KNOWLEDGE_MANIFESTS = {
@@ -2649,30 +2946,7 @@ var BUILT_IN_KNOWLEDGE_MANIFESTS = {
2649
2946
  };
2650
2947
 
2651
2948
  // src/coordination/agents/project-agent-learning-policy.ts
2652
- import { readFileSync as readFileSync3 } from "node:fs";
2653
-
2654
- // src/coordination/agents/project-agent-paths.ts
2655
- import * as path3 from "node:path";
2656
- var AGENT_ROLE_PATTERN = /^[a-z0-9][a-z0-9._-]{0,95}$/i;
2657
- function assertProjectAgentRole(role) {
2658
- const normalized = role.trim();
2659
- if (!AGENT_ROLE_PATTERN.test(normalized) || normalized === "." || normalized === ".." || normalized.includes("/") || normalized.includes("\\")) {
2660
- throw new Error(`Invalid project agent role: "${role}".`);
2661
- }
2662
- return normalized;
2663
- }
2664
- function agentsDir(projectRoot) {
2665
- const root = projectRoot ?? process.cwd();
2666
- return path3.join(root, ".wrongstack", "agents");
2667
- }
2668
- function roleDir(role, projectRoot) {
2669
- return path3.join(agentsDir(projectRoot), assertProjectAgentRole(role));
2670
- }
2671
- function learningPolicyPath(role, projectRoot) {
2672
- return path3.join(roleDir(role, projectRoot), "learning.json");
2673
- }
2674
-
2675
- // src/coordination/agents/project-agent-learning-policy.ts
2949
+ import { readFileSync as readFileSync4 } from "node:fs";
2676
2950
  var DEFAULT_LEARNING_POLICY = {
2677
2951
  enabled: true,
2678
2952
  lifetimeCaptureCount: 0
@@ -2680,7 +2954,7 @@ var DEFAULT_LEARNING_POLICY = {
2680
2954
  function loadProjectAgentLearningPolicy(role, projectRoot) {
2681
2955
  try {
2682
2956
  const parsed = JSON.parse(
2683
- readFileSync3(learningPolicyPath(role, projectRoot), "utf8")
2957
+ readFileSync4(learningPolicyPath(role, projectRoot), "utf8")
2684
2958
  );
2685
2959
  return {
2686
2960
  enabled: parsed.enabled !== false,
@@ -2693,47 +2967,6 @@ function loadProjectAgentLearningPolicy(role, projectRoot) {
2693
2967
  }
2694
2968
  }
2695
2969
 
2696
- // src/coordination/agents/project-agent-learning-entries.ts
2697
- function splitLearnedEntries(body) {
2698
- return body.split(/\n---\n+/).map((entry) => entry.trim()).map(
2699
- (entry) => entry.replace(/^# Learned wisdom for .+$/im, "").replace(/<!--[\s\S]*?-->/g, "").trim()
2700
- ).filter(Boolean);
2701
- }
2702
-
2703
- // src/coordination/agents/project-agent-consolidation.ts
2704
- import {
2705
- existsSync,
2706
- mkdirSync,
2707
- readFileSync as readFileSync4,
2708
- rmSync
2709
- } from "node:fs";
2710
- import * as path4 from "node:path";
2711
- function consolidationPath(role, projectRoot) {
2712
- return path4.join(roleDir(role, projectRoot), "consolidated.md");
2713
- }
2714
- function consolidationMetaPath(role, projectRoot) {
2715
- return path4.join(roleDir(role, projectRoot), "consolidation.json");
2716
- }
2717
- function loadProjectAgentConsolidated(role, projectRoot) {
2718
- try {
2719
- return readFileSync4(consolidationPath(role, projectRoot), "utf8").trim();
2720
- } catch {
2721
- return "";
2722
- }
2723
- }
2724
- function loadConsolidationMetadata(role, projectRoot) {
2725
- try {
2726
- const raw = readFileSync4(consolidationMetaPath(role, projectRoot), "utf8");
2727
- const parsed = JSON.parse(raw);
2728
- if (typeof parsed === "object" && parsed !== null && typeof parsed.consolidatedAt === "string" && typeof parsed.sourceEntryCount === "number") {
2729
- return parsed;
2730
- }
2731
- return void 0;
2732
- } catch {
2733
- return void 0;
2734
- }
2735
- }
2736
-
2737
2970
  // src/coordination/agents/project-agent-identity.ts
2738
2971
  function loadProjectAgentIdentity(role, projectRoot) {
2739
2972
  const identityPath = path5.join(roleDir(role, projectRoot), "identity.md");
@@ -3062,6 +3295,64 @@ function isDirectory2(candidate) {
3062
3295
  }
3063
3296
  }
3064
3297
 
3298
+ // src/coordination/agents/types.ts
3299
+ var HOUR = 60 * 60 * 1e3;
3300
+ var LIGHT_BUDGET = {
3301
+ timeoutMs: 3 * HOUR,
3302
+ maxIterations: 3e3,
3303
+ maxToolCalls: 8e3
3304
+ };
3305
+ var MEDIUM_BUDGET = {
3306
+ timeoutMs: 5 * HOUR,
3307
+ maxIterations: 5e3,
3308
+ maxToolCalls: 14e3
3309
+ };
3310
+ var HEAVY_BUDGET = {
3311
+ timeoutMs: 10 * HOUR,
3312
+ maxIterations: 8e3,
3313
+ maxToolCalls: 2e4
3314
+ };
3315
+ var TOOLS = {
3316
+ /** Pure read/inspect — safe for analysis and review agents. */
3317
+ read: ["read", "grep", "glob", "search", "tree", "mailbox"],
3318
+ /** Read + structured inspection (logs, diffs, json, dependency audit). */
3319
+ inspect: ["read", "grep", "glob", "search", "tree", "json", "diff", "logs", "audit", "mailbox"],
3320
+ /** Read + edit (no shell). For agents that write code/docs but don't run it. */
3321
+ write: ["read", "grep", "glob", "search", "tree", "write", "edit", "replace", "patch", "mailbox"],
3322
+ /** Full build loop: edit + run (lint/format/typecheck/test/bash). */
3323
+ build: [
3324
+ "read",
3325
+ "grep",
3326
+ "glob",
3327
+ "search",
3328
+ "tree",
3329
+ "write",
3330
+ "edit",
3331
+ "replace",
3332
+ "patch",
3333
+ "bash",
3334
+ "exec",
3335
+ "lint",
3336
+ "format",
3337
+ "typecheck",
3338
+ "test",
3339
+ "mailbox"
3340
+ ],
3341
+ /** Version control. */
3342
+ vcs: ["read", "grep", "glob", "git", "diff"],
3343
+ /** Dependency management + CVE audit. */
3344
+ deps: ["read", "grep", "glob", "install", "outdated", "audit", "json", "mailbox"],
3345
+ /** Documentation authoring. */
3346
+ docs: ["read", "grep", "glob", "search", "tree", "write", "edit", "document", "mailbox"],
3347
+ /** Web research. */
3348
+ research: ["read", "grep", "glob", "search", "fetch", "mailbox"]
3349
+ };
3350
+ var SPECIALIST_TOOLS = {
3351
+ browser: toolsForRuntimeCapabilities(["browser.interact"]),
3352
+ memory: toolsForRuntimeCapabilities(["memory.manage"]),
3353
+ mcp: toolsForRuntimeCapabilities(["mcp.dynamic"])
3354
+ };
3355
+
3065
3356
  // src/coordination/agents/phase1-discovery.ts
3066
3357
  var DISCOVERY_AGENTS = [
3067
3358
  {
@@ -3097,7 +3388,7 @@ var DISCOVERY_AGENTS = [
3097
3388
  id: "search",
3098
3389
  name: "Search",
3099
3390
  role: "search",
3100
- tools: [...TOOLS.read],
3391
+ tools: [...TOOLS.read, "codebase-search"],
3101
3392
  prompt: agentPrompt("search")
3102
3393
  },
3103
3394
  budget: MEDIUM_BUDGET,
@@ -3559,14 +3850,7 @@ var WAVE1_AGENTS = [
3559
3850
  capability: {
3560
3851
  phase: "domain",
3561
3852
  summary: "Android platform specialist: Kotlin, Jetpack Compose, Android SDK, lifecycle and Play Store delivery.",
3562
- keywords: [
3563
- ...ANDROID_META.signals,
3564
- "android",
3565
- "kotlin",
3566
- "compose",
3567
- "gradle",
3568
- "playstore"
3569
- ]
3853
+ keywords: [...ANDROID_META.signals, "android", "kotlin", "compose", "gradle", "playstore"]
3570
3854
  }
3571
3855
  },
3572
3856
  {
@@ -3581,14 +3865,7 @@ var WAVE1_AGENTS = [
3581
3865
  capability: {
3582
3866
  phase: "domain",
3583
3867
  summary: "Desktop application specialist: Electron or Tauri, native packaging, IPC and OS integration.",
3584
- keywords: [
3585
- ...DESKTOP_META.signals,
3586
- "desktop",
3587
- "electron",
3588
- "tauri",
3589
- "ipc",
3590
- "tray"
3591
- ]
3868
+ keywords: [...DESKTOP_META.signals, "desktop", "electron", "tauri", "ipc", "tray"]
3592
3869
  }
3593
3870
  },
3594
3871
  {
@@ -3664,7 +3941,7 @@ var WAVE1_AGENTS = [
3664
3941
  id: "platform-engineer",
3665
3942
  name: "Platform Engineer",
3666
3943
  role: "platform-engineer",
3667
- tools: [...TOOLS.build, "install", "git", "node-modern"],
3944
+ tools: [...TOOLS.build, "install", "git"],
3668
3945
  prompt: agentPrompt("platform-engineer")
3669
3946
  },
3670
3947
  budget: MEDIUM_BUDGET,
@@ -3908,8 +4185,7 @@ var WAVE2_AGENTS = [
3908
4185
  id: "resilience-engineer",
3909
4186
  name: "Resilience Engineer",
3910
4187
  role: "resilience-engineer",
3911
- tools: [...TOOLS.build, "logs", "observability"],
3912
- // uniqueness guaranteed by 'observability' vs chaos-engineer's 'test'
4188
+ tools: [...TOOLS.build, "logs"],
3913
4189
  prompt: agentPrompt("resilience-engineer")
3914
4190
  },
3915
4191
  budget: MEDIUM_BUDGET,
@@ -3932,8 +4208,7 @@ var WAVE2_AGENTS = [
3932
4208
  id: "chaos-engineer",
3933
4209
  name: "Chaos Engineer",
3934
4210
  role: "chaos-engineer",
3935
- tools: [...TOOLS.build, "logs", "observability"],
3936
- // uniqueness guaranteed by 'observability' vs chaos-engineer's 'test'
4211
+ tools: [...TOOLS.build, "logs"],
3937
4212
  prompt: agentPrompt("chaos-engineer")
3938
4213
  },
3939
4214
  budget: MEDIUM_BUDGET,
@@ -4074,21 +4349,7 @@ var VERIFY_AGENTS = [
4074
4349
  id: "e2e",
4075
4350
  name: "E2E",
4076
4351
  role: "e2e",
4077
- tools: [
4078
- ...TOOLS.build,
4079
- "fetch",
4080
- "playwright_navigate",
4081
- "playwright_screenshot",
4082
- "playwright_click",
4083
- "playwright_type",
4084
- "playwright_evaluate",
4085
- "playwright_select_option",
4086
- "playwright_hover",
4087
- "playwright_fill_form",
4088
- "playwright_wait_for",
4089
- "playwright_press_key",
4090
- "playwright_drag"
4091
- ],
4352
+ tools: [...TOOLS.build, "fetch", ...SPECIALIST_TOOLS.browser],
4092
4353
  prompt: agentPrompt("e2e")
4093
4354
  },
4094
4355
  budget: HEAVY_BUDGET,
@@ -4123,21 +4384,7 @@ var VERIFY_AGENTS = [
4123
4384
  id: "browser",
4124
4385
  name: "Browser",
4125
4386
  role: "browser",
4126
- tools: [
4127
- ...TOOLS.read,
4128
- "fetch",
4129
- "playwright_navigate",
4130
- "playwright_screenshot",
4131
- "playwright_click",
4132
- "playwright_type",
4133
- "playwright_evaluate",
4134
- "playwright_select_option",
4135
- "playwright_hover",
4136
- "playwright_fill_form",
4137
- "playwright_wait_for",
4138
- "playwright_press_key",
4139
- "playwright_drag"
4140
- ],
4387
+ tools: [...TOOLS.read, "fetch", ...SPECIALIST_TOOLS.browser],
4141
4388
  prompt: agentPrompt("browser")
4142
4389
  },
4143
4390
  budget: MEDIUM_BUDGET,
@@ -4838,27 +5085,7 @@ var DELIVERY_AGENTS = [
4838
5085
  id: "devops",
4839
5086
  name: "DevOps",
4840
5087
  role: "devops",
4841
- tools: [
4842
- ...TOOLS.build,
4843
- "mcp__ssh__ssh_list_servers",
4844
- "mcp__ssh__ssh_connection_status",
4845
- "mcp__ssh__ssh_execute",
4846
- "mcp__ssh__ssh_execute_sudo",
4847
- "mcp__ssh__ssh_upload",
4848
- "mcp__ssh__ssh_download",
4849
- "mcp__ssh__ssh_sync",
4850
- "mcp__ssh__ssh_deploy",
4851
- "mcp__ssh__ssh_health_check",
4852
- "mcp__ssh__ssh_service_status",
4853
- "mcp__ssh__ssh_process_manager",
4854
- "mcp__ssh__ssh_tunnel",
4855
- "mcp__ssh__ssh_backup_create",
4856
- "mcp__ssh__ssh_backup_list",
4857
- "mcp__ssh__ssh_backup_restore",
4858
- "mcp__ssh__ssh_db_list",
4859
- "mcp__ssh__ssh_db_query",
4860
- "mcp__ssh__ssh_profile"
4861
- ],
5088
+ tools: [...TOOLS.build, ...SPECIALIST_TOOLS.mcp],
4862
5089
  prompt: agentPrompt("devops")
4863
5090
  },
4864
5091
  budget: MEDIUM_BUDGET,
@@ -5059,7 +5286,7 @@ var WAVE3_AGENTS = [
5059
5286
  id: "messaging",
5060
5287
  name: "Messaging",
5061
5288
  role: "messaging",
5062
- tools: [...TOOLS.build, "logs", "observability"],
5289
+ tools: [...TOOLS.build, "logs"],
5063
5290
  prompt: agentPrompt("messaging")
5064
5291
  },
5065
5292
  budget: HEAVY_BUDGET,
@@ -5500,7 +5727,7 @@ var WAVE4_AGENTS = [
5500
5727
  id: "memory-curator",
5501
5728
  name: "Memory Curator",
5502
5729
  role: "memory-curator",
5503
- tools: [...TOOLS.read, "memory"],
5730
+ tools: [...TOOLS.read, ...SPECIALIST_TOOLS.memory],
5504
5731
  prompt: agentPrompt("memory-curator")
5505
5732
  },
5506
5733
  budget: LIGHT_BUDGET,
@@ -5522,7 +5749,7 @@ var WAVE4_AGENTS = [
5522
5749
  id: "fleet-coordinator",
5523
5750
  name: "Fleet Coordinator",
5524
5751
  role: "fleet-coordinator",
5525
- tools: [...TOOLS.read, "plan", "multi-agent"],
5752
+ tools: [...TOOLS.read, "plan"],
5526
5753
  prompt: agentPrompt("fleet-coordinator")
5527
5754
  },
5528
5755
  budget: MEDIUM_BUDGET,
@@ -5622,8 +5849,20 @@ var ROLE_SKILL_SETS = {
5622
5849
  cost: skillSet("audit-log", "tech-stack", "observability", "research-web"),
5623
5850
  "tech-stack": skillSet("tech-stack", "research-web", "security-scanner", "node-modern"),
5624
5851
  // ── Wave 1: Platform and systems engineering ──────────────────────────
5625
- android: skillSet("react-modern", "typescript-strict", "testing", "security-scanner", "tech-stack"),
5626
- desktop: skillSet("node-modern", "typescript-strict", "testing", "security-scanner", "tech-stack"),
5852
+ android: skillSet(
5853
+ "react-modern",
5854
+ "typescript-strict",
5855
+ "testing",
5856
+ "security-scanner",
5857
+ "tech-stack"
5858
+ ),
5859
+ desktop: skillSet(
5860
+ "node-modern",
5861
+ "typescript-strict",
5862
+ "testing",
5863
+ "security-scanner",
5864
+ "tech-stack"
5865
+ ),
5627
5866
  realtime: skillSet(
5628
5867
  "api-design",
5629
5868
  "observability",
@@ -5727,26 +5966,9 @@ var ROLE_SKILL_SETS = {
5727
5966
  "security-scanner",
5728
5967
  "tech-stack"
5729
5968
  ),
5730
- "benchmark-engineer": skillSet(
5731
- "observability",
5732
- "testing",
5733
- "output-standards",
5734
- "tech-stack"
5735
- ),
5736
- "memory-curator": skillSet(
5737
- "mnemosyne",
5738
- "audit-log",
5739
- "testing",
5740
- "output-standards",
5741
- "tech-stack"
5742
- ),
5743
- "fleet-coordinator": skillSet(
5744
- "multi-agent",
5745
- "sdd",
5746
- "output-standards",
5747
- "testing",
5748
- "tech-stack"
5749
- ),
5969
+ "benchmark-engineer": skillSet("observability", "testing", "output-standards", "tech-stack"),
5970
+ "memory-curator": skillSet("mnemosyne", "audit-log", "testing", "output-standards", "tech-stack"),
5971
+ "fleet-coordinator": skillSet("multi-agent", "sdd", "output-standards", "testing", "tech-stack"),
5750
5972
  // ── Wave 2: Security, resilience, governance and agent platform ────────
5751
5973
  "threat-modeler": skillSet(
5752
5974
  "security-scanner",
@@ -5798,6 +6020,7 @@ var SHADOW_AGENT_SKILLS = skillSet(
5798
6020
  "observability",
5799
6021
  "security-scanner"
5800
6022
  );
6023
+ var MAX_EAGER_ROSTER_SKILLS = 3;
5801
6024
  function assignSkillsToAgents(definitions) {
5802
6025
  return definitions.map((definition) => {
5803
6026
  const role = definition.config.role;
@@ -5811,7 +6034,8 @@ function assignSkillsToAgents(definitions) {
5811
6034
  ...definition,
5812
6035
  config: {
5813
6036
  ...definition.config,
5814
- skillNames: [...skills]
6037
+ capabilities: inferRuntimeCapabilities(definition.config.tools ?? []),
6038
+ skillNames: skills.slice(0, MAX_EAGER_ROSTER_SKILLS)
5815
6039
  }
5816
6040
  };
5817
6041
  });
@@ -8165,10 +8389,9 @@ var OneShotOrchestrator = class {
8165
8389
  /** Attempt a provider call while preserving the actual failure for callers. */
8166
8390
  async tryCall(provider, request, signal, providerId, model) {
8167
8391
  try {
8168
- return {
8169
- response: await provider.complete(request, { signal }),
8170
- fallbackEligible: false
8171
- };
8392
+ const direct = (req) => provider.complete(req, { signal });
8393
+ const response = this.opts.wrapProviderCall ? await this.opts.wrapProviderCall(request, direct) : await direct(request);
8394
+ return { response, fallbackEligible: false };
8172
8395
  } catch (err) {
8173
8396
  if (err instanceof ProviderError && providerId && model) {
8174
8397
  this.opts.statusTracker?.recordFailure(
@@ -8182,7 +8405,12 @@ var OneShotOrchestrator = class {
8182
8405
  }
8183
8406
  return {
8184
8407
  error: err,
8185
- fallbackEligible: !signal.aborted && (!(err instanceof ProviderError) || isFallbackWorthy(err.kind))
8408
+ // Provider failures retain their normal fallback policy. A plain error
8409
+ // thrown by the host wrapper is a local refusal (for example,
8410
+ // prompt-firewall block mode), not evidence that another provider may
8411
+ // succeed; retrying would only replay the same blocked request and
8412
+ // misattribute the final error to the last fallback.
8413
+ fallbackEligible: !signal.aborted && (err instanceof ProviderError ? isFallbackWorthy(err.kind) : this.opts.wrapProviderCall === void 0)
8186
8414
  };
8187
8415
  }
8188
8416
  }
@@ -8313,7 +8541,8 @@ function createOneShotLLMTool(opts) {
8313
8541
  getConfig: opts.getConfig,
8314
8542
  fallbackProfileManager: opts.fallbackProfileManager,
8315
8543
  modelRouter: opts.modelRouter,
8316
- logger: opts.logger
8544
+ logger: opts.logger,
8545
+ wrapProviderCall: opts.wrapProviderCall
8317
8546
  });
8318
8547
  return {
8319
8548
  name: ONE_SHOT_LLM_TOOL_NAME,
@@ -8383,6 +8612,25 @@ function isRecord2(value) {
8383
8612
  return typeof value === "object" && value !== null && !Array.isArray(value);
8384
8613
  }
8385
8614
 
8615
+ // src/security/readonly-permission-policy.ts
8616
+ var MUTATION_CAPABILITIES = /* @__PURE__ */ new Set([
8617
+ ToolCapabilities.FS_WRITE,
8618
+ ToolCapabilities.FS_WRITE_OUTSIDE_PROJECT,
8619
+ ToolCapabilities.MEMORY_WRITE,
8620
+ ToolCapabilities.MEMORY_DELETE,
8621
+ ToolCapabilities.SHELL_ARBITRARY,
8622
+ ToolCapabilities.SHELL_RESTRICTED,
8623
+ ToolCapabilities.SHELL_EXEC,
8624
+ ToolCapabilities.TOOL_MUTATE_ANY,
8625
+ ToolCapabilities.CONFIG_MUTATE,
8626
+ ToolCapabilities.PACKAGE_INSTALL,
8627
+ ToolCapabilities.SUBAGENT_SPAWN
8628
+ ]);
8629
+ function toolMutates(tool) {
8630
+ if (tool.mutating === true) return true;
8631
+ return (tool.capabilities ?? []).some((c) => MUTATION_CAPABILITIES.has(c));
8632
+ }
8633
+
8386
8634
  // src/utils/json-schema-validate.ts
8387
8635
  function validateAgainstSchema(value, schema) {
8388
8636
  const errors = [];
@@ -8698,7 +8946,36 @@ function createPluginManagerTool(opts) {
8698
8946
  directCall: { tool: tool.name, input: input.input ?? {}, inputSchema: tool.inputSchema }
8699
8947
  };
8700
8948
  }
8701
- const nestedInput = input.input ?? {};
8949
+ const dangerousCaps = getDangerousCapabilities(tool);
8950
+ if (dangerousCaps.length > 0) {
8951
+ return {
8952
+ status: "needs_direct_call",
8953
+ message: `Tool "${tool.name}" declares dangerous capabilities (${dangerousCaps.join(", ")}); the permission pipeline must rule on it. Call it directly.`,
8954
+ directCall: { tool: tool.name, input: input.input ?? {}, inputSchema: tool.inputSchema }
8955
+ };
8956
+ }
8957
+ if (ctx.meta["readOnly"] === true && toolMutates(tool)) {
8958
+ return {
8959
+ status: "needs_direct_call",
8960
+ message: `Session is in read-only mode and "${tool.name}" mutates. Call it directly so read-only mode can rule on it.`,
8961
+ directCall: { tool: tool.name, input: input.input ?? {}, inputSchema: tool.inputSchema }
8962
+ };
8963
+ }
8964
+ let nestedInput = input.input ?? {};
8965
+ const hooks = opts.getHookRunner?.();
8966
+ if (hooks) {
8967
+ const pre = await hooks.preToolUse(tool.name, nestedInput, ctx, {
8968
+ capabilities: tool.capabilities,
8969
+ mutating: tool.mutating
8970
+ });
8971
+ if (pre.block) {
8972
+ return {
8973
+ status: "error",
8974
+ message: `A policy hook blocked "${tool.name}"` + (pre.reason ? `: ${pre.reason}` : ".")
8975
+ };
8976
+ }
8977
+ if (pre.input) nestedInput = pre.input;
8978
+ }
8702
8979
  const validation = validateAgainstSchema(nestedInput, tool.inputSchema);
8703
8980
  if (!validation.ok) {
8704
8981
  return {