opencode-swarm 7.13.1 → 7.14.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 (216) hide show
  1. package/dist/cli/index.js +144 -15
  2. package/dist/commands/deep-dive.d.ts +5 -0
  3. package/dist/commands/index.d.ts +1 -0
  4. package/dist/commands/registry.d.ts +14 -0
  5. package/dist/config/evidence-schema.d.ts +13 -13
  6. package/dist/config/schema.d.ts +4 -4
  7. package/dist/index.js +422 -123
  8. package/dist/tools/convene-council.d.ts +3 -3
  9. package/dist/tools/submit-phase-council-verdicts.d.ts +3 -3
  10. package/package.json +1 -1
  11. package/dist/__tests__/acknowledge-spec-drift.test.d.ts +0 -1
  12. package/dist/__tests__/cli-version.adversarial.test.d.ts +0 -1
  13. package/dist/__tests__/cli-version.test.d.ts +0 -1
  14. package/dist/__tests__/conflict-resolution.test.d.ts +0 -1
  15. package/dist/__tests__/convene-general-council.test.d.ts +0 -12
  16. package/dist/__tests__/critic_drift_verifier-whitelist.test.d.ts +0 -1
  17. package/dist/__tests__/critic_hallucination_verifier-whitelist.test.d.ts +0 -1
  18. package/dist/__tests__/disagreement-detector.test.d.ts +0 -7
  19. package/dist/__tests__/evidence-lock.adversarial.test.d.ts +0 -8
  20. package/dist/__tests__/evidence-lock.test.d.ts +0 -6
  21. package/dist/__tests__/gate-evidence.adversarial.test.d.ts +0 -7
  22. package/dist/__tests__/general-council-service.test.d.ts +0 -7
  23. package/dist/__tests__/lint-spec.test.d.ts +0 -1
  24. package/dist/__tests__/preflight-phase.test.d.ts +0 -1
  25. package/dist/__tests__/qa-gate-hardening.test.d.ts +0 -12
  26. package/dist/__tests__/req-coverage.test.d.ts +0 -1
  27. package/dist/__tests__/security-adversarial.test.d.ts +0 -1
  28. package/dist/__tests__/sounding-board-parser.test.d.ts +0 -1
  29. package/dist/__tests__/spec-hash.test.d.ts +0 -1
  30. package/dist/__tests__/spec-schema.test.d.ts +0 -1
  31. package/dist/__tests__/web-search-provider.test.d.ts +0 -6
  32. package/dist/__tests__/write-drift-evidence-requirement-coverage.test.d.ts +0 -4
  33. package/dist/adversarial-tests.test.d.ts +0 -1
  34. package/dist/agents/architect-permission.adversarial.test.d.ts +0 -5
  35. package/dist/agents/architect.commands-list.adversarial.test.d.ts +0 -1
  36. package/dist/agents/architect.commands-list.test.d.ts +0 -1
  37. package/dist/agents/architect.dark-matter.test.d.ts +0 -1
  38. package/dist/agents/architect.designer-gate.test.d.ts +0 -1
  39. package/dist/agents/architect.skip-aliases.test.d.ts +0 -1
  40. package/dist/agents/coder.test.d.ts +0 -1
  41. package/dist/agents/council-prompts.test.d.ts +0 -9
  42. package/dist/agents/council-registration.test.d.ts +0 -23
  43. package/dist/agents/explorer-consumer-contract.test.d.ts +0 -1
  44. package/dist/agents/explorer-role-boundary.test.d.ts +0 -1
  45. package/dist/agents/prompt-namespace.test.d.ts +0 -1
  46. package/dist/agents/reviewer.test.d.ts +0 -1
  47. package/dist/agents/test-engineer.adversarial.test.d.ts +0 -5
  48. package/dist/agents/test-engineer.security.test.d.ts +0 -1
  49. package/dist/background/trigger.vulnerability.test.d.ts +0 -1
  50. package/dist/commands/archive.error-handling.test.d.ts +0 -9
  51. package/dist/commands/benchmark.error-handling.test.d.ts +0 -7
  52. package/dist/commands/brainstorm.test.d.ts +0 -1
  53. package/dist/commands/clashes-with-native-cc.test.d.ts +0 -10
  54. package/dist/commands/command-adapters.security.test.d.ts +0 -14
  55. package/dist/commands/command-names.test.d.ts +0 -1
  56. package/dist/commands/commands.test.d.ts +0 -1
  57. package/dist/commands/conflict-registry.structural.test.d.ts +0 -1
  58. package/dist/commands/conflict-registry.test.d.ts +0 -5
  59. package/dist/commands/council.test.d.ts +0 -4
  60. package/dist/commands/curate.test.d.ts +0 -1
  61. package/dist/commands/dark-matter.error-handling.test.d.ts +0 -1
  62. package/dist/commands/first-run.test.d.ts +0 -11
  63. package/dist/commands/full-auto-config-guard.test.d.ts +0 -7
  64. package/dist/commands/full-auto-discoverability.test.d.ts +0 -8
  65. package/dist/commands/full-auto-registration.test.d.ts +0 -5
  66. package/dist/commands/full-auto-sessionid.test.d.ts +0 -5
  67. package/dist/commands/full-auto.regression.test.d.ts +0 -10
  68. package/dist/commands/full-auto.test.d.ts +0 -6
  69. package/dist/commands/handoff.error-handling.adversarial.test.d.ts +0 -1
  70. package/dist/commands/handoff.error-handling.test.d.ts +0 -1
  71. package/dist/commands/index.help-text.test.d.ts +0 -1
  72. package/dist/commands/index.not-found.adversarial.test.d.ts +0 -12
  73. package/dist/commands/index.not-found.test.d.ts +0 -11
  74. package/dist/commands/qa-gates.test.d.ts +0 -1
  75. package/dist/commands/registration-parity.test.d.ts +0 -1
  76. package/dist/commands/registry-documentation.test.d.ts +0 -1
  77. package/dist/commands/registry-type.test.d.ts +0 -1
  78. package/dist/commands/registry.find-similar.adversarial.test.d.ts +0 -1
  79. package/dist/commands/registry.find-similar.test.d.ts +0 -1
  80. package/dist/commands/registry.test.d.ts +0 -1
  81. package/dist/commands/shortcut-routing.test.d.ts +0 -11
  82. package/dist/commands/simulate.report-write.adversarial.test.d.ts +0 -1
  83. package/dist/commands/simulate.report-write.test.d.ts +0 -1
  84. package/dist/commands/turbo-registration.test.d.ts +0 -5
  85. package/dist/commands/turbo-sessionid.test.d.ts +0 -5
  86. package/dist/commands/turbo.regression.test.d.ts +0 -11
  87. package/dist/commands/turbo.test.d.ts +0 -5
  88. package/dist/config/constants.architect-whitelist.test.d.ts +0 -1
  89. package/dist/config/constants.security.test.d.ts +0 -1
  90. package/dist/council/__tests__/council-evidence-writer.adversarial.test.d.ts +0 -6
  91. package/dist/db/global-db.test.d.ts +0 -7
  92. package/dist/db/project-db.test.d.ts +0 -4
  93. package/dist/db/qa-gate-profile.test.d.ts +0 -4
  94. package/dist/diff/__tests__/semantic-classifier.test.d.ts +0 -1
  95. package/dist/diff/__tests__/summary-generator.test.d.ts +0 -1
  96. package/dist/gate-evidence.test.d.ts +0 -1
  97. package/dist/hooks/__tests__/repo-graph-builder.test.d.ts +0 -12
  98. package/dist/hooks/__tests__/semantic-diff-injection.test.d.ts +0 -1
  99. package/dist/hooks/agent-activity.test.d.ts +0 -1
  100. package/dist/hooks/cc-command-intercept.test.d.ts +0 -1
  101. package/dist/hooks/curator-drift-advisory.test.d.ts +0 -1
  102. package/dist/hooks/delegation-gate.evidence.test.d.ts +0 -4
  103. package/dist/hooks/delegation-gate.getEvidenceTaskId.test.d.ts +0 -20
  104. package/dist/hooks/delegation-gate.plan-fallback-security.test.d.ts +0 -13
  105. package/dist/hooks/delegation-gate.plan-fallback.test.d.ts +0 -5
  106. package/dist/hooks/delegation-gate.seed-state.test.d.ts +0 -1
  107. package/dist/hooks/delegation-gate.turbo-evidence.test.d.ts +0 -8
  108. package/dist/hooks/delegation-gate.verify.test.d.ts +0 -11
  109. package/dist/hooks/delegation-ledger.test.d.ts +0 -11
  110. package/dist/hooks/diff-scope.test.d.ts +0 -1
  111. package/dist/hooks/incremental-verify.test.d.ts +0 -1
  112. package/dist/hooks/loop-detector.test.d.ts +0 -1
  113. package/dist/hooks/scope-guard-throw-behavior.test.d.ts +0 -15
  114. package/dist/hooks/scope-guard.adversarial.test.d.ts +0 -1
  115. package/dist/hooks/scope-guard.test.d.ts +0 -14
  116. package/dist/hooks/self-review.test.d.ts +0 -14
  117. package/dist/hooks/slop-detector.adversarial.test.d.ts +0 -1
  118. package/dist/hooks/slop-detector.test.d.ts +0 -1
  119. package/dist/hooks/spawn-helper.test.d.ts +0 -1
  120. package/dist/hooks/watchdog.integration.test.d.ts +0 -9
  121. package/dist/index.adversarial-bootstrap.test.d.ts +0 -1
  122. package/dist/index.bootstrap-adversarial.test.d.ts +0 -1
  123. package/dist/index.bootstrap-directory.test.d.ts +0 -1
  124. package/dist/model-fallback.adversarial.test.d.ts +0 -22
  125. package/dist/model-fallback.test.d.ts +0 -12
  126. package/dist/mutation/__tests__/engine.adversarial.test.d.ts +0 -1
  127. package/dist/mutation/__tests__/engine.test.d.ts +0 -1
  128. package/dist/mutation/__tests__/equivalence.adversarial.test.d.ts +0 -1
  129. package/dist/mutation/__tests__/equivalence.test.d.ts +0 -1
  130. package/dist/mutation/__tests__/gate.adversarial.test.d.ts +0 -1
  131. package/dist/mutation/__tests__/gate.test.d.ts +0 -1
  132. package/dist/mutation/__tests__/generator.test.d.ts +0 -1
  133. package/dist/parallel/dispatcher/noop-dispatcher.test.d.ts +0 -10
  134. package/dist/plan/checkpoint.test.d.ts +0 -1
  135. package/dist/plan/ledger-integrity.test.d.ts +0 -5
  136. package/dist/plan/ledger-snapshot-adversarial.test.d.ts +0 -1
  137. package/dist/plan/ledger.test.d.ts +0 -1
  138. package/dist/plan/manager.cas-backoff.test.d.ts +0 -10
  139. package/dist/plan/manager.ledger-aware.test.d.ts +0 -1
  140. package/dist/plan/manager.loadplan-validation-guard.test.d.ts +0 -13
  141. package/dist/plan/manager.update-task-status.test.d.ts +0 -1
  142. package/dist/plan/migration-revert.regression.test.d.ts +0 -8
  143. package/dist/prm/__tests__/course-correction.test.d.ts +0 -1
  144. package/dist/prm/__tests__/escalation-queue-drain.test.d.ts +0 -1
  145. package/dist/prm/__tests__/escalation.test.d.ts +0 -1
  146. package/dist/prm/__tests__/index.test.d.ts +0 -1
  147. package/dist/prm/__tests__/integration.test.d.ts +0 -1
  148. package/dist/prm/__tests__/pattern-detector.test.d.ts +0 -5
  149. package/dist/prm/__tests__/replay.test.d.ts +0 -1
  150. package/dist/prm/__tests__/trajectory-store.test.d.ts +0 -7
  151. package/dist/sast/semgrep.test.d.ts +0 -1
  152. package/dist/scope/scope-persistence.test.d.ts +0 -13
  153. package/dist/services/compaction-service.test.d.ts +0 -1
  154. package/dist/services/config-doctor.security.test.d.ts +0 -1
  155. package/dist/services/config-doctor.test.d.ts +0 -1
  156. package/dist/services/status-service.turbo-indicator.test.d.ts +0 -5
  157. package/dist/services/tool-doctor.test.d.ts +0 -1
  158. package/dist/state.agent-run-context.test.d.ts +0 -10
  159. package/dist/state.rehydrate.test.d.ts +0 -1
  160. package/dist/state.rehydration-adversarial.test.d.ts +0 -1
  161. package/dist/state.rehydration-integration.test.d.ts +0 -1
  162. package/dist/state.session-restart.test.d.ts +0 -7
  163. package/dist/state.telemetry.test.d.ts +0 -1
  164. package/dist/telemetry.test.d.ts +0 -1
  165. package/dist/test-impact/__tests__/analyzer-import-fix.adversarial.test.d.ts +0 -1
  166. package/dist/test-impact/__tests__/analyzer-import-fix.test.d.ts +0 -1
  167. package/dist/test-impact/__tests__/analyzer.adversarial.test.d.ts +0 -1
  168. package/dist/test-impact/__tests__/analyzer.test.d.ts +0 -1
  169. package/dist/test-impact/__tests__/council-fixes.test.d.ts +0 -1
  170. package/dist/test-impact/__tests__/failure-classifier.adversarial.test.d.ts +0 -1
  171. package/dist/test-impact/__tests__/failure-classifier.test.d.ts +0 -1
  172. package/dist/test-impact/__tests__/flaky-detector.adversarial.test.d.ts +0 -1
  173. package/dist/test-impact/__tests__/flaky-detector.test.d.ts +0 -1
  174. package/dist/test-impact/__tests__/history-store.adversarial.test.d.ts +0 -1
  175. package/dist/test-impact/__tests__/history-store.test.d.ts +0 -1
  176. package/dist/test-impact/__tests__/test-impact.adversarial.test.d.ts +0 -1
  177. package/dist/test-impact/__tests__/test-impact.test.d.ts +0 -1
  178. package/dist/tools/__tests__/barrel-exports.test.d.ts +0 -1
  179. package/dist/tools/__tests__/diff-ast-fallback.test.d.ts +0 -1
  180. package/dist/tools/__tests__/diff-markdown-summary.test.d.ts +0 -1
  181. package/dist/tools/__tests__/diff-semantic.test.d.ts +0 -1
  182. package/dist/tools/__tests__/diff-summary.adversarial.test.d.ts +0 -1
  183. package/dist/tools/__tests__/diff-summary.test.d.ts +0 -1
  184. package/dist/tools/__tests__/mutation-test.adversarial.test.d.ts +0 -1
  185. package/dist/tools/__tests__/mutation-test.sourcefiles.test.d.ts +0 -1
  186. package/dist/tools/__tests__/mutation-test.test.d.ts +0 -1
  187. package/dist/tools/__tests__/repo-graph-walk.test.d.ts +0 -16
  188. package/dist/tools/__tests__/test-runner-history.test.d.ts +0 -1
  189. package/dist/tools/__tests__/test-runner-impact.adversarial.test.d.ts +0 -1
  190. package/dist/tools/__tests__/test-runner-impact.test.d.ts +0 -1
  191. package/dist/tools/__tests__/test-runner-source-files.test.d.ts +0 -1
  192. package/dist/tools/barrel-export-check-gate-status.test.d.ts +0 -6
  193. package/dist/tools/batch-symbols.test.d.ts +0 -1
  194. package/dist/tools/check-gate-status.adversarial.test.d.ts +0 -1
  195. package/dist/tools/check-gate-status.gates.test.d.ts +0 -1
  196. package/dist/tools/check-gate-status.plugin-registration.test.d.ts +0 -1
  197. package/dist/tools/curator-analyze.test.d.ts +0 -1
  198. package/dist/tools/knowledge-tools.integration.test.d.ts +0 -1
  199. package/dist/tools/mutation-test.security.test.d.ts +0 -1
  200. package/dist/tools/plugin-registration-adversarial.test.d.ts +0 -1
  201. package/dist/tools/resolve-working-directory.test.d.ts +0 -1
  202. package/dist/tools/save-plan.subdirectory-rejection.test.d.ts +0 -1
  203. package/dist/tools/search.adversarial.test.d.ts +0 -1
  204. package/dist/tools/search.test.d.ts +0 -1
  205. package/dist/tools/suggest-patch.adversarial.test.d.ts +0 -1
  206. package/dist/tools/suggest-patch.test.d.ts +0 -1
  207. package/dist/tools/test-runner.security-adversarial.test.d.ts +0 -5
  208. package/dist/tools/update-task-status.adversarial.test.d.ts +0 -13
  209. package/dist/tools/update-task-status.gates.test.d.ts +0 -1
  210. package/dist/tools/update-task-status.test.d.ts +0 -1
  211. package/dist/tools/update-task-status.turbo-bypass.test.d.ts +0 -1
  212. package/dist/tools/verify-six-tools-registration.test.d.ts +0 -9
  213. package/dist/tools/write-mutation-evidence.test.d.ts +0 -1
  214. package/dist/transient-retry.test.d.ts +0 -10
  215. package/dist/utils/__tests__/bun-compat.test.d.ts +0 -11
  216. package/dist/utils/__tests__/timeout.test.d.ts +0 -12
package/dist/index.js CHANGED
@@ -33,7 +33,7 @@ var package_default;
33
33
  var init_package = __esm(() => {
34
34
  package_default = {
35
35
  name: "opencode-swarm",
36
- version: "7.13.1",
36
+ version: "7.14.0",
37
37
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
38
38
  main: "dist/index.js",
39
39
  types: "dist/index.d.ts",
@@ -46041,6 +46041,118 @@ var init_dark_matter = __esm(() => {
46041
46041
  init_co_change_analyzer();
46042
46042
  });
46043
46043
 
46044
+ // src/commands/deep-dive.ts
46045
+ function sanitizeScope(raw) {
46046
+ const collapsed = raw.replace(/\s+/g, " ").trim();
46047
+ const stripped = collapsed.replace(/\[\s*MODE\s*:[^\]]*\]/gi, "");
46048
+ const normalized = stripped.replace(/\s+/g, " ").trim();
46049
+ if (normalized.length <= MAX_SCOPE_LEN)
46050
+ return normalized;
46051
+ return `${normalized.slice(0, MAX_SCOPE_LEN)}…`;
46052
+ }
46053
+ function isValidPositiveInteger(raw) {
46054
+ if (!raw || !/^\d+$/.test(raw))
46055
+ return false;
46056
+ const n = Number(raw);
46057
+ if (!Number.isFinite(n) || !Number.isInteger(n) || n < 0)
46058
+ return false;
46059
+ return true;
46060
+ }
46061
+ function parseArgs2(args2) {
46062
+ const result = {
46063
+ profile: DEFAULT_PROFILE,
46064
+ maxExplorers: DEFAULT_MAX_EXPLORERS,
46065
+ output: "markdown",
46066
+ updateMain: true,
46067
+ allowDirty: false,
46068
+ rest: []
46069
+ };
46070
+ let i2 = 0;
46071
+ while (i2 < args2.length) {
46072
+ const token = args2[i2];
46073
+ if (token === "--profile") {
46074
+ if (i2 + 1 >= args2.length) {
46075
+ return { ...result, error: `Flag "${token}" requires a value` };
46076
+ }
46077
+ const value = args2[++i2];
46078
+ if (!PROFILES.has(value)) {
46079
+ return {
46080
+ ...result,
46081
+ error: `Invalid profile "${value}". Must be one of: standard, security, ux, architecture, full.`
46082
+ };
46083
+ }
46084
+ result.profile = value;
46085
+ } else if (token === "--max-explorers") {
46086
+ if (i2 + 1 >= args2.length) {
46087
+ return { ...result, error: `Flag "${token}" requires a value` };
46088
+ }
46089
+ const value = args2[++i2];
46090
+ if (!isValidPositiveInteger(value) || value.includes(".") || value.startsWith("0x") || value.startsWith("0X") || Number(value) < 1 || Number(value) > 8) {
46091
+ return {
46092
+ ...result,
46093
+ error: `Invalid --max-explorers value "${value}". Must be an integer between 1 and 8.`
46094
+ };
46095
+ }
46096
+ result.maxExplorers = Number(value);
46097
+ result.maxExplorersExplicit = true;
46098
+ } else if (token === "--json") {
46099
+ result.output = "json";
46100
+ } else if (token === "--skip-update") {
46101
+ result.updateMain = false;
46102
+ } else if (token === "--allow-dirty") {
46103
+ result.allowDirty = true;
46104
+ } else if (token.startsWith("--")) {
46105
+ return { ...result, error: `Unknown flag "${token}"` };
46106
+ } else {
46107
+ result.rest.push(token);
46108
+ }
46109
+ i2++;
46110
+ }
46111
+ return result;
46112
+ }
46113
+ async function handleDeepDiveCommand(_directory, args2) {
46114
+ const parsed = parseArgs2(args2);
46115
+ if (parsed.error) {
46116
+ return `Error: ${parsed.error}
46117
+
46118
+ ${USAGE2}`;
46119
+ }
46120
+ const scope = sanitizeScope(parsed.rest.join(" "));
46121
+ if (!scope) {
46122
+ return USAGE2;
46123
+ }
46124
+ if (parsed.profile === "full" && !parsed.maxExplorersExplicit) {
46125
+ parsed.maxExplorers = FULL_PROFILE_DEFAULT_MAX_EXPLORERS;
46126
+ }
46127
+ const header = `[MODE: DEEP_DIVE profile=${parsed.profile} max_explorers=${parsed.maxExplorers} output=${parsed.output} update_main=${parsed.updateMain} allow_dirty=${parsed.allowDirty}] ${scope}`;
46128
+ return header;
46129
+ }
46130
+ var MAX_SCOPE_LEN = 2000, PROFILES, DEFAULT_PROFILE = "standard", DEFAULT_MAX_EXPLORERS = 6, FULL_PROFILE_DEFAULT_MAX_EXPLORERS = 8, USAGE2 = `Usage: /swarm deep-dive <scope> [--profile standard|security|ux|architecture|full] [--max-explorers N] [--json] [--skip-update] [--allow-dirty]
46131
+
46132
+ Run a bounded, evidence-backed deep dive on an application section.
46133
+
46134
+ Examples:
46135
+ /swarm deep-dive auth
46136
+ /swarm deep dive src/commands --profile architecture
46137
+ /swarm deep-dive "settings page" --profile ux
46138
+ /swarm deep-dive src/security --profile security --max-explorers 5
46139
+
46140
+ Flags:
46141
+ --profile <name> standard, security, ux, architecture, or full
46142
+ --max-explorers <N> explorer runs per wave, 1..8
46143
+ --json include machine-readable JSON in the final report
46144
+ --skip-update skip the repo update-to-main preflight
46145
+ --allow-dirty allow audit to proceed with dirty worktree`;
46146
+ var init_deep_dive = __esm(() => {
46147
+ PROFILES = new Set([
46148
+ "standard",
46149
+ "security",
46150
+ "ux",
46151
+ "architecture",
46152
+ "full"
46153
+ ]);
46154
+ });
46155
+
46044
46156
  // src/config/cache-paths.ts
46045
46157
  import * as os5 from "node:os";
46046
46158
  import * as path25 from "node:path";
@@ -50995,7 +51107,7 @@ function validateAndSanitizeUrl(rawUrl) {
50995
51107
  return { error: "Invalid URL format" };
50996
51108
  }
50997
51109
  }
50998
- function parseArgs2(args2) {
51110
+ function parseArgs3(args2) {
50999
51111
  const out2 = {
51000
51112
  plan: false,
51001
51113
  trace: false,
@@ -51086,24 +51198,24 @@ function parseGitRemoteUrl(remoteUrl) {
51086
51198
  return null;
51087
51199
  }
51088
51200
  function handleIssueCommand(_directory, args2) {
51089
- const parsed = parseArgs2(args2);
51201
+ const parsed = parseArgs3(args2);
51090
51202
  const rawInput = parsed.rest.join(" ").trim();
51091
51203
  if (!rawInput) {
51092
- return USAGE2;
51204
+ return USAGE3;
51093
51205
  }
51094
51206
  const isFullUrl = /^https?:\/\//i.test(rawInput);
51095
51207
  const issueInfo = parseIssueRef(isFullUrl ? sanitizeUrl(rawInput) : rawInput);
51096
51208
  if (!issueInfo) {
51097
51209
  return `Error: Could not parse issue reference from "${rawInput}"
51098
51210
 
51099
- ${USAGE2}`;
51211
+ ${USAGE3}`;
51100
51212
  }
51101
51213
  const issueUrl = `https://github.com/${issueInfo.owner}/${issueInfo.repo}/issues/${issueInfo.number}`;
51102
51214
  const result = validateAndSanitizeUrl(issueUrl);
51103
51215
  if ("error" in result) {
51104
51216
  return `Error: ${result.error}
51105
51217
 
51106
- ${USAGE2}`;
51218
+ ${USAGE3}`;
51107
51219
  }
51108
51220
  const flags2 = [];
51109
51221
  if (parsed.plan)
@@ -51115,9 +51227,9 @@ ${USAGE2}`;
51115
51227
  const flagsStr = flags2.length > 0 ? ` ${flags2.join(" ")}` : "";
51116
51228
  return `[MODE: ISSUE_INGEST issue="${result.sanitized}"${flagsStr}]`;
51117
51229
  }
51118
- var MAX_URL_LEN = 2048, USAGE2;
51230
+ var MAX_URL_LEN = 2048, USAGE3;
51119
51231
  var init_issue = __esm(() => {
51120
- USAGE2 = [
51232
+ USAGE3 = [
51121
51233
  "Usage: /swarm issue <url|owner/repo#N|N> [--plan] [--trace] [--no-repro]",
51122
51234
  "",
51123
51235
  "Ingest a GitHub issue into the swarm workflow.",
@@ -51734,7 +51846,7 @@ function validateAndSanitizeUrl2(rawUrl) {
51734
51846
  return { error: "Invalid URL format" };
51735
51847
  }
51736
51848
  }
51737
- function parseArgs3(args2) {
51849
+ function parseArgs4(args2) {
51738
51850
  const out2 = { council: false, rest: [] };
51739
51851
  for (const token of args2) {
51740
51852
  if (token === "--council") {
@@ -51818,31 +51930,31 @@ function parseGitRemoteUrl2(remoteUrl) {
51818
51930
  return null;
51819
51931
  }
51820
51932
  function handlePrReviewCommand(_directory, args2) {
51821
- const parsed = parseArgs3(args2);
51933
+ const parsed = parseArgs4(args2);
51822
51934
  const rawInput = parsed.rest.join(" ").trim();
51823
51935
  if (!rawInput) {
51824
- return USAGE3;
51936
+ return USAGE4;
51825
51937
  }
51826
51938
  const isFullUrl = /^https?:\/\//i.test(rawInput);
51827
51939
  const prInfo = parsePrRef(isFullUrl ? sanitizeUrl2(rawInput) : rawInput);
51828
51940
  if (!prInfo) {
51829
51941
  return `Error: Could not parse PR reference from "${rawInput}"
51830
51942
 
51831
- ${USAGE3}`;
51943
+ ${USAGE4}`;
51832
51944
  }
51833
51945
  const prUrl = `https://github.com/${prInfo.owner}/${prInfo.repo}/pull/${prInfo.number}`;
51834
51946
  const result = validateAndSanitizeUrl2(prUrl);
51835
51947
  if ("error" in result) {
51836
51948
  return `Error: ${result.error}
51837
51949
 
51838
- ${USAGE3}`;
51950
+ ${USAGE4}`;
51839
51951
  }
51840
51952
  const councilFlag = parsed.council ? "council=true" : "council=false";
51841
51953
  return `[MODE: PR_REVIEW pr="${result.sanitized}" ${councilFlag}]`;
51842
51954
  }
51843
- var MAX_URL_LEN2 = 2048, USAGE3;
51955
+ var MAX_URL_LEN2 = 2048, USAGE4;
51844
51956
  var init_pr_review = __esm(() => {
51845
- USAGE3 = [
51957
+ USAGE4 = [
51846
51958
  "Usage: /swarm pr-review <url|owner/repo#N|N> [--council]",
51847
51959
  "",
51848
51960
  "Run a full swarm PR review on a GitHub pull request.",
@@ -57572,6 +57684,7 @@ __export(exports_commands, {
57572
57684
  handleEvidenceCommand: () => handleEvidenceCommand,
57573
57685
  handleDoctorCommand: () => handleDoctorCommand,
57574
57686
  handleDiagnoseCommand: () => handleDiagnoseCommand,
57687
+ handleDeepDiveCommand: () => handleDeepDiveCommand,
57575
57688
  handleDarkMatterCommand: () => handleDarkMatterCommand,
57576
57689
  handleCurateCommand: () => handleCurateCommand,
57577
57690
  handleCouncilCommand: () => handleCouncilCommand,
@@ -57775,6 +57888,7 @@ var init_commands = __esm(() => {
57775
57888
  init_council();
57776
57889
  init_curate();
57777
57890
  init_dark_matter();
57891
+ init_deep_dive();
57778
57892
  init_diagnose();
57779
57893
  init_doctor();
57780
57894
  init_evidence();
@@ -57992,6 +58106,7 @@ var init_registry = __esm(() => {
57992
58106
  init_council();
57993
58107
  init_curate();
57994
58108
  init_dark_matter();
58109
+ init_deep_dive();
57995
58110
  init_diagnose();
57996
58111
  init_doctor();
57997
58112
  init_evidence();
@@ -58271,6 +58386,20 @@ var init_registry = __esm(() => {
58271
58386
  details: "Launches a structured PR review: reconstructs PR intent via obligation extraction cascade, runs 6 parallel explorer lanes (correctness, security, dependencies, docs-intent-vs-actual, tests, performance-architecture), validates findings through independent reviewer confirmation, applies critic challenge to HIGH/CRITICAL findings, synthesizes structured report. --council variant fires adversarial multi-model review. Supports full GitHub URL, owner/repo#N shorthand, or bare PR number (resolves against origin remote).",
58272
58387
  category: "agent"
58273
58388
  },
58389
+ "deep-dive": {
58390
+ handler: async (ctx) => handleDeepDiveCommand(ctx.directory, ctx.args),
58391
+ description: "Launch deep codebase audit with parallel explorer waves, dual reviewers, and critic challenge [scope]",
58392
+ args: "<scope> [--profile standard|security|ux|architecture|full] [--max-explorers 1..8] [--json] [--skip-update] [--allow-dirty]",
58393
+ details: "Runs a read-only deep audit of the specified scope using parallel explorer waves (8-file cap per mission, ~3500 line guardrail), always 2 parallel reviewers for verification, and sequential critic challenge on HIGH/CRITICAL findings. Profiles select explorer lanes: standard (5 lanes), security, ux, architecture, full (all 8 lanes). Emits a structured findings report without mutating source code.",
58394
+ category: "agent"
58395
+ },
58396
+ "deep dive": {
58397
+ handler: async (ctx) => handleDeepDiveCommand(ctx.directory, ctx.args),
58398
+ description: "Alias for /swarm deep-dive — launch deep codebase audit",
58399
+ args: "<scope> [--profile standard|security|ux|architecture|full] [--max-explorers 1..8] [--json] [--skip-update] [--allow-dirty]",
58400
+ category: "agent",
58401
+ aliasOf: "deep-dive"
58402
+ },
58274
58403
  issue: {
58275
58404
  handler: async (ctx) => handleIssueCommand(ctx.directory, ctx.args),
58276
58405
  description: "Ingest a GitHub issue into the swarm workflow [url] [--plan] [--trace] [--no-repro]",
@@ -59767,7 +59896,130 @@ Do NOT share other agents' responses at this stage.
59767
59896
  - CITE THE STRONGEST SOURCES: link key claims with [title](url) format from the source list in the synthesis. Pick the most reputable source per claim; do not cite duplicates.
59768
59897
  - BE CONCISE: a few short paragraphs plus a bulleted summary. Expand only when the question genuinely requires it.
59769
59898
  - HARD CONSTRAINTS: You MUST NOT invent claims not present in the council's responses. You MUST NOT add new web research. You MUST NOT favor a position based on confidence alone.
59770
- Preface the answer with one line listing the participating models (reviewer model as generalist, critic model as skeptic, SME model as domain expert). Do NOT present raw per-member JSON.
59899
+ Preface the answer with one line listing the participating models (reviewer model as generalist, critic model as skeptic, SME model as domain expert). Do NOT present raw per-member JSON.
59900
+
59901
+ ### MODE: DEEP_DIVE
59902
+ Activates when: architect receives \`[MODE: DEEP_DIVE profile=X max_explorers=N output=X update_main=X allow_dirty=X] <scope>\` signal from the deep-dive command handler.
59903
+
59904
+ Purpose: Perform a read-only deep audit of the specified codebase scope using parallel explorer waves, always 2 parallel reviewers, and sequential critic challenge. This mode does NOT mutate source code, does NOT delegate to coder, and does NOT call declare_scope.
59905
+
59906
+ #### STEP 0 — PARSE HEADER
59907
+ Parse the MODE: DEEP_DIVE header to extract:
59908
+ - \`scope\`: the codebase area to audit (e.g., "auth", "payment flow", "src/hooks/")
59909
+ - \`profile\`: one of standard | security | ux | architecture | full (default: standard)
59910
+ - \`max_explorers\`: integer 1..8 (default: 6, or 8 for full profile)
59911
+ - \`output\`: markdown | json (default: markdown)
59912
+ - \`update_main\`: boolean (default: true) — whether to fetch/ff-only main before starting
59913
+ - \`allow_dirty\`: boolean (default: false) — whether to proceed with uncommitted changes
59914
+
59915
+ If the header is malformed or missing required fields, report the error and stop.
59916
+
59917
+ #### STEP 1 — REPO READINESS
59918
+ 1. Check git working tree status. If dirty and \`allow_dirty\` is false, warn the user and ask whether to proceed. Do NOT proceed automatically.
59919
+ 2. If \`update_main\` is true and tree is clean: check current branch. If not on \`main\`, report current branch to user and ASK FOR CONFIRMATION before switching. Only after explicit user approval: \`git fetch origin main && git checkout main && git merge --ff-only origin/main\`. If ff-only fails, warn the user and ask before proceeding.
59920
+ 3. Record the current HEAD commit hash for the report.
59921
+
59922
+ #### STEP 2 — SCOPE RESOLUTION
59923
+ Use the following tools to map the audit scope:
59924
+ 1. \`repo_map\` with action "build" to establish the code graph
59925
+ 2. \`repo_map\` with action "localization" for the scope target
59926
+ 3. \`symbols\` and \`batch_symbols\` on key files identified by localization
59927
+ 4. \`imports\` to trace dependency boundaries
59928
+ 5. \`doc_scan\` if documentation coverage is relevant
59929
+ 6. \`knowledge_recall\` with query matching the scope domain
59930
+
59931
+ Produce a SCOPE MAP: list of files, modules, and interfaces within the audit boundary. Cap at 50 files total.
59932
+
59933
+ #### STEP 3 — EXPLORER MISSIONS (Parallel Waves)
59934
+ Dispatch explorer waves using parallel Task calls. Each wave contains up to \`max_explorers\` missions.
59935
+
59936
+ **File caps per mission:**
59937
+ - 8 files maximum per mission
59938
+ - ~3500 total lines across all files in a mission
59939
+ - Group files by import proximity (files that import each other go in the same mission)
59940
+
59941
+ **Profile-based lane selection — each profile activates specific lanes:**
59942
+
59943
+ | Lane | Template | standard | security | ux | architecture | full |
59944
+ |------|----------|----------|----------|----|-------------|------|
59945
+ | SCOPE_MAP | Map structure, exports, boundaries | ✓ | ✓ | ✓ | ✓ | ✓ |
59946
+ | WIRING_DATAFLOW | Trace data flow, API contracts, state propagation | ✓ | ✓ | | ✓ | ✓ |
59947
+ | RUNTIME_BEHAVIOR | Error handling, edge cases, lifecycle, async patterns | ✓ | | | ✓ | ✓ |
59948
+ | UX_FLOW | User-facing behavior, accessibility, responsiveness | | | ✓ | | ✓ |
59949
+ | SECURITY_TRUST | Auth boundaries, input validation, trust transitions | | ✓ | | | ✓ |
59950
+ | TEST_COVERAGE | Coverage gaps, flaky tests, missing assertions | ✓ | | | | ✓ |
59951
+ | PERFORMANCE_RELIABILITY | Resource leaks, N+1 queries, race conditions | | | | ✓ | ✓ |
59952
+ | DOCS_CONFIG_DEPLOYMENT | Config consistency, docs accuracy, deployment drift | | | | | ✓ |
59953
+
59954
+ Each explorer mission receives:
59955
+ - Lane template name and description
59956
+ - Assigned files (8 max, grouped by import proximity)
59957
+ - The scope map context from Step 2
59958
+ - Instruction: "You are performing a [LANE] audit. Report findings as candidate observations with severity (INFO/LOW/MEDIUM/HIGH/CRITICAL), location, and evidence."
59959
+
59960
+ Explorer missions are dispatched in parallel waves. Wait for ALL missions in a wave to complete before dispatching the next wave.
59961
+
59962
+ Explorers generate CANDIDATE FINDINGS only — they do NOT make verdicts. All findings are unverified until Step 5.
59963
+
59964
+ #### STEP 4 — NORMALIZE CANDIDATES
59965
+ 1. Collect all candidate findings from all explorer missions.
59966
+ 2. Deduplicate: merge findings that reference the same location and issue.
59967
+ 3. Assign DD-C001 through DD-CNNN identifiers to unique findings.
59968
+ 4. Cap at 10 findings per shard (see Step 5 for sharding).
59969
+ 5. Sort by severity (CRITICAL → HIGH → MEDIUM → LOW → INFO).
59970
+
59971
+ #### STEP 5 — ALWAYS 2 PARALLEL REVIEWERS
59972
+ Split the verified candidates into 2 shards of ≤10 candidates each. Dispatch 2 parallel \`{{AGENT_PREFIX}}reviewer\` calls.
59973
+
59974
+ Each reviewer receives:
59975
+ - Their shard of candidates (up to 10)
59976
+ - The scope map context
59977
+ - The original scope description
59978
+ - Instruction: "Verify or reject each candidate finding. For each: verdict (VERIFIED / REJECTED / NEEDS_MORE_EVIDENCE), confidence (0-1), and brief reasoning."
59979
+
59980
+ Reviewers MUST NOT suggest fixes — they verify findings only.
59981
+
59982
+ #### STEP 5b — REVIEWER MERGE/DEDUP
59983
+ After both reviewers return, perform a lightweight sync pass:
59984
+ 1. Cross-reference findings between reviewers — flag correlations
59985
+ 2. Deduplicate any findings both reviewers verified independently
59986
+ 3. For NEEDS_MORE_EVIDENCE findings: if the other reviewer verified a related finding, merge
59987
+ 4. Produce a unified findings list with verified/rejected status
59988
+
59989
+ #### STEP 6 — CRITIC CHALLENGE (HIGH/CRITICAL only)
59990
+ For verified findings rated HIGH or CRITICAL, dispatch sequential critic passes:
59991
+
59992
+ **Pass 1 — False-positive / root-cause challenge:**
59993
+ - \`{{AGENT_PREFIX}}critic\` receives each HIGH/CRITICAL finding
59994
+ - Challenge: "Is this a false positive? Is the root cause correctly identified? Provide verdict: SURVIVES / DOWNGRADE / REJECT"
59995
+ - Only findings that SURVIVE proceed to Pass 2
59996
+
59997
+ **Pass 2 — Impact / severity challenge:**
59998
+ - \`{{AGENT_PREFIX}}critic\` receives surviving findings
59999
+ - Challenge: "Is the severity correctly rated? Could this be lower impact than claimed? Provide verdict: SURVIVES / DOWNGRADE / REJECT"
60000
+ - Final severity is the critic's assessed severity
60001
+
60002
+ CRITICAL: Do NOT challenge MEDIUM/LOW/INFO findings. Only HIGH and CRITICAL go through critic review.
60003
+
60004
+ #### STEP 7 — FINAL REPORT
60005
+ Assemble and present the audit report:
60006
+
60007
+ 1. **Wiring Map**: Visual summary of the scope's module structure and data flow
60008
+ 2. **Functionality Assessment**: High-level summary of what the scope does and how well
60009
+ 3. **Verified Findings Table**: DD-ID, severity, location, description, evidence
60010
+ 4. **Rejected Candidates**: Brief list with rejection reasons
60011
+ 5. **Enhancements**: Non-blocking improvement suggestions
60012
+ 6. **Recommended Implementation Phases**: If findings suggest follow-up work, outline phases
60013
+ 7. **JSON Block** (when output=json): Structured machine-readable findings
60014
+
60015
+ IMPORTANT CONSTRAINTS for MODE: DEEP_DIVE:
60016
+ - Do NOT mutate source code under any circumstances
60017
+ - Do NOT delegate to coder
60018
+ - Do NOT call declare_scope
60019
+ - Do NOT create or modify any files outside .swarm/
60020
+ - No final finding may appear in the report without reviewer verification
60021
+ - Explorers generate candidate findings only — reviewers verify or reject
60022
+ - Critics challenge only HIGH/CRITICAL findings — do NOT waste cycles on lower severity
59771
60023
 
59772
60024
  ### MODE: ISSUE_INGEST
59773
60025
  Activates when: user invokes \`/swarm issue <url>\`; OR architect receives \`[MODE: ISSUE_INGEST issue="<url>"]\` signal.
@@ -67021,7 +67273,14 @@ __export(exports_doc_scan, {
67021
67273
  });
67022
67274
  import * as crypto7 from "node:crypto";
67023
67275
  import * as fs47 from "node:fs";
67024
- import { mkdir as mkdir11, readFile as readFile11, writeFile as writeFile10 } from "node:fs/promises";
67276
+ import {
67277
+ mkdir as mkdir11,
67278
+ readdir as readdir5,
67279
+ readFile as readFile11,
67280
+ realpath as realpath2,
67281
+ stat as stat6,
67282
+ writeFile as writeFile10
67283
+ } from "node:fs/promises";
67025
67284
  import * as path70 from "node:path";
67026
67285
  function normalizeSeparators(filePath) {
67027
67286
  return filePath.replace(/\\/g, "/");
@@ -67102,8 +67361,8 @@ async function scanDocIndex(directory) {
67102
67361
  for (const file3 of existingManifest.files) {
67103
67362
  try {
67104
67363
  const fullPath = path70.join(directory, file3.path);
67105
- const stat6 = fs47.statSync(fullPath);
67106
- if (stat6.mtimeMs > file3.mtime) {
67364
+ const stat7 = fs47.statSync(fullPath);
67365
+ if (stat7.mtimeMs > file3.mtime) {
67107
67366
  cacheValid = false;
67108
67367
  break;
67109
67368
  }
@@ -67117,66 +67376,90 @@ async function scanDocIndex(directory) {
67117
67376
  }
67118
67377
  }
67119
67378
  } catch {}
67379
+ const resolvedDirectory = await realpath2(directory).catch(() => directory);
67120
67380
  const discoveredFiles = [];
67121
- let rawEntries;
67122
- try {
67123
- rawEntries = fs47.readdirSync(directory, { recursive: true });
67124
- } catch {
67125
- const manifest2 = {
67126
- schema_version: 1,
67127
- scanned_at: new Date().toISOString(),
67128
- files: []
67129
- };
67130
- return { manifest: manifest2, cached: false };
67131
- }
67132
- const entries = rawEntries.filter((e) => typeof e === "string");
67133
- for (const entry of entries) {
67134
- const fullPath = path70.join(directory, entry);
67135
- let stat6;
67381
+ let rootReadable = false;
67382
+ const walkDir = async (dir) => {
67383
+ let entries;
67136
67384
  try {
67137
- stat6 = fs47.statSync(fullPath);
67385
+ entries = await readdir5(dir, { withFileTypes: true });
67386
+ if (dir === directory)
67387
+ rootReadable = true;
67138
67388
  } catch {
67139
- continue;
67389
+ return;
67140
67390
  }
67141
- if (!stat6.isFile())
67142
- continue;
67143
- const pathParts = normalizeSeparators(entry).split("/");
67144
- let skipThisFile = false;
67145
- for (const part of pathParts) {
67146
- if (SKIP_DIRECTORIES3.has(part)) {
67147
- skipThisFile = true;
67148
- break;
67391
+ for (const entry of entries) {
67392
+ if (discoveredFiles.length >= MAX_INDEXED_FILES)
67393
+ return;
67394
+ const isDir = entry.isDirectory();
67395
+ let isFile = entry.isFile();
67396
+ if (entry.isSymbolicLink()) {
67397
+ try {
67398
+ const symlinkPath = path70.join(dir, entry.name);
67399
+ const resolved = await realpath2(symlinkPath);
67400
+ const rel = path70.relative(resolvedDirectory, resolved);
67401
+ if (rel.startsWith("..") || path70.isAbsolute(rel))
67402
+ continue;
67403
+ const targetStat = await stat6(symlinkPath);
67404
+ isFile = targetStat.isFile();
67405
+ } catch {
67406
+ continue;
67407
+ }
67149
67408
  }
67150
- }
67151
- if (skipThisFile)
67152
- continue;
67153
- for (const pattern of SKIP_PATTERNS) {
67154
- if (pattern.test(entry)) {
67155
- skipThisFile = true;
67156
- break;
67409
+ if (isDir) {
67410
+ if (!SKIP_DIRECTORIES3.has(entry.name)) {
67411
+ await walkDir(path70.join(dir, entry.name));
67412
+ }
67413
+ continue;
67157
67414
  }
67415
+ if (!isFile)
67416
+ continue;
67417
+ const fullPath = path70.join(dir, entry.name);
67418
+ const relPath = normalizeSeparators(path70.relative(directory, fullPath));
67419
+ let skipThisFile = false;
67420
+ for (const pattern of SKIP_PATTERNS) {
67421
+ if (pattern.test(relPath)) {
67422
+ skipThisFile = true;
67423
+ break;
67424
+ }
67425
+ }
67426
+ if (skipThisFile)
67427
+ continue;
67428
+ if (!matchesDocPattern(relPath, allPatterns))
67429
+ continue;
67430
+ let fileStat;
67431
+ try {
67432
+ fileStat = await stat6(fullPath);
67433
+ } catch {
67434
+ continue;
67435
+ }
67436
+ let content;
67437
+ try {
67438
+ content = await readFile11(fullPath, "utf-8");
67439
+ } catch {
67440
+ continue;
67441
+ }
67442
+ const { title, summary } = extractTitleAndSummary(content, path70.basename(relPath));
67443
+ discoveredFiles.push({
67444
+ path: relPath,
67445
+ title,
67446
+ summary,
67447
+ lines: content.split(`
67448
+ `).length,
67449
+ mtime: fileStat.mtimeMs
67450
+ });
67158
67451
  }
67159
- if (skipThisFile)
67160
- continue;
67161
- if (!matchesDocPattern(entry, allPatterns)) {
67162
- continue;
67163
- }
67164
- let content;
67165
- try {
67166
- content = fs47.readFileSync(fullPath, "utf-8");
67167
- } catch {
67168
- continue;
67169
- }
67170
- const { title, summary } = extractTitleAndSummary(content, path70.basename(entry));
67171
- const lineCount = content.split(`
67172
- `).length;
67173
- discoveredFiles.push({
67174
- path: entry,
67175
- title,
67176
- summary,
67177
- lines: lineCount,
67178
- mtime: stat6.mtimeMs
67179
- });
67452
+ };
67453
+ await walkDir(directory);
67454
+ if (!rootReadable) {
67455
+ return {
67456
+ manifest: {
67457
+ schema_version: 1,
67458
+ scanned_at: new Date().toISOString(),
67459
+ files: []
67460
+ },
67461
+ cached: false
67462
+ };
67180
67463
  }
67181
67464
  discoveredFiles.sort((a, b) => a.path.toLowerCase().localeCompare(b.path.toLowerCase()));
67182
67465
  let truncated = false;
@@ -67325,7 +67608,13 @@ var init_doc_scan = __esm(() => {
67325
67608
  "dist",
67326
67609
  "build",
67327
67610
  ".next",
67328
- "vendor"
67611
+ "vendor",
67612
+ "bazel-out",
67613
+ "bazel-bin",
67614
+ "bazel-genfiles",
67615
+ "bazel-testlogs",
67616
+ ".gradle",
67617
+ "target"
67329
67618
  ]);
67330
67619
  SKIP_PATTERNS = [/\.test\./, /\.spec\./, /\.d\.ts$/];
67331
67620
  CONSTRAINT_PATTERNS = [
@@ -74786,6 +75075,12 @@ function createSystemEnhancerHook(config3, directory) {
74786
75075
  output.system.push(text);
74787
75076
  injectedTokens += tokens;
74788
75077
  };
75078
+ if (_input.sessionID) {
75079
+ const sessionAgent = swarmState.activeAgent.get(_input.sessionID);
75080
+ if (sessionAgent && OPENCODE_NATIVE_AGENTS.has(sessionAgent.toLowerCase())) {
75081
+ return;
75082
+ }
75083
+ }
74789
75084
  const maxInjectionTokens = config3.context_budget?.max_injection_tokens ?? 4000;
74790
75085
  let injectedTokens = 0;
74791
75086
  const contextContent = await readSwarmFileAsync(directory, "context.md");
@@ -76448,22 +76743,22 @@ function classifyPathRisk(filePath, context) {
76448
76743
  }
76449
76744
  })();
76450
76745
  const withinProjectRoot = isWithinDirectory(absolute, context.directory) && isWithinDirectory(resolvedAbsolute, context.directory);
76451
- const relative15 = path72.relative(context.directory, absolute).replace(/\\/g, "/");
76746
+ const relative16 = path72.relative(context.directory, absolute).replace(/\\/g, "/");
76452
76747
  let withinDeclaredScope = null;
76453
76748
  if (Array.isArray(context.declaredScope)) {
76454
76749
  withinDeclaredScope = context.declaredScope.length === 0 ? false : context.declaredScope.some((scope) => {
76455
76750
  const s = normalizePath3(scope);
76456
76751
  if (!s)
76457
76752
  return false;
76458
- return relative15 === s || relative15.startsWith(`${s}/`);
76753
+ return relative16 === s || relative16.startsWith(`${s}/`);
76459
76754
  });
76460
76755
  }
76461
76756
  const highRiskBuild = HIGH_RISK_BUILD_PATHS.some((entry) => {
76462
76757
  const e = normalizePath3(entry);
76463
76758
  if (e.endsWith("/")) {
76464
- return relative15.startsWith(e);
76759
+ return relative16.startsWith(e);
76465
76760
  }
76466
- return relative15 === e || relative15.startsWith(`${e}/`);
76761
+ return relative16 === e || relative16.startsWith(`${e}/`);
76467
76762
  });
76468
76763
  return {
76469
76764
  withinProjectRoot,
@@ -78932,8 +79227,8 @@ async function cleanupOldTrajectoryFiles(directory, maxAgeDays = 7) {
78932
79227
  continue;
78933
79228
  const filePath = path79.join(dirPath, entry.name);
78934
79229
  try {
78935
- const stat7 = await fs57.stat(filePath);
78936
- if (now - stat7.mtimeMs > cutoffMs) {
79230
+ const stat8 = await fs57.stat(filePath);
79231
+ if (now - stat8.mtimeMs > cutoffMs) {
78937
79232
  await fs57.unlink(filePath);
78938
79233
  }
78939
79234
  } catch {}
@@ -80773,8 +81068,8 @@ async function executeCompletionVerify(args2, directory) {
80773
81068
  const normalizedPath = filePath.replace(/\\/g, "/");
80774
81069
  const resolvedPath = path84.resolve(directory, normalizedPath);
80775
81070
  const projectRoot = path84.resolve(directory);
80776
- const relative18 = path84.relative(projectRoot, resolvedPath);
80777
- const withinProject = relative18 === "" || !relative18.startsWith("..") && !path84.isAbsolute(relative18);
81071
+ const relative19 = path84.relative(projectRoot, resolvedPath);
81072
+ const withinProject = relative19 === "" || !relative19.startsWith("..") && !path84.isAbsolute(relative19);
80778
81073
  if (!withinProject) {
80779
81074
  blockedTasks.push({
80780
81075
  task_id: task.id,
@@ -80949,8 +81244,8 @@ function estimateCyclomaticComplexity(content) {
80949
81244
  }
80950
81245
  function getComplexityForFile(filePath) {
80951
81246
  try {
80952
- const stat7 = fs63.statSync(filePath);
80953
- if (stat7.size > MAX_FILE_SIZE_BYTES4) {
81247
+ const stat8 = fs63.statSync(filePath);
81248
+ if (stat8.size > MAX_FILE_SIZE_BYTES4) {
80954
81249
  return null;
80955
81250
  }
80956
81251
  const content = fs63.readFileSync(filePath, "utf-8");
@@ -81151,8 +81446,8 @@ async function computeDuplicationRatio(files, workingDir) {
81151
81446
  continue;
81152
81447
  }
81153
81448
  try {
81154
- const stat7 = fs63.statSync(fullPath);
81155
- if (stat7.size > MAX_FILE_SIZE_BYTES4) {
81449
+ const stat8 = fs63.statSync(fullPath);
81450
+ if (stat8.size > MAX_FILE_SIZE_BYTES4) {
81156
81451
  continue;
81157
81452
  }
81158
81453
  const content = fs63.readFileSync(fullPath, "utf-8");
@@ -81612,8 +81907,8 @@ async function getGitChurn(days, directory) {
81612
81907
  }
81613
81908
  function getComplexityForFile2(filePath) {
81614
81909
  try {
81615
- const stat7 = fs64.statSync(filePath);
81616
- if (stat7.size > MAX_FILE_SIZE_BYTES5) {
81910
+ const stat8 = fs64.statSync(filePath);
81911
+ if (stat8.size > MAX_FILE_SIZE_BYTES5) {
81617
81912
  return null;
81618
81913
  }
81619
81914
  const content = fs64.readFileSync(filePath, "utf-8");
@@ -81809,7 +82104,7 @@ import {
81809
82104
  appendFileSync as appendFileSync9,
81810
82105
  existsSync as existsSync45,
81811
82106
  mkdirSync as mkdirSync21,
81812
- readFileSync as readFileSync37,
82107
+ readFileSync as readFileSync36,
81813
82108
  writeFileSync as writeFileSync14
81814
82109
  } from "node:fs";
81815
82110
  import { join as join72 } from "node:path";
@@ -81852,7 +82147,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
81852
82147
  const existingRoot = Object.create(null);
81853
82148
  if (existsSync45(filePath)) {
81854
82149
  try {
81855
- const parsed = JSON.parse(readFileSync37(filePath, "utf-8"));
82150
+ const parsed = JSON.parse(readFileSync36(filePath, "utf-8"));
81856
82151
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
81857
82152
  safeAssignOwnProps(existingRoot, parsed);
81858
82153
  }
@@ -82119,7 +82414,7 @@ function buildPhaseCouncilFeedback(phaseNumber, phaseSummary, verdict, vetoedBy,
82119
82414
  }
82120
82415
 
82121
82416
  // src/council/criteria-store.ts
82122
- import { existsSync as existsSync46, mkdirSync as mkdirSync22, readFileSync as readFileSync38, writeFileSync as writeFileSync15 } from "node:fs";
82417
+ import { existsSync as existsSync46, mkdirSync as mkdirSync22, readFileSync as readFileSync37, writeFileSync as writeFileSync15 } from "node:fs";
82123
82418
  import { join as join73 } from "node:path";
82124
82419
  var COUNCIL_DIR = ".swarm/council";
82125
82420
  function writeCriteria(workingDir, taskId, criteria) {
@@ -82137,7 +82432,7 @@ function readCriteria(workingDir, taskId) {
82137
82432
  if (!existsSync46(filePath))
82138
82433
  return null;
82139
82434
  try {
82140
- const parsed = JSON.parse(readFileSync38(filePath, "utf-8"));
82435
+ const parsed = JSON.parse(readFileSync37(filePath, "utf-8"));
82141
82436
  if (parsed && typeof parsed === "object" && typeof parsed.taskId === "string" && Array.isArray(parsed.criteria)) {
82142
82437
  return parsed;
82143
82438
  }
@@ -83785,8 +84080,8 @@ function readEvidenceFiles(evidenceDir, _cwd) {
83785
84080
  if (!resolvedPath.startsWith(evidenceDirResolved)) {
83786
84081
  continue;
83787
84082
  }
83788
- const stat7 = fs69.lstatSync(filePath);
83789
- if (!stat7.isFile()) {
84083
+ const stat8 = fs69.lstatSync(filePath);
84084
+ if (!stat8.isFile()) {
83790
84085
  continue;
83791
84086
  }
83792
84087
  } catch {
@@ -84470,9 +84765,9 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
84470
84765
  continue;
84471
84766
  }
84472
84767
  const fullPath = path93.join(dir, entry);
84473
- let stat7;
84768
+ let stat8;
84474
84769
  try {
84475
- stat7 = fs71.statSync(fullPath);
84770
+ stat8 = fs71.statSync(fullPath);
84476
84771
  } catch (e) {
84477
84772
  stats.fileErrors.push({
84478
84773
  path: fullPath,
@@ -84480,9 +84775,9 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
84480
84775
  });
84481
84776
  continue;
84482
84777
  }
84483
- if (stat7.isDirectory()) {
84778
+ if (stat8.isDirectory()) {
84484
84779
  findSourceFiles2(fullPath, files, stats);
84485
- } else if (stat7.isFile()) {
84780
+ } else if (stat8.isFile()) {
84486
84781
  const ext = path93.extname(fullPath).toLowerCase();
84487
84782
  if (SUPPORTED_EXTENSIONS3.includes(ext)) {
84488
84783
  files.push(fullPath);
@@ -84577,8 +84872,8 @@ var imports = createSwarmTool({
84577
84872
  if (consumers.length >= MAX_CONSUMERS)
84578
84873
  break;
84579
84874
  try {
84580
- const stat7 = fs71.statSync(filePath);
84581
- if (stat7.size > MAX_FILE_SIZE_BYTES7) {
84875
+ const stat8 = fs71.statSync(filePath);
84876
+ if (stat8.size > MAX_FILE_SIZE_BYTES7) {
84582
84877
  skippedFileCount++;
84583
84878
  continue;
84584
84879
  }
@@ -88154,8 +88449,8 @@ async function placeholderScan(input, directory) {
88154
88449
  }
88155
88450
  let content;
88156
88451
  try {
88157
- const stat7 = fs76.statSync(fullPath);
88158
- if (stat7.size > MAX_FILE_SIZE) {
88452
+ const stat8 = fs76.statSync(fullPath);
88453
+ if (stat8.size > MAX_FILE_SIZE) {
88159
88454
  continue;
88160
88455
  }
88161
88456
  content = fs76.readFileSync(fullPath, "utf-8");
@@ -90021,13 +90316,13 @@ function validatePath(inputPath, baseDir, workspaceDir) {
90021
90316
  resolved = path102.resolve(baseDir, inputPath);
90022
90317
  }
90023
90318
  const workspaceResolved = path102.resolve(workspaceDir);
90024
- let relative22;
90319
+ let relative23;
90025
90320
  if (isWinAbs) {
90026
- relative22 = path102.win32.relative(workspaceResolved, resolved);
90321
+ relative23 = path102.win32.relative(workspaceResolved, resolved);
90027
90322
  } else {
90028
- relative22 = path102.relative(workspaceResolved, resolved);
90323
+ relative23 = path102.relative(workspaceResolved, resolved);
90029
90324
  }
90030
- if (relative22.startsWith("..")) {
90325
+ if (relative23.startsWith("..")) {
90031
90326
  return "path traversal detected";
90032
90327
  }
90033
90328
  return null;
@@ -90270,14 +90565,14 @@ async function runSecretscanWithFiles(files, directory) {
90270
90565
  skippedFiles++;
90271
90566
  continue;
90272
90567
  }
90273
- let stat7;
90568
+ let stat8;
90274
90569
  try {
90275
- stat7 = fs80.statSync(file3);
90570
+ stat8 = fs80.statSync(file3);
90276
90571
  } catch {
90277
90572
  skippedFiles++;
90278
90573
  continue;
90279
90574
  }
90280
- if (stat7.size > MAX_FILE_SIZE_BYTES9) {
90575
+ if (stat8.size > MAX_FILE_SIZE_BYTES9) {
90281
90576
  skippedFiles++;
90282
90577
  continue;
90283
90578
  }
@@ -91042,8 +91337,8 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
91042
91337
  for (const entry of entries) {
91043
91338
  const entryPath = path104.join(evidenceDir, entry);
91044
91339
  try {
91045
- const stat7 = fs81.statSync(entryPath);
91046
- if (!stat7.isDirectory()) {
91340
+ const stat8 = fs81.statSync(entryPath);
91341
+ if (!stat8.isDirectory()) {
91047
91342
  continue;
91048
91343
  }
91049
91344
  } catch {
@@ -91063,11 +91358,11 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
91063
91358
  if (!resolvedPath.startsWith(evidenceDirResolved + path104.sep)) {
91064
91359
  continue;
91065
91360
  }
91066
- const stat7 = fs81.lstatSync(evidenceFilePath);
91067
- if (!stat7.isFile()) {
91361
+ const stat8 = fs81.lstatSync(evidenceFilePath);
91362
+ if (!stat8.isFile()) {
91068
91363
  continue;
91069
91364
  }
91070
- if (stat7.size > MAX_FILE_SIZE_BYTES9) {
91365
+ if (stat8.size > MAX_FILE_SIZE_BYTES9) {
91071
91366
  continue;
91072
91367
  }
91073
91368
  } catch {
@@ -91489,8 +91784,8 @@ async function executeSavePlan(args2, fallbackDir) {
91489
91784
  if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
91490
91785
  const specPath = path105.join(targetWorkspace, ".swarm", "spec.md");
91491
91786
  try {
91492
- const stat7 = await fs82.promises.stat(specPath);
91493
- specMtime = stat7.mtime.toISOString();
91787
+ const stat8 = await fs82.promises.stat(specPath);
91788
+ specMtime = stat8.mtime.toISOString();
91494
91789
  const content = await fs82.promises.readFile(specPath, "utf8");
91495
91790
  specHash = crypto10.createHash("sha256").update(content).digest("hex");
91496
91791
  } catch {
@@ -94266,7 +94561,7 @@ init_loader();
94266
94561
  import {
94267
94562
  existsSync as existsSync65,
94268
94563
  mkdirSync as mkdirSync28,
94269
- readFileSync as readFileSync55,
94564
+ readFileSync as readFileSync54,
94270
94565
  renameSync as renameSync18,
94271
94566
  unlinkSync as unlinkSync14,
94272
94567
  writeFileSync as writeFileSync22
@@ -94403,7 +94698,7 @@ var submit_phase_council_verdicts = createSwarmTool({
94403
94698
  function getPhaseMutationGapFinding(phaseNumber, workingDir) {
94404
94699
  const mutationGatePath = path112.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
94405
94700
  try {
94406
- const raw = readFileSync55(mutationGatePath, "utf-8");
94701
+ const raw = readFileSync54(mutationGatePath, "utf-8");
94407
94702
  const parsed = JSON.parse(raw);
94408
94703
  const gateEntry = (parsed.entries ?? []).find((entry) => entry?.type === "mutation-gate");
94409
94704
  if (!gateEntry) {
@@ -96027,15 +96322,15 @@ function findSourceFiles3(dir, files = []) {
96027
96322
  continue;
96028
96323
  }
96029
96324
  const fullPath = path118.join(dir, entry);
96030
- let stat7;
96325
+ let stat8;
96031
96326
  try {
96032
- stat7 = fs90.statSync(fullPath);
96327
+ stat8 = fs90.statSync(fullPath);
96033
96328
  } catch {
96034
96329
  continue;
96035
96330
  }
96036
- if (stat7.isDirectory()) {
96331
+ if (stat8.isDirectory()) {
96037
96332
  findSourceFiles3(fullPath, files);
96038
- } else if (stat7.isFile()) {
96333
+ } else if (stat8.isFile()) {
96039
96334
  if (isSupportedExtension(fullPath)) {
96040
96335
  files.push(fullPath);
96041
96336
  }
@@ -96132,8 +96427,8 @@ var todo_extract = createSwarmTool({
96132
96427
  return JSON.stringify(errorResult, null, 2);
96133
96428
  }
96134
96429
  const filesToScan = [];
96135
- const stat7 = fs90.statSync(scanPath);
96136
- if (stat7.isFile()) {
96430
+ const stat8 = fs90.statSync(scanPath);
96431
+ if (stat8.isFile()) {
96137
96432
  if (isSupportedExtension(scanPath)) {
96138
96433
  filesToScan.push(scanPath);
96139
96434
  } else {
@@ -98161,6 +98456,10 @@ async function initializeOpenCodeSwarm(ctx) {
98161
98456
  template: "/swarm pr-review $ARGUMENTS",
98162
98457
  description: "Use /swarm pr-review to launch deep PR review with multi-lane analysis"
98163
98458
  },
98459
+ "swarm-deep-dive": {
98460
+ template: "/swarm deep-dive $ARGUMENTS",
98461
+ description: "Use /swarm deep-dive to launch a read-only deep audit with parallel explorer waves, dual reviewers, and critic challenge"
98462
+ },
98164
98463
  "swarm-issue": {
98165
98464
  template: "/swarm issue $ARGUMENTS",
98166
98465
  description: "Use /swarm issue to ingest a GitHub issue into the swarm workflow"