opencode-swarm 7.52.3 → 7.54.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.
package/dist/index.js CHANGED
@@ -69,7 +69,7 @@ var package_default;
69
69
  var init_package = __esm(() => {
70
70
  package_default = {
71
71
  name: "opencode-swarm",
72
- version: "7.52.3",
72
+ version: "7.54.0",
73
73
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
74
74
  main: "dist/index.js",
75
75
  types: "dist/index.d.ts",
@@ -566,11 +566,11 @@ var init_tool_metadata = __esm(() => {
566
566
  agents: ["architect"]
567
567
  },
568
568
  web_search: {
569
- description: "External web search (Tavily or Brave) for architect-driven council research. Returns titled results with snippets and URLs. Config-gated on council.general.enabled; requires a search API key. Used by the architect in MODE: COUNCIL to gather a RESEARCH CONTEXT before dispatching council agents.",
569
+ description: "External web search (Tavily or Brave) for architect-driven council research. Returns titled results with snippets, URLs, normalized query metadata, temporal intent, freshness, and removed stale years. Config-gated on council.general.enabled in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides. Requires a search API key. Used by the architect in MODE: COUNCIL to gather a RESEARCH CONTEXT before dispatching council agents.",
570
570
  agents: ["architect", "skill_improver"]
571
571
  },
572
572
  convene_general_council: {
573
- description: "Synthesize responses from a multi-model General Council. Accepts parallel member responses (Round 1, optionally Round 2), detects disagreements, and returns consensus points, persisting disagreements, and a structured synthesis. Architect-only. Config-gated on council.general.enabled.",
573
+ description: "Synthesize responses from a multi-model General Council. Accepts parallel member responses (Round 1, optionally Round 2), detects disagreements, and returns consensus points, persisting disagreements, and a structured synthesis. Architect-only. Config-gated on council.general.enabled in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides.",
574
574
  agents: ["architect"]
575
575
  },
576
576
  write_final_council_evidence: {
@@ -40596,6 +40596,18 @@ import * as path19 from "node:path";
40596
40596
  function clearPendingCoderScope() {
40597
40597
  pendingCoderScopeByTaskId.clear();
40598
40598
  }
40599
+ function isBackgroundTrue(value) {
40600
+ return value === true || value === "true";
40601
+ }
40602
+ function outputLooksLikeBackgroundRunning(output) {
40603
+ if (typeof output !== "object" || output === null)
40604
+ return false;
40605
+ const o = output;
40606
+ if (o.state === "running")
40607
+ return true;
40608
+ const metadata2 = o.metadata;
40609
+ return typeof metadata2 === "object" && metadata2 !== null && metadata2.background === true;
40610
+ }
40599
40611
  function extractTaskLine(text) {
40600
40612
  const match = text.match(/TASK:\s*(.+?)(?:\n|$)/i);
40601
40613
  return match ? match[1].trim() : null;
@@ -40874,6 +40886,9 @@ function createDelegationGateHook(config2, directory) {
40874
40886
  if (typeof subagentType !== "string")
40875
40887
  return;
40876
40888
  const targetAgent = stripKnownSwarmPrefix(subagentType);
40889
+ if (isBackgroundTrue(args2.background) && isKnownCanonicalRole(targetAgent)) {
40890
+ throw new Error(SWARM_BACKGROUND_TASK_BLOCKED_MESSAGE);
40891
+ }
40877
40892
  if (targetAgent === "reviewer") {
40878
40893
  try {
40879
40894
  const reviewSession = swarmState.agentSessions.get(input.sessionID);
@@ -40974,6 +40989,11 @@ function createDelegationGateHook(config2, directory) {
40974
40989
  const directArgs = input.args;
40975
40990
  const storedArgs = getStoredInputArgs(input.callID);
40976
40991
  const subagentType = directArgs?.subagent_type ?? storedArgs?.subagent_type;
40992
+ if (typeof subagentType === "string" && isKnownCanonicalRole(stripKnownSwarmPrefix(subagentType)) && (isBackgroundTrue(directArgs?.background) || isBackgroundTrue(storedArgs?.background) || outputLooksLikeBackgroundRunning(_output))) {
40993
+ if (storedArgs !== undefined)
40994
+ deleteStoredInputArgs(input.callID);
40995
+ return;
40996
+ }
40977
40997
  let hasReviewer = false;
40978
40998
  let hasTestEngineer = false;
40979
40999
  if (typeof subagentType === "string") {
@@ -41451,7 +41471,7 @@ ${warningLines.join(`
41451
41471
  toolAfter
41452
41472
  };
41453
41473
  }
41454
- var EvidenceTaskIdPlanSchema, pendingCoderScopeByTaskId, ACTIVE_PARALLEL_TASK_STATES;
41474
+ var EvidenceTaskIdPlanSchema, pendingCoderScopeByTaskId, SWARM_BACKGROUND_TASK_BLOCKED_MESSAGE, ACTIVE_PARALLEL_TASK_STATES;
41455
41475
  var init_delegation_gate = __esm(() => {
41456
41476
  init_zod();
41457
41477
  init_schema();
@@ -41472,6 +41492,7 @@ var init_delegation_gate = __esm(() => {
41472
41492
  }).passthrough()).optional()
41473
41493
  }).passthrough();
41474
41494
  pendingCoderScopeByTaskId = new Map;
41495
+ SWARM_BACKGROUND_TASK_BLOCKED_MESSAGE = "SWARM_BACKGROUND_TASK_BLOCKED: OpenCode background subagents (Task with background=true, " + "requires OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true) are recognized upstream, but swarm " + "cannot yet safely consume their deferred completion events — the Task returns a running " + "placeholder now and completes later via synthetic injection, which would advance swarm gates " + "before any review/test output exists. Omit `background` (or set background=false) for swarm " + "delegations until the completion-ingestion PR lands.";
41475
41496
  ACTIVE_PARALLEL_TASK_STATES = new Set([
41476
41497
  "coder_delegated",
41477
41498
  "pre_check_passed",
@@ -62057,7 +62078,7 @@ var init_council = __esm(() => {
62057
62078
  " --preset <name> Use a named member preset from council.general.presets",
62058
62079
  " --spec-review Use spec_review mode (single advisory pass on a draft spec)",
62059
62080
  "",
62060
- "Requires council.general.enabled: true and a configured search API key in opencode-swarm.json."
62081
+ "Requires council.general.enabled: true and a configured search API key in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides."
62061
62082
  ].join(`
62062
62083
  `);
62063
62084
  });
@@ -73213,7 +73234,7 @@ var init_plan = __esm(() => {
73213
73234
  init_plan_service();
73214
73235
  });
73215
73236
 
73216
- // src/commands/pr-review.ts
73237
+ // src/commands/pr-ref.ts
73217
73238
  import { execSync as execSync3 } from "node:child_process";
73218
73239
  function sanitizeUrl2(raw) {
73219
73240
  let urlStr = raw.trim();
@@ -73232,6 +73253,22 @@ function sanitizeUrl2(raw) {
73232
73253
  }
73233
73254
  return urlStr.trim();
73234
73255
  }
73256
+ function sanitizeInstructions(raw) {
73257
+ const collapsed = raw.replace(/\s+/g, " ").trim();
73258
+ const stripped = collapsed.replace(/\[\s*MODE\s*:[^\]]*\]/gi, "");
73259
+ const normalized = stripped.replace(/\s+/g, " ").trim();
73260
+ if (normalized.length <= MAX_INSTRUCTIONS_LEN)
73261
+ return normalized;
73262
+ return `${normalized.slice(0, MAX_INSTRUCTIONS_LEN)}…`;
73263
+ }
73264
+ function hasNonAsciiHostname(hostname5) {
73265
+ for (const ch of hostname5) {
73266
+ const cp = ch.codePointAt(0);
73267
+ if (cp !== undefined && cp > 127)
73268
+ return true;
73269
+ }
73270
+ return false;
73271
+ }
73235
73272
  function isPrivateHost2(url3) {
73236
73273
  const host = url3.hostname.toLowerCase();
73237
73274
  if (host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "0.0.0.0") {
@@ -73266,8 +73303,7 @@ function validateAndSanitizeUrl2(rawUrl) {
73266
73303
  }
73267
73304
  try {
73268
73305
  const url3 = new URL(sanitized);
73269
- const hostname5 = url3.hostname;
73270
- if (/[\u0080-\u{10FFFF}]/u.test(hostname5)) {
73306
+ if (hasNonAsciiHostname(url3.hostname)) {
73271
73307
  return { error: "Non-ASCII hostnames are not allowed" };
73272
73308
  }
73273
73309
  if (isPrivateHost2(url3)) {
@@ -73284,18 +73320,7 @@ function validateAndSanitizeUrl2(rawUrl) {
73284
73320
  return { error: "Invalid URL format" };
73285
73321
  }
73286
73322
  }
73287
- function parseArgs5(args2) {
73288
- const out2 = { council: false, rest: [] };
73289
- for (const token of args2) {
73290
- if (token === "--council") {
73291
- out2.council = true;
73292
- continue;
73293
- }
73294
- out2.rest.push(token);
73295
- }
73296
- return out2;
73297
- }
73298
- function parsePrRef(input) {
73323
+ function parsePrRef(input, cwd) {
73299
73324
  const urlMatch = input.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)\/?$/i);
73300
73325
  if (urlMatch) {
73301
73326
  return {
@@ -73315,7 +73340,7 @@ function parsePrRef(input) {
73315
73340
  const bareMatch = input.match(/^(\d+)$/);
73316
73341
  if (bareMatch) {
73317
73342
  const prNumber = parseInt(bareMatch[1], 10);
73318
- const remoteUrl = detectGitRemote2();
73343
+ const remoteUrl = detectGitRemote2(cwd);
73319
73344
  if (!remoteUrl) {
73320
73345
  return null;
73321
73346
  }
@@ -73331,12 +73356,13 @@ function parsePrRef(input) {
73331
73356
  }
73332
73357
  return null;
73333
73358
  }
73334
- function detectGitRemote2() {
73359
+ function detectGitRemote2(cwd) {
73335
73360
  try {
73336
- const remoteUrl = execSync3("git remote get-url origin", {
73361
+ const remoteUrl = _internals31.execSync("git remote get-url origin", {
73337
73362
  encoding: "utf-8",
73338
73363
  stdio: ["pipe", "pipe", "pipe"],
73339
- timeout: 5000
73364
+ timeout: 5000,
73365
+ ...cwd ? { cwd } : {}
73340
73366
  }).trim();
73341
73367
  return remoteUrl || null;
73342
73368
  } catch {
@@ -73367,41 +73393,115 @@ function parseGitRemoteUrl2(remoteUrl) {
73367
73393
  }
73368
73394
  return null;
73369
73395
  }
73370
- function handlePrReviewCommand(_directory, args2) {
73371
- const parsed = parseArgs5(args2);
73372
- const rawInput = parsed.rest.join(" ").trim();
73373
- if (!rawInput) {
73374
- return USAGE5;
73396
+ function looksLikePrRef(token) {
73397
+ return /^https?:\/\//i.test(token) || /^[^/]+\/[^#]+#\d+$/.test(token) || /^\d+$/.test(token);
73398
+ }
73399
+ function resolvePrCommandInput(rest, cwd) {
73400
+ if (rest.length === 0) {
73401
+ return null;
73375
73402
  }
73376
- const isFullUrl = /^https?:\/\//i.test(rawInput);
73377
- const prInfo = parsePrRef(isFullUrl ? sanitizeUrl2(rawInput) : rawInput);
73403
+ const refToken = rest[0];
73404
+ const instructions = sanitizeInstructions(rest.slice(1).join(" "));
73405
+ const isFullUrl = /^https?:\/\//i.test(refToken);
73406
+ const prInfo = parsePrRef(isFullUrl ? sanitizeUrl2(refToken) : refToken, cwd);
73378
73407
  if (!prInfo) {
73379
- return `Error: Could not parse PR reference from "${rawInput}"
73380
-
73381
- ${USAGE5}`;
73408
+ return { error: `Could not parse PR reference from "${refToken}"` };
73382
73409
  }
73383
73410
  const prUrl = `https://github.com/${prInfo.owner}/${prInfo.repo}/pull/${prInfo.number}`;
73384
73411
  const result = validateAndSanitizeUrl2(prUrl);
73385
73412
  if ("error" in result) {
73386
- return `Error: ${result.error}
73413
+ return { error: result.error };
73414
+ }
73415
+ return { prUrl: result.sanitized, instructions };
73416
+ }
73417
+ var _internals31, MAX_URL_LEN2 = 2048, MAX_INSTRUCTIONS_LEN = 1000;
73418
+ var init_pr_ref = __esm(() => {
73419
+ _internals31 = { execSync: execSync3 };
73420
+ });
73421
+
73422
+ // src/commands/pr-feedback.ts
73423
+ function handlePrFeedbackCommand(directory, args2) {
73424
+ const rest = args2.filter((t) => t.trim().length > 0);
73425
+ if (rest.length === 0) {
73426
+ return "[MODE: PR_FEEDBACK]";
73427
+ }
73428
+ const resolved = resolvePrCommandInput(rest, directory);
73429
+ if (resolved && "prUrl" in resolved) {
73430
+ const signal = `[MODE: PR_FEEDBACK pr="${resolved.prUrl}"]`;
73431
+ return resolved.instructions ? `${signal} ${resolved.instructions}` : signal;
73432
+ }
73433
+ if (resolved && "error" in resolved && looksLikePrRef(rest[0])) {
73434
+ return [
73435
+ `Error: ${resolved.error}`,
73436
+ "",
73437
+ "That looked like a PR reference but could not be resolved. Pass a full",
73438
+ "URL or `owner/repo#N`, or omit the reference to start a no-PR feedback",
73439
+ "session (e.g. `/swarm pr-feedback address the review notes`)."
73440
+ ].join(`
73441
+ `);
73442
+ }
73443
+ const instructions = sanitizeInstructions(rest.join(" "));
73444
+ return instructions ? `[MODE: PR_FEEDBACK] ${instructions}` : "[MODE: PR_FEEDBACK]";
73445
+ }
73446
+ var init_pr_feedback = __esm(() => {
73447
+ init_pr_ref();
73448
+ });
73449
+
73450
+ // src/commands/pr-review.ts
73451
+ function parseArgs5(args2) {
73452
+ const out2 = { council: false, rest: [] };
73453
+ for (const token of args2) {
73454
+ if (token === "--council") {
73455
+ out2.council = true;
73456
+ continue;
73457
+ }
73458
+ if (token.startsWith("--")) {
73459
+ if (out2.unknownFlag === undefined)
73460
+ out2.unknownFlag = token;
73461
+ continue;
73462
+ }
73463
+ if (token.trim().length === 0)
73464
+ continue;
73465
+ out2.rest.push(token);
73466
+ }
73467
+ return out2;
73468
+ }
73469
+ function handlePrReviewCommand(directory, args2) {
73470
+ const parsed = parseArgs5(args2);
73471
+ if (parsed.unknownFlag) {
73472
+ return `Error: Unknown flag "${parsed.unknownFlag}"
73473
+
73474
+ ${USAGE5}`;
73475
+ }
73476
+ const resolved = resolvePrCommandInput(parsed.rest, directory);
73477
+ if (resolved === null) {
73478
+ return USAGE5;
73479
+ }
73480
+ if ("error" in resolved) {
73481
+ return `Error: ${resolved.error}
73387
73482
 
73388
73483
  ${USAGE5}`;
73389
73484
  }
73390
73485
  const councilFlag = parsed.council ? "council=true" : "council=false";
73391
- return `[MODE: PR_REVIEW pr="${result.sanitized}" ${councilFlag}]`;
73486
+ const signal = `[MODE: PR_REVIEW pr="${resolved.prUrl}" ${councilFlag}]`;
73487
+ return resolved.instructions ? `${signal} ${resolved.instructions}` : signal;
73392
73488
  }
73393
- var MAX_URL_LEN2 = 2048, USAGE5;
73489
+ var USAGE5;
73394
73490
  var init_pr_review = __esm(() => {
73491
+ init_pr_ref();
73395
73492
  USAGE5 = [
73396
- "Usage: /swarm pr-review <url|owner/repo#N|N> [--council]",
73493
+ "Usage: /swarm pr-review <url|owner/repo#N|N> [--council] [instructions...]",
73397
73494
  "",
73398
73495
  "Run a full swarm PR review on a GitHub pull request.",
73399
73496
  " /swarm pr-review https://github.com/owner/repo/pull/42",
73400
73497
  " /swarm pr-review owner/repo#42",
73401
73498
  " /swarm pr-review 42 --council",
73499
+ " /swarm pr-review 42 focus on the auth refactor and the new retry logic",
73402
73500
  "",
73403
73501
  "Flags:",
73404
- " --council Run adversarial council variant (all lanes assume work is wrong)"
73502
+ " --council Run adversarial council variant (all lanes assume work is wrong)",
73503
+ "",
73504
+ "Any text after the PR reference is forwarded to the reviewer as extra instructions."
73405
73505
  ].join(`
73406
73506
  `);
73407
73507
  });
@@ -73843,7 +73943,7 @@ async function runAdditionalLint(linter, mode, cwd) {
73843
73943
  };
73844
73944
  }
73845
73945
  }
73846
- var MAX_OUTPUT_BYTES = 512000, MAX_COMMAND_LENGTH = 500, lint, _internals31;
73946
+ var MAX_OUTPUT_BYTES = 512000, MAX_COMMAND_LENGTH = 500, lint, _internals32;
73847
73947
  var init_lint = __esm(() => {
73848
73948
  init_zod();
73849
73949
  init_discovery();
@@ -73875,15 +73975,15 @@ var init_lint = __esm(() => {
73875
73975
  }
73876
73976
  const { mode } = args2;
73877
73977
  const cwd = directory;
73878
- const linter = await _internals31.detectAvailableLinter(directory);
73978
+ const linter = await _internals32.detectAvailableLinter(directory);
73879
73979
  if (linter) {
73880
- const result = await _internals31.runLint(linter, mode, directory);
73980
+ const result = await _internals32.runLint(linter, mode, directory);
73881
73981
  return JSON.stringify(result, null, 2);
73882
73982
  }
73883
- const additionalLinter = _internals31.detectAdditionalLinter(cwd);
73983
+ const additionalLinter = _internals32.detectAdditionalLinter(cwd);
73884
73984
  if (additionalLinter) {
73885
73985
  warn(`[lint] Using ${additionalLinter} linter for this project`);
73886
- const result = await _internals31.runAdditionalLint(additionalLinter, mode, cwd);
73986
+ const result = await _internals32.runAdditionalLint(additionalLinter, mode, cwd);
73887
73987
  return JSON.stringify(result, null, 2);
73888
73988
  }
73889
73989
  const errorResult = {
@@ -73897,7 +73997,7 @@ For Rust: rustup component add clippy`
73897
73997
  return JSON.stringify(errorResult, null, 2);
73898
73998
  }
73899
73999
  });
73900
- _internals31 = {
74000
+ _internals32 = {
73901
74001
  detectAvailableLinter,
73902
74002
  runLint,
73903
74003
  detectAdditionalLinter,
@@ -74211,7 +74311,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
74211
74311
  }
74212
74312
  async function runSecretscan(directory) {
74213
74313
  try {
74214
- const result = await _internals32.secretscan.execute({ directory }, {});
74314
+ const result = await _internals33.secretscan.execute({ directory }, {});
74215
74315
  const jsonStr = typeof result === "string" ? result : result.output;
74216
74316
  return JSON.parse(jsonStr);
74217
74317
  } catch (e) {
@@ -74226,7 +74326,7 @@ async function runSecretscan(directory) {
74226
74326
  return errorResult;
74227
74327
  }
74228
74328
  }
74229
- var MAX_FILE_PATH_LENGTH = 500, MAX_FILE_SIZE_BYTES, MAX_FILES_SCANNED = 1000, MAX_FINDINGS = 100, MAX_OUTPUT_BYTES2 = 512000, MAX_LINE_LENGTH = 1e4, MAX_CONTENT_BYTES, BINARY_SIGNATURES, BINARY_PREFIX_BYTES = 4, BINARY_NULL_CHECK_BYTES = 8192, BINARY_NULL_THRESHOLD = 0.1, DEFAULT_EXCLUDE_DIRS, DEFAULT_EXCLUDE_EXTENSIONS, SECRET_PATTERNS2, O_NOFOLLOW, secretscan, _internals32;
74329
+ var MAX_FILE_PATH_LENGTH = 500, MAX_FILE_SIZE_BYTES, MAX_FILES_SCANNED = 1000, MAX_FINDINGS = 100, MAX_OUTPUT_BYTES2 = 512000, MAX_LINE_LENGTH = 1e4, MAX_CONTENT_BYTES, BINARY_SIGNATURES, BINARY_PREFIX_BYTES = 4, BINARY_NULL_CHECK_BYTES = 8192, BINARY_NULL_THRESHOLD = 0.1, DEFAULT_EXCLUDE_DIRS, DEFAULT_EXCLUDE_EXTENSIONS, SECRET_PATTERNS2, O_NOFOLLOW, secretscan, _internals33;
74230
74330
  var init_secretscan = __esm(() => {
74231
74331
  init_zod();
74232
74332
  init_path_security();
@@ -74598,7 +74698,7 @@ var init_secretscan = __esm(() => {
74598
74698
  }
74599
74699
  }
74600
74700
  });
74601
- _internals32 = {
74701
+ _internals33 = {
74602
74702
  secretscan,
74603
74703
  runSecretscan
74604
74704
  };
@@ -75190,14 +75290,14 @@ function buildGoBackend() {
75190
75290
  selectEntryPoints
75191
75291
  };
75192
75292
  }
75193
- var PROFILE_ID = "go", IMPORT_REGEX_SINGLE, IMPORT_REGEX_GROUP, IMPORT_REGEX_GROUP_LINE, _internals33;
75293
+ var PROFILE_ID = "go", IMPORT_REGEX_SINGLE, IMPORT_REGEX_GROUP, IMPORT_REGEX_GROUP_LINE, _internals34;
75194
75294
  var init_go = __esm(() => {
75195
75295
  init_default_backend();
75196
75296
  init_profiles();
75197
75297
  IMPORT_REGEX_SINGLE = /^\s*import\s+(?:[a-zA-Z_.][a-zA-Z0-9_]*\s+)?"([^"]+)"/gm;
75198
75298
  IMPORT_REGEX_GROUP = /^\s*import\s*\(([\s\S]*?)\)/gm;
75199
75299
  IMPORT_REGEX_GROUP_LINE = /(?:[a-zA-Z_.][a-zA-Z0-9_]*\s+)?"([^"]+)"/g;
75200
- _internals33 = { extractImports };
75300
+ _internals34 = { extractImports };
75201
75301
  });
75202
75302
 
75203
75303
  // src/lang/backends/python.ts
@@ -75309,13 +75409,13 @@ function buildPythonBackend() {
75309
75409
  selectEntryPoints: selectEntryPoints2
75310
75410
  };
75311
75411
  }
75312
- var PROFILE_ID2 = "python", IMPORT_REGEX_FROM_WITH_TARGETS, IMPORT_REGEX_IMPORT, _internals34;
75412
+ var PROFILE_ID2 = "python", IMPORT_REGEX_FROM_WITH_TARGETS, IMPORT_REGEX_IMPORT, _internals35;
75313
75413
  var init_python = __esm(() => {
75314
75414
  init_default_backend();
75315
75415
  init_profiles();
75316
75416
  IMPORT_REGEX_FROM_WITH_TARGETS = /^\s*from\s+(\.*[\w.]*)\s+import\s+(\([^)]*\)|[^\n#]+)/gm;
75317
75417
  IMPORT_REGEX_IMPORT = /^\s*import\s+([^\n#]+)/gm;
75318
- _internals34 = { extractImports: extractImports2 };
75418
+ _internals35 = { extractImports: extractImports2 };
75319
75419
  });
75320
75420
 
75321
75421
  // src/test-impact/analyzer.ts
@@ -75539,7 +75639,7 @@ function addImpactEdgesForTestFile(testFile, content, impactMap) {
75539
75639
  return;
75540
75640
  }
75541
75641
  if (PYTHON_EXTENSIONS.has(ext)) {
75542
- const modules = _internals34.extractImports(testFile, content);
75642
+ const modules = _internals35.extractImports(testFile, content);
75543
75643
  for (const mod of modules) {
75544
75644
  const resolved = resolvePythonImport(testDir, mod);
75545
75645
  if (resolved !== null)
@@ -75548,7 +75648,7 @@ function addImpactEdgesForTestFile(testFile, content, impactMap) {
75548
75648
  return;
75549
75649
  }
75550
75650
  if (GO_EXTENSIONS.has(ext)) {
75551
- const imports = _internals33.extractImports(testFile, content);
75651
+ const imports = _internals34.extractImports(testFile, content);
75552
75652
  for (const importPath of imports) {
75553
75653
  const sourceFiles = resolveGoImport(testDir, importPath);
75554
75654
  for (const source of sourceFiles)
@@ -75575,8 +75675,8 @@ async function buildImpactMapInternal(cwd) {
75575
75675
  return impactMap;
75576
75676
  }
75577
75677
  async function buildImpactMap(cwd) {
75578
- const impactMap = await _internals35.buildImpactMapInternal(cwd);
75579
- await _internals35.saveImpactMap(cwd, impactMap);
75678
+ const impactMap = await _internals36.buildImpactMapInternal(cwd);
75679
+ await _internals36.saveImpactMap(cwd, impactMap);
75580
75680
  return impactMap;
75581
75681
  }
75582
75682
  async function loadImpactMap(cwd, options) {
@@ -75590,7 +75690,7 @@ async function loadImpactMap(cwd, options) {
75590
75690
  const hasValidValues = Object.values(map3).every((v) => Array.isArray(v) && v.every((item) => typeof item === "string"));
75591
75691
  if (hasValidValues) {
75592
75692
  const generatedAt = new Date(data.generatedAt).getTime();
75593
- if (!_internals35.isCacheStale(map3, generatedAt)) {
75693
+ if (!_internals36.isCacheStale(map3, generatedAt)) {
75594
75694
  return map3;
75595
75695
  }
75596
75696
  if (options?.skipRebuild) {
@@ -75610,13 +75710,13 @@ async function loadImpactMap(cwd, options) {
75610
75710
  if (options?.skipRebuild) {
75611
75711
  return {};
75612
75712
  }
75613
- return _internals35.buildImpactMap(cwd);
75713
+ return _internals36.buildImpactMap(cwd);
75614
75714
  }
75615
75715
  async function saveImpactMap(cwd, impactMap) {
75616
75716
  if (!path55.isAbsolute(cwd)) {
75617
75717
  throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
75618
75718
  }
75619
- _internals35.validateProjectRoot(cwd);
75719
+ _internals36.validateProjectRoot(cwd);
75620
75720
  const cacheDir2 = path55.join(cwd, ".swarm", "cache");
75621
75721
  const cachePath = path55.join(cacheDir2, "impact-map.json");
75622
75722
  if (!fs28.existsSync(cacheDir2)) {
@@ -75640,7 +75740,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
75640
75740
  };
75641
75741
  }
75642
75742
  const validFiles = changedFiles.filter((f) => typeof f === "string" && f.length > 0 && !f.includes("\x00"));
75643
- const impactMap = await _internals35.loadImpactMap(cwd);
75743
+ const impactMap = await _internals36.loadImpactMap(cwd);
75644
75744
  const impactedTestsSet = new Set;
75645
75745
  const untestedFiles = [];
75646
75746
  let visitedCount = 0;
@@ -75725,7 +75825,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
75725
75825
  budgetExceeded
75726
75826
  };
75727
75827
  }
75728
- var IMPORT_REGEX_ES, IMPORT_REGEX_REQUIRE, IMPORT_REGEX_REEXPORT, TS_EXTENSIONS, PYTHON_EXTENSIONS, GO_EXTENSIONS, EXTENSIONS_TO_TRY, goModuleCache, _internals35;
75828
+ var IMPORT_REGEX_ES, IMPORT_REGEX_REQUIRE, IMPORT_REGEX_REEXPORT, TS_EXTENSIONS, PYTHON_EXTENSIONS, GO_EXTENSIONS, EXTENSIONS_TO_TRY, goModuleCache, _internals36;
75729
75829
  var init_analyzer = __esm(() => {
75730
75830
  init_manager2();
75731
75831
  init_go();
@@ -75738,7 +75838,7 @@ var init_analyzer = __esm(() => {
75738
75838
  GO_EXTENSIONS = new Set([".go"]);
75739
75839
  EXTENSIONS_TO_TRY = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
75740
75840
  goModuleCache = new Map;
75741
- _internals35 = {
75841
+ _internals36 = {
75742
75842
  validateProjectRoot,
75743
75843
  normalizePath,
75744
75844
  isCacheStale,
@@ -76074,7 +76174,7 @@ function batchAppendTestRuns(records, workingDir) {
76074
76174
  }
76075
76175
  const historyPath = getHistoryPath(workingDir);
76076
76176
  const historyDir = path56.dirname(historyPath);
76077
- _internals36.validateProjectRoot(workingDir);
76177
+ _internals37.validateProjectRoot(workingDir);
76078
76178
  if (!fs29.existsSync(historyDir)) {
76079
76179
  fs29.mkdirSync(historyDir, { recursive: true });
76080
76180
  }
@@ -76197,7 +76297,7 @@ function getAllHistory(workingDir) {
76197
76297
  records.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
76198
76298
  return records;
76199
76299
  }
76200
- var MAX_HISTORY_PER_TEST = 20, MAX_ERROR_LENGTH = 500, MAX_STACK_LENGTH = 200, MAX_CHANGED_FILES = 50, HISTORY_WRITE_LOCK_TIMEOUT_MS = 5000, HISTORY_WRITE_LOCK_STALE_MS = 60000, HISTORY_WRITE_LOCK_BACKOFF_MS = 10, DANGEROUS_PROPERTY_NAMES, _internals36;
76300
+ var MAX_HISTORY_PER_TEST = 20, MAX_ERROR_LENGTH = 500, MAX_STACK_LENGTH = 200, MAX_CHANGED_FILES = 50, HISTORY_WRITE_LOCK_TIMEOUT_MS = 5000, HISTORY_WRITE_LOCK_STALE_MS = 60000, HISTORY_WRITE_LOCK_BACKOFF_MS = 10, DANGEROUS_PROPERTY_NAMES, _internals37;
76201
76301
  var init_history_store = __esm(() => {
76202
76302
  init_manager2();
76203
76303
  DANGEROUS_PROPERTY_NAMES = new Set([
@@ -76205,7 +76305,7 @@ var init_history_store = __esm(() => {
76205
76305
  "constructor",
76206
76306
  "prototype"
76207
76307
  ]);
76208
- _internals36 = {
76308
+ _internals37 = {
76209
76309
  validateProjectRoot
76210
76310
  };
76211
76311
  });
@@ -76331,7 +76431,7 @@ function readPackageJsonRaw(dir) {
76331
76431
  }
76332
76432
  }
76333
76433
  function readPackageJson(dir) {
76334
- return _internals37.readPackageJsonRaw(dir);
76434
+ return _internals38.readPackageJsonRaw(dir);
76335
76435
  }
76336
76436
  function readPackageJsonTestScript(dir) {
76337
76437
  return readPackageJson(dir)?.scripts?.test ?? null;
@@ -76501,7 +76601,7 @@ function buildTypescriptBackend() {
76501
76601
  selectEntryPoints: selectEntryPoints3
76502
76602
  };
76503
76603
  }
76504
- var PROFILE_ID3 = "typescript", IMPORT_REGEX_ES2, IMPORT_REGEX_BARE, IMPORT_REGEX_REQUIRE2, IMPORT_REGEX_DYNAMIC, IMPORT_REGEX_REEXPORT2, _internals37;
76604
+ var PROFILE_ID3 = "typescript", IMPORT_REGEX_ES2, IMPORT_REGEX_BARE, IMPORT_REGEX_REQUIRE2, IMPORT_REGEX_DYNAMIC, IMPORT_REGEX_REEXPORT2, _internals38;
76505
76605
  var init_typescript = __esm(() => {
76506
76606
  init_default_backend();
76507
76607
  init_profiles();
@@ -76510,7 +76610,7 @@ var init_typescript = __esm(() => {
76510
76610
  IMPORT_REGEX_REQUIRE2 = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
76511
76611
  IMPORT_REGEX_DYNAMIC = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
76512
76612
  IMPORT_REGEX_REEXPORT2 = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
76513
- _internals37 = {
76613
+ _internals38 = {
76514
76614
  readPackageJsonRaw,
76515
76615
  readPackageJsonTestScript,
76516
76616
  frameworkFromScriptsTest
@@ -76541,7 +76641,7 @@ __export(exports_dispatch, {
76541
76641
  pickedProfiles: () => pickedProfiles,
76542
76642
  pickBackend: () => pickBackend,
76543
76643
  clearDispatchCache: () => clearDispatchCache,
76544
- _internals: () => _internals38
76644
+ _internals: () => _internals39
76545
76645
  });
76546
76646
  import * as fs32 from "node:fs";
76547
76647
  import * as path59 from "node:path";
@@ -76596,7 +76696,7 @@ function findManifestRoot(start2) {
76596
76696
  return start2;
76597
76697
  }
76598
76698
  function evictIfNeeded() {
76599
- if (cache.size <= _internals38.cacheCapacity)
76699
+ if (cache.size <= _internals39.cacheCapacity)
76600
76700
  return;
76601
76701
  let oldestKey;
76602
76702
  let oldestOrder = Infinity;
@@ -76627,7 +76727,7 @@ async function pickBackend(dir) {
76627
76727
  evictIfNeeded();
76628
76728
  return null;
76629
76729
  }
76630
- const profiles = await _internals38.detectProjectLanguages(root);
76730
+ const profiles = await _internals39.detectProjectLanguages(root);
76631
76731
  if (profiles.length === 0) {
76632
76732
  cache.set(cacheKey, {
76633
76733
  hash: hash3,
@@ -76659,12 +76759,12 @@ function clearDispatchCache() {
76659
76759
  manifestRootCache.clear();
76660
76760
  insertCounter = 0;
76661
76761
  }
76662
- var _internals38, cache, insertCounter = 0, MANIFEST_FILES, _MANIFEST_SET, manifestRootCache;
76762
+ var _internals39, cache, insertCounter = 0, MANIFEST_FILES, _MANIFEST_SET, manifestRootCache;
76663
76763
  var init_dispatch = __esm(() => {
76664
76764
  init_backends();
76665
76765
  init_detector();
76666
76766
  init_registry_backend();
76667
- _internals38 = {
76767
+ _internals39 = {
76668
76768
  detectProjectLanguages,
76669
76769
  cacheCapacity: 64
76670
76770
  };
@@ -78521,9 +78621,9 @@ function getVersionFileVersion(dir) {
78521
78621
  async function runVersionCheck2(dir, _timeoutMs) {
78522
78622
  const startTime = Date.now();
78523
78623
  try {
78524
- const packageVersion = _internals39.getPackageVersion(dir);
78525
- const changelogVersion = _internals39.getChangelogVersion(dir);
78526
- const versionFileVersion = _internals39.getVersionFileVersion(dir);
78624
+ const packageVersion = _internals40.getPackageVersion(dir);
78625
+ const changelogVersion = _internals40.getChangelogVersion(dir);
78626
+ const versionFileVersion = _internals40.getVersionFileVersion(dir);
78527
78627
  const versions3 = [];
78528
78628
  if (packageVersion)
78529
78629
  versions3.push(`package.json: ${packageVersion}`);
@@ -78888,7 +78988,7 @@ async function runPreflight(dir, phase, config3) {
78888
78988
  const reportId = `preflight-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
78889
78989
  let validatedDir;
78890
78990
  try {
78891
- validatedDir = _internals39.validateDirectoryPath(dir);
78991
+ validatedDir = _internals40.validateDirectoryPath(dir);
78892
78992
  } catch (error93) {
78893
78993
  return {
78894
78994
  id: reportId,
@@ -78908,7 +79008,7 @@ async function runPreflight(dir, phase, config3) {
78908
79008
  }
78909
79009
  let validatedTimeout;
78910
79010
  try {
78911
- validatedTimeout = _internals39.validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
79011
+ validatedTimeout = _internals40.validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
78912
79012
  } catch (error93) {
78913
79013
  return {
78914
79014
  id: reportId,
@@ -78949,12 +79049,12 @@ async function runPreflight(dir, phase, config3) {
78949
79049
  });
78950
79050
  const checks5 = [];
78951
79051
  log("[Preflight] Running lint check...");
78952
- const lintResult = await _internals39.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
79052
+ const lintResult = await _internals40.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
78953
79053
  checks5.push(lintResult);
78954
79054
  log(`[Preflight] Lint check: ${lintResult.status} ${lintResult.message}`);
78955
79055
  if (!cfg.skipTests) {
78956
79056
  log("[Preflight] Running tests check...");
78957
- const testsResult = await _internals39.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
79057
+ const testsResult = await _internals40.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
78958
79058
  checks5.push(testsResult);
78959
79059
  log(`[Preflight] Tests check: ${testsResult.status} ${testsResult.message}`);
78960
79060
  } else {
@@ -78966,7 +79066,7 @@ async function runPreflight(dir, phase, config3) {
78966
79066
  }
78967
79067
  if (!cfg.skipSecrets) {
78968
79068
  log("[Preflight] Running secrets check...");
78969
- const secretsResult = await _internals39.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
79069
+ const secretsResult = await _internals40.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
78970
79070
  checks5.push(secretsResult);
78971
79071
  log(`[Preflight] Secrets check: ${secretsResult.status} ${secretsResult.message}`);
78972
79072
  } else {
@@ -78978,7 +79078,7 @@ async function runPreflight(dir, phase, config3) {
78978
79078
  }
78979
79079
  if (!cfg.skipEvidence) {
78980
79080
  log("[Preflight] Running evidence check...");
78981
- const evidenceResult = await _internals39.runEvidenceCheck(validatedDir);
79081
+ const evidenceResult = await _internals40.runEvidenceCheck(validatedDir);
78982
79082
  checks5.push(evidenceResult);
78983
79083
  log(`[Preflight] Evidence check: ${evidenceResult.status} ${evidenceResult.message}`);
78984
79084
  } else {
@@ -78989,12 +79089,12 @@ async function runPreflight(dir, phase, config3) {
78989
79089
  });
78990
79090
  }
78991
79091
  log("[Preflight] Running requirement coverage check...");
78992
- const reqCoverageResult = await _internals39.runRequirementCoverageCheck(validatedDir, phase);
79092
+ const reqCoverageResult = await _internals40.runRequirementCoverageCheck(validatedDir, phase);
78993
79093
  checks5.push(reqCoverageResult);
78994
79094
  log(`[Preflight] Requirement coverage check: ${reqCoverageResult.status} ${reqCoverageResult.message}`);
78995
79095
  if (!cfg.skipVersion) {
78996
79096
  log("[Preflight] Running version check...");
78997
- const versionResult = await _internals39.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
79097
+ const versionResult = await _internals40.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
78998
79098
  checks5.push(versionResult);
78999
79099
  log(`[Preflight] Version check: ${versionResult.status} ${versionResult.message}`);
79000
79100
  } else {
@@ -79057,10 +79157,10 @@ function formatPreflightMarkdown(report) {
79057
79157
  async function handlePreflightCommand(directory, _args) {
79058
79158
  const plan = await loadPlan(directory);
79059
79159
  const phase = plan?.current_phase ?? 1;
79060
- const report = await _internals39.runPreflight(directory, phase);
79061
- return _internals39.formatPreflightMarkdown(report);
79160
+ const report = await _internals40.runPreflight(directory, phase);
79161
+ return _internals40.formatPreflightMarkdown(report);
79062
79162
  }
79063
- var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG, _internals39;
79163
+ var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG, _internals40;
79064
79164
  var init_preflight_service = __esm(() => {
79065
79165
  init_gate_bridge();
79066
79166
  init_manager2();
@@ -79078,7 +79178,7 @@ var init_preflight_service = __esm(() => {
79078
79178
  testScope: "convention",
79079
79179
  linter: "biome"
79080
79180
  };
79081
- _internals39 = {
79181
+ _internals40 = {
79082
79182
  runPreflight,
79083
79183
  formatPreflightMarkdown,
79084
79184
  handlePreflightCommand,
@@ -80973,7 +81073,7 @@ async function getStatusData(directory, agents) {
80973
81073
  }
80974
81074
  function enrichWithLeanTurbo(status, directory) {
80975
81075
  const turboMode = hasActiveTurboMode();
80976
- const leanActive = _internals40.hasActiveLeanTurbo();
81076
+ const leanActive = _internals41.hasActiveLeanTurbo();
80977
81077
  let turboStrategy = "off";
80978
81078
  if (leanActive) {
80979
81079
  turboStrategy = "lean";
@@ -80992,7 +81092,7 @@ function enrichWithLeanTurbo(status, directory) {
80992
81092
  }
80993
81093
  }
80994
81094
  if (leanSessionID) {
80995
- const runState = _internals40.loadLeanTurboRunState(directory, leanSessionID);
81095
+ const runState = _internals41.loadLeanTurboRunState(directory, leanSessionID);
80996
81096
  if (runState) {
80997
81097
  status.leanTurboPhase = runState.phase;
80998
81098
  status.leanMaxParallelCoders = runState.maxParallelCoders;
@@ -81024,7 +81124,7 @@ function enrichWithLeanTurbo(status, directory) {
81024
81124
  }
81025
81125
  }
81026
81126
  }
81027
- status.fullAutoActive = _internals40.hasActiveFullAuto();
81127
+ status.fullAutoActive = _internals41.hasActiveFullAuto();
81028
81128
  return status;
81029
81129
  }
81030
81130
  function formatStatusMarkdown(status) {
@@ -81106,7 +81206,7 @@ async function handleStatusCommand(directory, agents) {
81106
81206
  }
81107
81207
  return formatStatusMarkdown(statusData);
81108
81208
  }
81109
- var _internals40;
81209
+ var _internals41;
81110
81210
  var init_status_service = __esm(() => {
81111
81211
  init_extractors();
81112
81212
  init_utils2();
@@ -81115,7 +81215,7 @@ var init_status_service = __esm(() => {
81115
81215
  init_state3();
81116
81216
  init_compaction_service();
81117
81217
  init_context_budget_service();
81118
- _internals40 = {
81218
+ _internals41 = {
81119
81219
  loadLeanTurboRunState,
81120
81220
  hasActiveLeanTurbo,
81121
81221
  hasActiveFullAuto
@@ -81206,7 +81306,7 @@ async function handleTurboCommand(directory, args2, sessionID) {
81206
81306
  if (arg0 === "on") {
81207
81307
  let strategy = "standard";
81208
81308
  try {
81209
- const { config: config3 } = _internals41.loadPluginConfigWithMeta(directory);
81309
+ const { config: config3 } = _internals42.loadPluginConfigWithMeta(directory);
81210
81310
  if (config3.turbo?.strategy === "lean") {
81211
81311
  strategy = "lean";
81212
81312
  }
@@ -81261,7 +81361,7 @@ function enableLeanTurbo(session, directory, sessionID) {
81261
81361
  let maxParallelCoders = 4;
81262
81362
  let conflictPolicy = "serialize";
81263
81363
  try {
81264
- const { config: config3 } = _internals41.loadPluginConfigWithMeta(directory);
81364
+ const { config: config3 } = _internals42.loadPluginConfigWithMeta(directory);
81265
81365
  const leanConfig = config3.turbo?.lean;
81266
81366
  if (leanConfig) {
81267
81367
  maxParallelCoders = leanConfig.max_parallel_coders ?? 4;
@@ -81331,13 +81431,13 @@ function buildStatusMessage2(session, directory, sessionID) {
81331
81431
  ].join(`
81332
81432
  `);
81333
81433
  }
81334
- var _internals41;
81434
+ var _internals42;
81335
81435
  var init_turbo = __esm(() => {
81336
81436
  init_config();
81337
81437
  init_state();
81338
81438
  init_state3();
81339
81439
  init_logger();
81340
- _internals41 = {
81440
+ _internals42 = {
81341
81441
  loadPluginConfigWithMeta
81342
81442
  };
81343
81443
  });
@@ -81430,7 +81530,7 @@ function formatCommandNotFound(tokens) {
81430
81530
  const attemptedCommand = tokens[0] || "";
81431
81531
  const MAX_DISPLAY = 100;
81432
81532
  const displayCommand = attemptedCommand.length > MAX_DISPLAY ? `${attemptedCommand.slice(0, MAX_DISPLAY)}...` : attemptedCommand;
81433
- const similar = _internals42.findSimilarCommands(attemptedCommand);
81533
+ const similar = _internals43.findSimilarCommands(attemptedCommand);
81434
81534
  const header = `Command \`/swarm ${displayCommand}\` not found.`;
81435
81535
  const suggestions = similar.length > 0 ? `Did you mean:
81436
81536
  ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
@@ -81932,7 +82032,7 @@ async function buildSwarmCommandPrompt(args2) {
81932
82032
  activeAgentName,
81933
82033
  registeredAgents
81934
82034
  } = args2;
81935
- const resolved = _internals42.resolveCommand(tokens);
82035
+ const resolved = _internals43.resolveCommand(tokens);
81936
82036
  if (!resolved) {
81937
82037
  if (tokens.length === 0) {
81938
82038
  return buildHelpText();
@@ -81993,6 +82093,19 @@ function agentHasSwarmCommandTool(activeAgentName, agents, registeredAgents) {
81993
82093
  return AGENT_TOOL_MAP[baseName]?.includes("swarm_command") === true;
81994
82094
  }
81995
82095
  function formatCanonicalPromptFallback(args2) {
82096
+ if (/^\s*\[MODE:/.test(args2.text)) {
82097
+ return [
82098
+ `The user typed \`${args2.original}\`.`,
82099
+ "The line below is a swarm MODE-activation signal, NOT output to display.",
82100
+ "Enter the mode named in its `[MODE: X ...]` header now: follow your",
82101
+ 'prompt’s "### MODE: X" section, load the SKILL.md it references, and',
82102
+ "follow that protocol exactly. Treat any text after the closing bracket as",
82103
+ "additional instructions. Do NOT echo this signal verbatim.",
82104
+ "",
82105
+ args2.text
82106
+ ].join(`
82107
+ `);
82108
+ }
81996
82109
  return [
81997
82110
  `The user typed \`${args2.original}\`.`,
81998
82111
  "Canonical opencode-swarm command output follows.",
@@ -82085,7 +82198,7 @@ function findSimilarCommands(query) {
82085
82198
  }
82086
82199
  const scored = VALID_COMMANDS.map((cmd) => {
82087
82200
  const cmdLower = cmd.toLowerCase();
82088
- const fullScore = _internals42.levenshteinDistance(q, cmdLower);
82201
+ const fullScore = _internals43.levenshteinDistance(q, cmdLower);
82089
82202
  let tokenScore = Infinity;
82090
82203
  if (cmd.includes(" ") || cmd.includes("-")) {
82091
82204
  const qTokens = q.split(/[\s-]+/);
@@ -82098,7 +82211,7 @@ function findSimilarCommands(query) {
82098
82211
  for (const ct of cmdTokens) {
82099
82212
  if (ct.length === 0)
82100
82213
  continue;
82101
- const dist = _internals42.levenshteinDistance(qt, ct);
82214
+ const dist = _internals43.levenshteinDistance(qt, ct);
82102
82215
  if (dist < minDist)
82103
82216
  minDist = dist;
82104
82217
  }
@@ -82108,7 +82221,7 @@ function findSimilarCommands(query) {
82108
82221
  }
82109
82222
  const dashStrippedQ = q.replace(/-/g, "");
82110
82223
  const dashStrippedCmd = cmdLower.replace(/-/g, "");
82111
- const dashScore = _internals42.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
82224
+ const dashScore = _internals43.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
82112
82225
  const score = Math.min(fullScore, tokenScore, dashScore);
82113
82226
  return { cmd, score };
82114
82227
  });
@@ -82140,11 +82253,11 @@ async function handleHelpCommand(ctx) {
82140
82253
  return buildHelpText2();
82141
82254
  }
82142
82255
  const tokens = targetCommand.split(/\s+/);
82143
- const resolved = _internals42.resolveCommand(tokens);
82256
+ const resolved = _internals43.resolveCommand(tokens);
82144
82257
  if (resolved) {
82145
- return _internals42.buildDetailedHelp(resolved.key, resolved.entry);
82258
+ return _internals43.buildDetailedHelp(resolved.key, resolved.entry);
82146
82259
  }
82147
- const similar = _internals42.findSimilarCommands(targetCommand);
82260
+ const similar = _internals43.findSimilarCommands(targetCommand);
82148
82261
  const { buildHelpText: fullHelp } = await Promise.resolve().then(() => (init_commands(), exports_commands));
82149
82262
  if (similar.length > 0) {
82150
82263
  return `Command '/swarm ${targetCommand}' not found.
@@ -82238,7 +82351,7 @@ function resolveCommand(tokens) {
82238
82351
  }
82239
82352
  return null;
82240
82353
  }
82241
- var COMMAND_REGISTRY, VALID_COMMANDS, _internals42, validation;
82354
+ var COMMAND_REGISTRY, VALID_COMMANDS, _internals43, validation;
82242
82355
  var init_registry = __esm(() => {
82243
82356
  init_acknowledge_spec_drift();
82244
82357
  init_agents();
@@ -82264,6 +82377,7 @@ var init_registry = __esm(() => {
82264
82377
  init_knowledge();
82265
82378
  init_memory2();
82266
82379
  init_plan();
82380
+ init_pr_feedback();
82267
82381
  init_pr_review();
82268
82382
  init_preflight();
82269
82383
  init_promote();
@@ -82311,7 +82425,7 @@ var init_registry = __esm(() => {
82311
82425
  clashesWithNativeCcCommand: "/agents"
82312
82426
  },
82313
82427
  help: {
82314
- handler: (ctx) => _internals42.handleHelpCommand(ctx),
82428
+ handler: (ctx) => _internals43.handleHelpCommand(ctx),
82315
82429
  description: "Show help for swarm commands",
82316
82430
  category: "core",
82317
82431
  args: "[command]",
@@ -82544,7 +82658,7 @@ Subcommands:
82544
82658
  handler: (ctx) => handleCouncilCommand(ctx.directory, ctx.args),
82545
82659
  description: "Enter architect MODE: COUNCIL — multi-model deliberation [question] [--preset <name>] [--spec-review]",
82546
82660
  args: "<question> [--preset <name>] [--spec-review]",
82547
- details: "Triggers the architect to convene a three-agent General Council: Generalist (reviewer model), Skeptic (critic model), and Domain Expert (SME model). Use --preset <name> to choose a named member preset from council.general.presets. " + "The architect first runs 1–3 targeted web searches and passes a compiled RESEARCH CONTEXT " + "to all three agents before dispatching them in parallel. Agents deliberate using the NSED peer-review protocol (Round 1 independent analysis, Round 2 MAINTAIN/CONCEDE/NUANCE for disagreements). The architect synthesizes the final answer directly from convene_general_council output. --spec-review switches to single-pass advisory mode for spec review. Requires council.general.enabled: true and a search API key in opencode-swarm.json.",
82661
+ details: "Triggers the architect to convene a three-agent General Council: Generalist (reviewer model), Skeptic (critic model), and Domain Expert (SME model). Use --preset <name> to choose a named member preset from council.general.presets. " + "The architect first runs 1–3 targeted web searches and passes a compiled RESEARCH CONTEXT " + "to all three agents before dispatching them in parallel. Agents deliberate using the NSED peer-review protocol (Round 1 independent analysis, Round 2 MAINTAIN/CONCEDE/NUANCE for disagreements). The architect synthesizes the final answer directly from convene_general_council output. --spec-review switches to single-pass advisory mode for spec review. Requires council.general.enabled: true and a search API key in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides.",
82548
82662
  category: "agent"
82549
82663
  },
82550
82664
  "pr-review": {
@@ -82554,6 +82668,13 @@ Subcommands:
82554
82668
  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).",
82555
82669
  category: "agent"
82556
82670
  },
82671
+ "pr-feedback": {
82672
+ handler: async (ctx) => handlePrFeedbackCommand(ctx.directory, ctx.args),
82673
+ description: "Ingest and close known PR feedback (review comments, CI failures, conflicts) [pr] [instructions]",
82674
+ args: "[url|owner/repo#N|N] [instructions...]",
82675
+ details: "Triggers MODE: PR_FEEDBACK — ingests existing pull-request feedback (review threads, requested changes, CI/check failures, merge conflicts, stale branch state, pasted notes), verifies every claim against source, clusters related problems, fixes confirmed items, validates the branch, and reports closure status for every ledger item. Distinct from /swarm pr-review, which discovers new findings. The PR reference is optional: with none, the architect builds the ledger from the current PR/branch; text after the reference is forwarded as extra instructions. Supports full GitHub URL, owner/repo#N shorthand, or bare PR number (resolved against origin).",
82676
+ category: "agent"
82677
+ },
82557
82678
  "deep-dive": {
82558
82679
  handler: async (ctx) => handleDeepDiveCommand(ctx.directory, ctx.args),
82559
82680
  description: "Launch deep codebase audit with parallel explorer waves, dual reviewers, and critic challenge [scope]",
@@ -82782,7 +82903,7 @@ Subcommands:
82782
82903
  }
82783
82904
  };
82784
82905
  VALID_COMMANDS = Object.keys(COMMAND_REGISTRY);
82785
- _internals42 = {
82906
+ _internals43 = {
82786
82907
  handleHelpCommand,
82787
82908
  validateAliases,
82788
82909
  resolveCommand,
@@ -82790,7 +82911,7 @@ Subcommands:
82790
82911
  findSimilarCommands,
82791
82912
  buildDetailedHelp
82792
82913
  };
82793
- validation = _internals42.validateAliases();
82914
+ validation = _internals43.validateAliases();
82794
82915
  if (!validation.valid) {
82795
82916
  throw new Error(`COMMAND_REGISTRY alias validation failed:
82796
82917
  ${validation.errors.join(`
@@ -82965,7 +83086,7 @@ Present the eleven gates with their defaults (DEFAULT_QA_GATES) as a single user
82965
83086
  - council_mode (default: OFF) — multi-member council gate (recommended for high-impact architecture, public APIs, schema/data mutation, security-sensitive code)
82966
83087
  - hallucination_guard (default: OFF) — when enabled, mandatory per-phase API/signature/claim/citation verification via critic_hallucination_verifier at PHASE-WRAP; phase_complete will REJECT phase completion unless .swarm/evidence/{phase}/hallucination-guard.json exists with an APPROVED verdict (recommended for claim-heavy or research-heavy work)
82967
83088
  - mutation_test (default: OFF) — when enabled, runs mutation testing on source files touched this phase via generate_mutants + mutation_test + write_mutation_evidence at PHASE-WRAP; FAIL verdict blocks phase_complete; WARN is non-blocking (recommended for projects with coverage gaps or safety-critical code)
82968
- - council_general_review (default: OFF) — when enabled, MODE: SPECIFY runs convene_general_council on the draft spec before the critic-gate; the architect runs a curated web_search pass, dispatches council_generalist / council_skeptic / council_domain_expert in parallel with a shared RESEARCH CONTEXT block, deliberates on disagreements, and synthesizes the result directly into the spec (recommended for novel architecture, unclear best practices, or high-risk design decisions). Requires council.general.enabled: true and a configured search API key.
83089
+ - council_general_review (default: OFF) — when enabled, MODE: SPECIFY runs convene_general_council on the draft spec before the critic-gate; the architect runs a curated web_search pass, dispatches council_generalist / council_skeptic / council_domain_expert in parallel with a shared RESEARCH CONTEXT block, deliberates on disagreements, and synthesizes the result directly into the spec (recommended for novel architecture, unclear best practices, or high-risk design decisions). Requires council.general.enabled: true and a configured search API key in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides.
82969
83090
  - drift_check (default: ON) — when enabled, mandatory per-phase drift verification via critic_drift_verifier at PHASE-WRAP; compares implemented changes against spec.md intent; hard-blocks phase_complete when spec.md exists and drift evidence is missing or REJECTED; advisory-only when no spec.md exists (recommended for all projects with a specification)
82970
83091
  - final_council (default: OFF) - when enabled, after all phases complete the architect dispatches the same five phase-council members (\`critic\`, \`reviewer\`, \`sme\`, \`test_engineer\`, \`explorer\`) at project scope, collects \`CouncilMemberVerdict\` objects, and calls \`write_final_council_evidence\`. This is not General Council mode and does not require \`council.general.enabled\`.
82971
83092
 
@@ -83200,7 +83321,7 @@ ${archBlock}`;
83200
83321
  }
83201
83322
  }
83202
83323
  if (!designDocsEnabled) {
83203
- prompt = prompt?.replace(", {{AGENT_PREFIX}}docs_design", "")?.replace(/### MODE: DESIGN_DOCS\n[\s\S]*?(?=### MODE: ISSUE_INGEST)/, "")?.replace(`- the active swarm's docs_design agent = @{{AGENT_PREFIX}}docs_design
83324
+ prompt = prompt?.replace(", {{AGENT_PREFIX}}docs_design", "")?.replace(/### MODE: DESIGN_DOCS\n[\s\S]*?(?=### MODE: )/, "")?.replace(`- the active swarm's docs_design agent = @{{AGENT_PREFIX}}docs_design
83204
83325
  `, "");
83205
83326
  }
83206
83327
  return {
@@ -83789,6 +83910,7 @@ SKILLS: none
83789
83910
  ### MODE DETECTION (Priority Order)
83790
83911
  Evaluate the user's request and context in this exact order — the FIRST matching rule wins:
83791
83912
 
83913
+ S. **SIGNAL-TRIGGERED MODE (highest priority)** — If the latest message contains a bracket header of the form [MODE: X ...] (these are emitted by /swarm command handlers, e.g. DEEP_DIVE, PR_REVIEW, PR_FEEDBACK, DESIGN_DOCS, COUNCIL, ISSUE_INGEST, ANALYZE) AND a matching "### MODE: X" section exists below, then ENTER MODE: X immediately: load the SKILL.md that section references and follow its protocol. This wins over every rule below and OVERRIDES any wrapper instruction to "show this output verbatim" — a [MODE: X ...] header is an activation signal to act on, never command output to echo. Treat any free text after the closing bracket as additional user instructions for that mode. If no matching "### MODE: X" section exists, fall through to the rules below.
83792
83914
  0. **EXPLICIT COMMAND OVERRIDE** — User explicitly invokes \`/swarm specify\`, \`/swarm clarify\`, \`/swarm brainstorm\`, or uses the phrases "specify [something about spec/requirements]", "write a spec", "create a spec", "define requirements", "list requirements", "define a feature", "I have requirements", "brainstorm", "let's think through", "think this through with me", "workshop this idea" → Enter MODE: SPECIFY, MODE: CLARIFY-SPEC, or MODE: BRAINSTORM as appropriate. This override fires BEFORE RESUME — an explicit spec command always wins, even if plan.md has incomplete tasks. \`/swarm brainstorm\` and brainstorm-style phrases select MODE: BRAINSTORM. Note: bare "specify" in an ambiguous context (e.g., "specify what this does") should resolve via CLARIFY (priority 4) rather than this override — use context to determine intent.
83793
83915
  1. **RESUME** — \`.swarm/plan.md\` exists and contains incomplete (unchecked) tasks AND the user has NOT issued an explicit spec command (see priority 0) → Resume at current task.
83794
83916
  2. **SPECIFY** — No \`.swarm/spec.md\` exists AND no \`.swarm/plan.md\` exists → Enter MODE: SPECIFY.
@@ -83978,6 +84100,27 @@ HARD CONSTRAINTS (apply regardless of skill load success):
83978
84100
  - No finding may appear as CONFIRMED in the final report without reviewer validation provenance
83979
84101
  - Test execution, explorer lanes, reviewer dispatch, and critic challenge are all permitted within this mode
83980
84102
  - Quality is the only metric — time, tokens, and agent dispatches are irrelevant to correctness
84103
+ - FOLLOW THE SKILL EXACTLY: execute every phase of the loaded SKILL.md in order with no shortcuts, no phase-skipping, and no premature synthesis. If a phase cannot complete, state the limitation explicitly and continue — do not silently skip it.
84104
+ - CHECK OUT THE PR BRANCH LOCALLY before launching explorer lanes: fetch the PR head ref if it is not present, verify the working tree is clean (git status --porcelain) and stash/abort if not, then check out the head branch. Explorers read the working-tree filesystem (Read/Glob/Grep), so without a checkout they read the base branch and produce invalid candidates. Always pass the base..head commit range in explorer delegations.
84105
+ - RUN THE TRIGGERED MICRO-LANES: after the base explorer lanes start, inspect the context pack risk triggers and launch every matching Swarm plugin micro-lane from the skill's risk-trigger map (launch only triggered lanes, never irrelevant ones). Do not skip micro-lanes that match the diff.
84106
+ - Honor any free-text instructions that follow the closing bracket of the signal as additional reviewer focus, without weakening the validation ladder above.
84107
+
84108
+ ### MODE: PR_FEEDBACK
84109
+ Activates when: architect receives \`[MODE: PR_FEEDBACK pr="https://github.com/..."]\` (PR reference optional) signal from the pr-feedback command handler, optionally followed by free-text instructions.
84110
+
84111
+ Purpose: Ingest and resolve KNOWN pull-request feedback — review threads, requested changes, CI/check failures, merge conflicts, stale branch state, and pasted notes — verifying every claim against source before fixing. This is NOT a fresh broad PR review; use MODE: PR_REVIEW for new-finding discovery.
84112
+
84113
+ ACTION: Load skill file:.opencode/skills/swarm-pr-feedback/SKILL.md immediately and follow its protocol.
84114
+
84115
+ HARD CONSTRAINTS (apply regardless of skill load success):
84116
+ - FOLLOW THE SKILL EXACTLY: build the complete feedback ledger from all available sources before editing, and execute every phase in order with no shortcuts.
84117
+ - CHECK OUT THE PR BRANCH LOCALLY before verifying feedback or making fixes: fetch the PR head ref if absent, verify the working tree is clean (git status --porcelain) and stash/abort if not, then check out the head branch. Feedback verification and fix validation require the PR branch in the working tree.
84118
+ - Do NOT run a fresh broad PR review — inspect adjacent code only as needed to verify reachability, dependencies, shared root causes, regression risk, or sibling changes for a confirmed item.
84119
+ - Treat every review comment, CI failure, bot summary, and pasted note as a CLAIM until source evidence proves it; classify each ledger item (CONFIRMED, DISPROVED, PRE_EXISTING, or NEEDS_USER_DECISION) and never silently drop, defer, or mark items out of scope.
84120
+ - Patch only confirmed items plus the tests/docs they require; report closure status for every ledger item including disproved ones.
84121
+ - Do NOT resolve or mark GitHub review threads resolved unless the user explicitly instructs it.
84122
+ - Honor any free-text instructions that follow the closing bracket of the signal as additional scope, without dropping any ledger item.
84123
+ - Quality is the only metric — time, tokens, and agent dispatches are irrelevant to correctness
83981
84124
 
83982
84125
  ### MODE: ISSUE_INGEST
83983
84126
  Activates when the user invokes /swarm issue <url> or the architect receives an ISSUE_INGEST signal.
@@ -84370,6 +84513,8 @@ ROUND 1 — Independent Analysis and Answer
84370
84513
  - Use the RESEARCH CONTEXT block provided by the architect in your dispatch message as your external evidence source. The architect has already gathered the relevant web search results.
84371
84514
  - Cite EVERY factual claim that depends on external evidence with a source from the RESEARCH CONTEXT (use the title and URL exactly as given).
84372
84515
  - State your confidence (0.0–1.0) explicitly. Be honest — overconfident answers hurt the council.
84516
+ - For current, latest, today, now, or otherwise time-sensitive claims, training knowledge is NOT evidence. If the RESEARCH CONTEXT is missing, stale, or ambiguous, say the claim is not established instead of filling the gap from memory.
84517
+ - Treat the dispatch message's CURRENT DATE as authoritative for relative time. Do not append your own training cutoff year to search-oriented reasoning or recommendations.
84373
84518
  - Enumerate areas of uncertainty so the architect knows where you're guessing vs. where you're sure.
84374
84519
  - Do NOT coordinate with other members. You will not see their responses until Round 2.
84375
84520
  - Do NOT pad. Be concise. Substance over volume.
@@ -84412,7 +84557,8 @@ Notes:
84412
84557
  - For Round 1: leave \`disagreementTopics\` as []. For Round 2: list the specific disagreement topics this response addresses.`, HARD_RULES = `================================================================
84413
84558
  HARD RULES
84414
84559
  ================================================================
84415
- - You have no tools. Reason from the provided RESEARCH CONTEXT and your training knowledge.
84560
+ - You have no tools. Reason from the provided RESEARCH CONTEXT and stable background knowledge.
84561
+ - Training knowledge may provide stable background only; it must not support current facts, rankings, prices, release status, active best practices, or "state of the art" claims.
84416
84562
  - Never invent sources. If the RESEARCH CONTEXT does not cover a needed claim, say so in \`areasOfUncertainty\`.
84417
84563
  - Never echo other members' responses verbatim. Paraphrase or quote with attribution.
84418
84564
  - Stay within your role and persona. The architect chose you for a specific perspective.`, GENERALIST_COUNCIL_PROMPT, SKEPTIC_COUNCIL_PROMPT, DOMAIN_EXPERT_COUNCIL_PROMPT;
@@ -91190,7 +91336,7 @@ __export(exports_runtime, {
91190
91336
  getSupportedLanguages: () => getSupportedLanguages,
91191
91337
  getInitializedLanguages: () => getInitializedLanguages,
91192
91338
  clearParserCache: () => clearParserCache,
91193
- _internals: () => _internals51
91339
+ _internals: () => _internals52
91194
91340
  });
91195
91341
  import * as path99 from "node:path";
91196
91342
  import { fileURLToPath as fileURLToPath4 } from "node:url";
@@ -91200,10 +91346,10 @@ async function initTreeSitter() {
91200
91346
  const thisDir = path99.dirname(fileURLToPath4(import.meta.url));
91201
91347
  const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
91202
91348
  if (isSource) {
91203
- await _internals51.parserInit();
91349
+ await _internals52.parserInit();
91204
91350
  } else {
91205
91351
  const grammarsDir = getGrammarsDirAbsolute();
91206
- await _internals51.parserInit({
91352
+ await _internals52.parserInit({
91207
91353
  locateFile(scriptName) {
91208
91354
  return path99.join(grammarsDir, scriptName);
91209
91355
  }
@@ -91308,12 +91454,12 @@ function getInitializedLanguages() {
91308
91454
  function getSupportedLanguages() {
91309
91455
  return Object.keys(LANGUAGE_WASM_MAP);
91310
91456
  }
91311
- var parserCache, initializedLanguages, treeSitterInitPromise = null, _internals51, LANGUAGE_WASM_MAP;
91457
+ var parserCache, initializedLanguages, treeSitterInitPromise = null, _internals52, LANGUAGE_WASM_MAP;
91312
91458
  var init_runtime = __esm(() => {
91313
91459
  init_tree_sitter();
91314
91460
  parserCache = new Map;
91315
91461
  initializedLanguages = new Set;
91316
- _internals51 = {
91462
+ _internals52 = {
91317
91463
  parserInit: Parser.init
91318
91464
  };
91319
91465
  LANGUAGE_WASM_MAP = {
@@ -92216,9 +92362,9 @@ var init_search_knowledge = __esm(() => {
92216
92362
  var exports_knowledge_recall = {};
92217
92363
  __export(exports_knowledge_recall, {
92218
92364
  knowledge_recall: () => knowledge_recall,
92219
- _internals: () => _internals52
92365
+ _internals: () => _internals53
92220
92366
  });
92221
- var knowledge_recall, _internals52;
92367
+ var knowledge_recall, _internals53;
92222
92368
  var init_knowledge_recall = __esm(() => {
92223
92369
  init_zod();
92224
92370
  init_config();
@@ -92299,7 +92445,7 @@ var init_knowledge_recall = __esm(() => {
92299
92445
  return JSON.stringify(result);
92300
92446
  }
92301
92447
  });
92302
- _internals52 = {
92448
+ _internals53 = {
92303
92449
  knowledge_recall
92304
92450
  };
92305
92451
  });
@@ -92354,7 +92500,7 @@ __export(exports_curator_drift, {
92354
92500
  runDeterministicDriftCheck: () => runDeterministicDriftCheck,
92355
92501
  readPriorDriftReports: () => readPriorDriftReports,
92356
92502
  buildDriftInjectionText: () => buildDriftInjectionText,
92357
- _internals: () => _internals55
92503
+ _internals: () => _internals56
92358
92504
  });
92359
92505
  import * as fs71 from "node:fs";
92360
92506
  import * as path108 from "node:path";
@@ -92403,7 +92549,7 @@ async function runDeterministicDriftCheck(directory, phase, curatorResult, confi
92403
92549
  try {
92404
92550
  const planMd = await readSwarmFileAsync(directory, "plan.md");
92405
92551
  const specMd = await readSwarmFileAsync(directory, "spec.md");
92406
- const priorReports = await _internals55.readPriorDriftReports(directory);
92552
+ const priorReports = await _internals56.readPriorDriftReports(directory);
92407
92553
  const complianceCount = curatorResult.compliance.length;
92408
92554
  const warningCompliance = curatorResult.compliance.filter((obs) => obs.severity === "warning");
92409
92555
  let alignment = "ALIGNED";
@@ -92466,7 +92612,7 @@ async function runDeterministicDriftCheck(directory, phase, curatorResult, confi
92466
92612
  scope_additions: [],
92467
92613
  injection_summary: injectionSummary
92468
92614
  };
92469
- const reportPath = await _internals55.writeDriftReport(directory, report);
92615
+ const reportPath = await _internals56.writeDriftReport(directory, report);
92470
92616
  getGlobalEventBus().publish("curator.drift.completed", {
92471
92617
  phase,
92472
92618
  alignment,
@@ -92529,12 +92675,12 @@ function buildDriftInjectionText(report, maxChars) {
92529
92675
  }
92530
92676
  return text.slice(0, maxChars);
92531
92677
  }
92532
- var DRIFT_REPORT_PREFIX = "drift-report-phase-", _internals55;
92678
+ var DRIFT_REPORT_PREFIX = "drift-report-phase-", _internals56;
92533
92679
  var init_curator_drift = __esm(() => {
92534
92680
  init_event_bus();
92535
92681
  init_logger();
92536
92682
  init_utils2();
92537
- _internals55 = {
92683
+ _internals56 = {
92538
92684
  readPriorDriftReports,
92539
92685
  writeDriftReport,
92540
92686
  runDeterministicDriftCheck,
@@ -92546,7 +92692,7 @@ var init_curator_drift = __esm(() => {
92546
92692
  var exports_design_doc_drift = {};
92547
92693
  __export(exports_design_doc_drift, {
92548
92694
  runDesignDocDriftCheck: () => runDesignDocDriftCheck,
92549
- _internals: () => _internals66
92695
+ _internals: () => _internals67
92550
92696
  });
92551
92697
  import * as fs106 from "node:fs";
92552
92698
  import * as path145 from "node:path";
@@ -92678,7 +92824,7 @@ async function runDesignDocDriftCheck(directory, phase, outDir) {
92678
92824
  return null;
92679
92825
  }
92680
92826
  }
92681
- var DOC_DRIFT_REPORT_PREFIX = "doc-drift-phase-", MAX_TRACEABILITY_BYTES, DESIGN_DOC_FILES, TRACEABILITY_REL, _internals66;
92827
+ var DOC_DRIFT_REPORT_PREFIX = "doc-drift-phase-", MAX_TRACEABILITY_BYTES, DESIGN_DOC_FILES, TRACEABILITY_REL, _internals67;
92682
92828
  var init_design_doc_drift = __esm(() => {
92683
92829
  init_event_bus();
92684
92830
  init_logger();
@@ -92692,7 +92838,7 @@ var init_design_doc_drift = __esm(() => {
92692
92838
  "idiom-notes": path145.join("reference", "idiom-notes.md")
92693
92839
  };
92694
92840
  TRACEABILITY_REL = path145.join("reference", "traceability.json");
92695
- _internals66 = {
92841
+ _internals67 = {
92696
92842
  mtimeMsOrNull,
92697
92843
  resolveAnchorWithin,
92698
92844
  DESIGN_DOC_FILES
@@ -92703,7 +92849,7 @@ var init_design_doc_drift = __esm(() => {
92703
92849
  var exports_project_context = {};
92704
92850
  __export(exports_project_context, {
92705
92851
  buildProjectContext: () => buildProjectContext,
92706
- _internals: () => _internals77,
92852
+ _internals: () => _internals78,
92707
92853
  LANG_BACKEND_DETECTION_TIMEOUT_MS: () => LANG_BACKEND_DETECTION_TIMEOUT_MS
92708
92854
  });
92709
92855
  import * as fs130 from "node:fs";
@@ -92787,7 +92933,7 @@ function selectLintCommand(backend, directory) {
92787
92933
  return null;
92788
92934
  }
92789
92935
  async function buildProjectContext(directory) {
92790
- const backend = await _internals77.pickBackend(directory);
92936
+ const backend = await _internals78.pickBackend(directory);
92791
92937
  if (!backend)
92792
92938
  return null;
92793
92939
  const ctx = emptyProjectContext();
@@ -92818,16 +92964,16 @@ async function buildProjectContext(directory) {
92818
92964
  if (backend.prompts.reviewerChecklist.length > 0) {
92819
92965
  ctx.REVIEWER_CHECKLIST = bulletList(backend.prompts.reviewerChecklist);
92820
92966
  }
92821
- const profiles = _internals77.pickedProfiles(directory);
92967
+ const profiles = _internals78.pickedProfiles(directory);
92822
92968
  if (profiles.length > 1) {
92823
92969
  ctx.PROJECT_CONTEXT_SECONDARY_LANGUAGES = profiles.slice(1).map((p) => p.id).join(", ");
92824
92970
  }
92825
92971
  return ctx;
92826
92972
  }
92827
- var LANG_BACKEND_DETECTION_TIMEOUT_MS = 300, _internals77;
92973
+ var LANG_BACKEND_DETECTION_TIMEOUT_MS = 300, _internals78;
92828
92974
  var init_project_context = __esm(() => {
92829
92975
  init_dispatch();
92830
- _internals77 = {
92976
+ _internals78 = {
92831
92977
  pickBackend,
92832
92978
  pickedProfiles
92833
92979
  };
@@ -93208,7 +93354,7 @@ import * as path76 from "node:path";
93208
93354
  import * as crypto7 from "node:crypto";
93209
93355
  import * as fs44 from "node:fs";
93210
93356
  import * as path75 from "node:path";
93211
- var _internals43 = {
93357
+ var _internals44 = {
93212
93358
  readFileSync: fs44.readFileSync,
93213
93359
  writeFileSync: fs44.writeFileSync,
93214
93360
  mkdirSync: fs44.mkdirSync,
@@ -93218,7 +93364,7 @@ var _internals43 = {
93218
93364
  createHash: crypto7.createHash.bind(crypto7)
93219
93365
  };
93220
93366
  function computeContentHash(content) {
93221
- return _internals43.createHash("sha256").update(content, "utf-8").digest("hex");
93367
+ return _internals44.createHash("sha256").update(content, "utf-8").digest("hex");
93222
93368
  }
93223
93369
  function createEmptyContextMap() {
93224
93370
  return {
@@ -93233,10 +93379,10 @@ function createEmptyContextMap() {
93233
93379
  function loadContextMap(directory) {
93234
93380
  const filePath = path75.join(directory, ".swarm", "context-map.json");
93235
93381
  try {
93236
- if (!_internals43.existsSync(filePath)) {
93382
+ if (!_internals44.existsSync(filePath)) {
93237
93383
  return null;
93238
93384
  }
93239
- const raw = _internals43.readFileSync(filePath, "utf-8");
93385
+ const raw = _internals44.readFileSync(filePath, "utf-8");
93240
93386
  const parsed = JSON.parse(raw);
93241
93387
  if (typeof parsed !== "object" || parsed === null || parsed.schema_version !== 1) {
93242
93388
  return null;
@@ -93250,14 +93396,14 @@ function saveContextMap(map3, directory) {
93250
93396
  const swarmDir = path75.join(directory, ".swarm");
93251
93397
  const tmpPath = path75.join(swarmDir, "context-map.tmp");
93252
93398
  const finalPath = path75.join(swarmDir, "context-map.json");
93253
- _internals43.mkdirSync(swarmDir, { recursive: true });
93399
+ _internals44.mkdirSync(swarmDir, { recursive: true });
93254
93400
  const updated = {
93255
93401
  ...map3,
93256
93402
  generated_at: new Date().toISOString()
93257
93403
  };
93258
93404
  const json3 = JSON.stringify(updated, null, 2);
93259
- _internals43.writeFileSync(tmpPath, json3, "utf-8");
93260
- _internals43.renameSync(tmpPath, finalPath);
93405
+ _internals44.writeFileSync(tmpPath, json3, "utf-8");
93406
+ _internals44.renameSync(tmpPath, finalPath);
93261
93407
  }
93262
93408
  function appendTaskHistory(map3, summary) {
93263
93409
  return {
@@ -93423,10 +93569,10 @@ function deriveFinalStatus(params) {
93423
93569
  }
93424
93570
  function readFileContent(absolutePath) {
93425
93571
  try {
93426
- if (!_internals44.existsSync(absolutePath)) {
93572
+ if (!_internals45.existsSync(absolutePath)) {
93427
93573
  return null;
93428
93574
  }
93429
- return _internals44.readFileSync(absolutePath, "utf-8");
93575
+ return _internals45.readFileSync(absolutePath, "utf-8");
93430
93576
  } catch {
93431
93577
  return null;
93432
93578
  }
@@ -93436,9 +93582,9 @@ function refreshFileEntry(relativePath, absolutePath, existingEntry) {
93436
93582
  if (content === null) {
93437
93583
  return null;
93438
93584
  }
93439
- return _internals44.extractFileSummary(relativePath, content, absolutePath, existingEntry);
93585
+ return _internals45.extractFileSummary(relativePath, content, absolutePath, existingEntry);
93440
93586
  }
93441
- var _internals44 = {
93587
+ var _internals45 = {
93442
93588
  loadContextMap,
93443
93589
  saveContextMap,
93444
93590
  createEmptyContextMap,
@@ -93457,10 +93603,10 @@ function extractEvidenceFindings(taskId, directory) {
93457
93603
  };
93458
93604
  try {
93459
93605
  const evidenceDir = path77.join(directory, ".swarm", "evidence", taskId);
93460
- if (!_internals44.existsSync(evidenceDir)) {
93606
+ if (!_internals45.existsSync(evidenceDir)) {
93461
93607
  return result;
93462
93608
  }
93463
- const evidenceFiles = _internals44.readdirSync(evidenceDir);
93609
+ const evidenceFiles = _internals45.readdirSync(evidenceDir);
93464
93610
  const targetFiles = [
93465
93611
  "evidence.json",
93466
93612
  "reviewer.json",
@@ -93552,20 +93698,20 @@ function extractEvidenceFindings(taskId, directory) {
93552
93698
  }
93553
93699
  function updateContextMapAfterAgent(params) {
93554
93700
  try {
93555
- let map3 = _internals44.loadContextMap(params.directory);
93701
+ let map3 = _internals45.loadContextMap(params.directory);
93556
93702
  if (map3 === null) {
93557
- map3 = _internals44.createEmptyContextMap();
93703
+ map3 = _internals45.createEmptyContextMap();
93558
93704
  }
93559
93705
  const root = path77.resolve(params.directory);
93560
93706
  const updatedFiles = {
93561
93707
  ...map3.files
93562
93708
  };
93563
93709
  const validFiles = [];
93564
- const realRoot = _internals44.realpathSync(root);
93710
+ const realRoot = _internals45.realpathSync(root);
93565
93711
  for (const filePath of params.files_touched) {
93566
93712
  try {
93567
93713
  const resolved = path77.resolve(root, filePath);
93568
- const realResolved = _internals44.realpathSync(resolved);
93714
+ const realResolved = _internals45.realpathSync(resolved);
93569
93715
  const relative12 = path77.relative(realRoot, realResolved);
93570
93716
  if (relative12.startsWith("..") || path77.isAbsolute(relative12)) {
93571
93717
  continue;
@@ -93603,7 +93749,7 @@ function updateContextMapAfterAgent(params) {
93603
93749
  reviewer_findings: reviewerFindings.length > 0 ? reviewerFindings : undefined,
93604
93750
  final_status: mergedRejectionReasons.length > 0 ? "rejected" : deriveFinalStatus(params)
93605
93751
  };
93606
- map3 = _internals44.appendTaskHistory(map3, taskSummary);
93752
+ map3 = _internals45.appendTaskHistory(map3, taskSummary);
93607
93753
  if (params.decisions) {
93608
93754
  for (const entry of params.decisions) {
93609
93755
  const decision = {
@@ -93613,17 +93759,17 @@ function updateContextMapAfterAgent(params) {
93613
93759
  timestamp: new Date().toISOString(),
93614
93760
  task_id: params.task_id
93615
93761
  };
93616
- map3 = _internals44.appendDecision(map3, decision);
93762
+ map3 = _internals45.appendDecision(map3, decision);
93617
93763
  }
93618
93764
  }
93619
- _internals44.saveContextMap(map3, params.directory);
93765
+ _internals45.saveContextMap(map3, params.directory);
93620
93766
  return map3;
93621
93767
  } catch {
93622
93768
  try {
93623
- const fallback = _internals44.loadContextMap(params.directory) ?? _internals44.createEmptyContextMap();
93769
+ const fallback = _internals45.loadContextMap(params.directory) ?? _internals45.createEmptyContextMap();
93624
93770
  return fallback;
93625
93771
  } catch {
93626
- return _internals44.createEmptyContextMap();
93772
+ return _internals45.createEmptyContextMap();
93627
93773
  }
93628
93774
  }
93629
93775
  }
@@ -94930,7 +95076,7 @@ import * as path79 from "node:path";
94930
95076
  function estimateTokens3(content) {
94931
95077
  return Math.max(1, estimateTokens2(content));
94932
95078
  }
94933
- var _internals45 = {
95079
+ var _internals46 = {
94934
95080
  loadContextMap,
94935
95081
  createEmptyContextMap,
94936
95082
  computeContentHash,
@@ -94998,14 +95144,14 @@ function buildReadPolicy(files, map3, directory, invalidateOnHashChange = true,
94998
95144
  const absolutePath = path79.join(directory, filePath);
94999
95145
  let currentContent;
95000
95146
  try {
95001
- if (_internals45.existsSync(absolutePath)) {
95002
- currentContent = _internals45.readFileSync(absolutePath, "utf-8");
95147
+ if (_internals46.existsSync(absolutePath)) {
95148
+ currentContent = _internals46.readFileSync(absolutePath, "utf-8");
95003
95149
  }
95004
95150
  } catch {}
95005
95151
  if (contentCache !== undefined) {
95006
95152
  contentCache.set(filePath, currentContent);
95007
95153
  }
95008
- if (currentContent === undefined || invalidateOnHashChange && _internals45.isFileStale(entry, currentContent)) {
95154
+ if (currentContent === undefined || invalidateOnHashChange && _internals46.isFileStale(entry, currentContent)) {
95009
95155
  policy.push({
95010
95156
  file_path: filePath,
95011
95157
  trust_summary: false,
@@ -95080,7 +95226,7 @@ function pruneCapsuleContent(sections, tokenEstimate, maxTokens, estimateFn) {
95080
95226
  function buildCapsule(params) {
95081
95227
  const { task_id, agent_role, delegation_reason, directory } = params;
95082
95228
  const generatedAt = new Date().toISOString();
95083
- const map3 = _internals45.loadContextMap(directory) ?? _internals45.createEmptyContextMap();
95229
+ const map3 = _internals46.loadContextMap(directory) ?? _internals46.createEmptyContextMap();
95084
95230
  let profile = DEFAULT_ROLE_PROFILES[agent_role];
95085
95231
  if (params.mode === "conservative") {
95086
95232
  profile = { ...profile, max_files: Math.ceil(profile.max_files * 1.5) };
@@ -95109,7 +95255,7 @@ function buildCapsule(params) {
95109
95255
  const shouldCheckStaleness = params.invalidate_on_hash_change !== false;
95110
95256
  if (shouldCheckStaleness) {
95111
95257
  const currentContent = contentCache.get(filePath);
95112
- if (currentContent === undefined || _internals45.isFileStale(entry, currentContent)) {
95258
+ if (currentContent === undefined || _internals46.isFileStale(entry, currentContent)) {
95113
95259
  staleEntries++;
95114
95260
  fileSummaries.push(`- ${filePath} — ${entry.purpose || "No summary available"} (stale)`);
95115
95261
  } else {
@@ -95151,11 +95297,11 @@ function buildCapsule(params) {
95151
95297
  }
95152
95298
  const content = sections.join(`
95153
95299
  `);
95154
- let tokenEstimate = _internals45.estimateTokens(content);
95300
+ let tokenEstimate = _internals46.estimateTokens(content);
95155
95301
  const maxCapsuleTokens = params.max_capsule_tokens ?? 2000;
95156
95302
  let prunedContent = content;
95157
95303
  if (tokenEstimate > maxCapsuleTokens) {
95158
- const { prunedSections, prunedTokenEstimate } = pruneCapsuleContent(sections, tokenEstimate, maxCapsuleTokens, _internals45.estimateTokens);
95304
+ const { prunedSections, prunedTokenEstimate } = pruneCapsuleContent(sections, tokenEstimate, maxCapsuleTokens, _internals46.estimateTokens);
95159
95305
  prunedContent = prunedSections.join(`
95160
95306
  `);
95161
95307
  tokenEstimate = prunedTokenEstimate;
@@ -95191,7 +95337,7 @@ function buildCapsule(params) {
95191
95337
  // src/context-map/capsule-persistence.ts
95192
95338
  import * as fs50 from "node:fs";
95193
95339
  import * as path80 from "node:path";
95194
- var _internals46 = {
95340
+ var _internals47 = {
95195
95341
  writeFileSync: fs50.writeFileSync,
95196
95342
  readFileSync: fs50.readFileSync,
95197
95343
  existsSync: fs50.existsSync,
@@ -95227,10 +95373,10 @@ function saveCapsule(capsule, directory) {
95227
95373
  const capsulesDir = path80.join(directory, ".swarm", "capsules");
95228
95374
  const finalPath = capsulePath(capsule.task_id, directory);
95229
95375
  const tmpPath = path80.join(capsulesDir, `capsule-${capsule.task_id}.tmp`);
95230
- _internals46.mkdirSync(capsulesDir, { recursive: true });
95376
+ _internals47.mkdirSync(capsulesDir, { recursive: true });
95231
95377
  const json3 = JSON.stringify(capsule, null, 2);
95232
- _internals46.writeFileSync(tmpPath, json3, "utf-8");
95233
- _internals46.renameSync(tmpPath, finalPath);
95378
+ _internals47.writeFileSync(tmpPath, json3, "utf-8");
95379
+ _internals47.renameSync(tmpPath, finalPath);
95234
95380
  return {
95235
95381
  success: true,
95236
95382
  capsule_path: finalPath,
@@ -95258,7 +95404,7 @@ function saveCapsule(capsule, directory) {
95258
95404
  // src/context-map/telemetry.ts
95259
95405
  import * as fs51 from "node:fs";
95260
95406
  import * as path81 from "node:path";
95261
- var _internals47 = {
95407
+ var _internals48 = {
95262
95408
  appendFileSync: fs51.appendFileSync,
95263
95409
  readFileSync: fs51.readFileSync,
95264
95410
  existsSync: fs51.existsSync,
@@ -95271,10 +95417,10 @@ function recordTelemetry(entry, directory) {
95271
95417
  const filePath = telemetryFilePath(directory);
95272
95418
  const swarmDir = path81.join(directory, ".swarm");
95273
95419
  try {
95274
- _internals47.mkdirSync(swarmDir, { recursive: true });
95420
+ _internals48.mkdirSync(swarmDir, { recursive: true });
95275
95421
  const line = `${JSON.stringify(entry)}
95276
95422
  `;
95277
- _internals47.appendFileSync(filePath, line, "utf-8");
95423
+ _internals48.appendFileSync(filePath, line, "utf-8");
95278
95424
  return true;
95279
95425
  } catch {
95280
95426
  return false;
@@ -95316,7 +95462,7 @@ function extractTaskGoal(taskId, directory) {
95316
95462
  return "";
95317
95463
  }
95318
95464
  }
95319
- var _internals48 = {
95465
+ var _internals49 = {
95320
95466
  buildCapsule,
95321
95467
  recordTelemetry,
95322
95468
  saveCapsule,
@@ -95384,21 +95530,21 @@ async function injectCapsule(input, output, config3, directory) {
95384
95530
  const sessionID = input.sessionID;
95385
95531
  if (!sessionID)
95386
95532
  return;
95387
- const agentName = _internals48.getActiveAgent(sessionID);
95533
+ const agentName = _internals49.getActiveAgent(sessionID);
95388
95534
  if (!agentName)
95389
95535
  return;
95390
95536
  const role = extractCapsuleRole(agentName);
95391
95537
  if (!role)
95392
95538
  return;
95393
- const taskId = _internals48.getCurrentTaskId(sessionID);
95539
+ const taskId = _internals49.getCurrentTaskId(sessionID);
95394
95540
  const effectiveTaskId = taskId ?? "unknown";
95395
- const files = _internals48.readScopeFile(effectiveTaskId, directory);
95541
+ const files = _internals49.readScopeFile(effectiveTaskId, directory);
95396
95542
  if (files.length === 0)
95397
95543
  return;
95398
95544
  const maxTokens = config3.context_map?.max_capsule_tokens;
95399
- const delegationReason = _internals48.resolveCapsuleDelegationReason(_internals48.getSession(sessionID), role, effectiveTaskId);
95400
- const taskGoal = _internals48.extractTaskGoal(effectiveTaskId, directory);
95401
- const { capsule, metadata: metadata2 } = _internals48.buildCapsule({
95545
+ const delegationReason = _internals49.resolveCapsuleDelegationReason(_internals49.getSession(sessionID), role, effectiveTaskId);
95546
+ const taskGoal = _internals49.extractTaskGoal(effectiveTaskId, directory);
95547
+ const { capsule, metadata: metadata2 } = _internals49.buildCapsule({
95402
95548
  task_id: effectiveTaskId,
95403
95549
  agent_role: role,
95404
95550
  delegation_reason: delegationReason,
@@ -95414,7 +95560,7 @@ async function injectCapsule(input, output, config3, directory) {
95414
95560
  return;
95415
95561
  output.system.push(capsule.content);
95416
95562
  try {
95417
- _internals48.saveCapsule(capsule, directory);
95563
+ _internals49.saveCapsule(capsule, directory);
95418
95564
  } catch {}
95419
95565
  const telemetryEntry = {
95420
95566
  timestamp: new Date().toISOString(),
@@ -95430,7 +95576,7 @@ async function injectCapsule(input, output, config3, directory) {
95430
95576
  success: metadata2.success
95431
95577
  };
95432
95578
  try {
95433
- _internals48.recordTelemetry(telemetryEntry, directory);
95579
+ _internals49.recordTelemetry(telemetryEntry, directory);
95434
95580
  } catch {}
95435
95581
  }
95436
95582
  // src/hooks/curator-llm-factory.ts
@@ -97140,7 +97286,7 @@ function validateGraphEdge(edge) {
97140
97286
  }
97141
97287
 
97142
97288
  // src/tools/repo-graph/builder.ts
97143
- var _internals49 = {
97289
+ var _internals50 = {
97144
97290
  safeRealpathSync,
97145
97291
  extractTSSymbols,
97146
97292
  extractPythonSymbols,
@@ -97227,12 +97373,12 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
97227
97373
  if (specifier.startsWith(".")) {
97228
97374
  const sourceDir = path88.dirname(sourceFile);
97229
97375
  let resolved = path88.resolve(sourceDir, specifier);
97230
- const initialRealResolved = _internals49.safeRealpathSync(resolved, resolved);
97376
+ const initialRealResolved = _internals50.safeRealpathSync(resolved, resolved);
97231
97377
  if (initialRealResolved === null) {
97232
97378
  return null;
97233
97379
  }
97234
97380
  let realResolved = initialRealResolved;
97235
- const realRoot = _internals49.safeRealpathSync(workspaceRoot, path88.normalize(workspaceRoot));
97381
+ const realRoot = _internals50.safeRealpathSync(workspaceRoot, path88.normalize(workspaceRoot));
97236
97382
  if (realRoot === null) {
97237
97383
  return null;
97238
97384
  }
@@ -97256,7 +97402,7 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
97256
97402
  }
97257
97403
  }
97258
97404
  if (found) {
97259
- const foundRealPath = _internals49.safeRealpathSync(found, found);
97405
+ const foundRealPath = _internals50.safeRealpathSync(found, found);
97260
97406
  if (foundRealPath === null) {
97261
97407
  return null;
97262
97408
  }
@@ -97456,14 +97602,14 @@ function scanFile(filePath, absoluteRoot, maxFileSize) {
97456
97602
  try {
97457
97603
  if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
97458
97604
  const relativePath = path88.relative(absoluteRoot, filePath);
97459
- const symbols2 = _internals49.extractTSSymbols(relativePath, absoluteRoot);
97605
+ const symbols2 = _internals50.extractTSSymbols(relativePath, absoluteRoot);
97460
97606
  exports = symbols2.filter((s) => s.exported).map((s) => s.name);
97461
97607
  } else if (ext === ".py") {
97462
97608
  const relativePath = path88.relative(absoluteRoot, filePath);
97463
- const symbols2 = _internals49.extractPythonSymbols(relativePath, absoluteRoot);
97609
+ const symbols2 = _internals50.extractPythonSymbols(relativePath, absoluteRoot);
97464
97610
  exports = symbols2.filter((s) => s.exported).map((s) => s.name);
97465
97611
  }
97466
- const parsedImports = _internals49.parseFileImports(content);
97612
+ const parsedImports = _internals50.parseFileImports(content);
97467
97613
  const node = {
97468
97614
  filePath,
97469
97615
  moduleName: toModuleName(filePath, absoluteRoot),
@@ -97593,7 +97739,7 @@ init_path_security();
97593
97739
  import { constants as constants4, existsSync as existsSync54 } from "node:fs";
97594
97740
  import * as fsPromises6 from "node:fs/promises";
97595
97741
  import * as path90 from "node:path";
97596
- var _internals50 = {
97742
+ var _internals51 = {
97597
97743
  safeRealpathSync
97598
97744
  };
97599
97745
  var WINDOWS_RENAME_MAX_RETRIES2 = 3;
@@ -97701,12 +97847,12 @@ async function saveGraph(workspace, graph, options) {
97701
97847
  throw new Error("Graph must have edges array");
97702
97848
  }
97703
97849
  const normalizedWorkspace = path90.normalize(workspace);
97704
- const realWorkspace = _internals50.safeRealpathSync(workspace, normalizedWorkspace);
97850
+ const realWorkspace = _internals51.safeRealpathSync(workspace, normalizedWorkspace);
97705
97851
  if (realWorkspace === null) {
97706
97852
  throw new Error(`Workspace realpath security check failed (non-ENOENT): ${workspace}`);
97707
97853
  }
97708
97854
  const normalizedGraphRoot = path90.normalize(graph.workspaceRoot);
97709
- const realGraphRoot = _internals50.safeRealpathSync(graph.workspaceRoot, normalizedGraphRoot);
97855
+ const realGraphRoot = _internals51.safeRealpathSync(graph.workspaceRoot, normalizedGraphRoot);
97710
97856
  if (realGraphRoot === null) {
97711
97857
  throw new Error(`Graph workspaceRoot realpath security check failed (non-ENOENT): ${graph.workspaceRoot}`);
97712
97858
  }
@@ -104181,7 +104327,7 @@ async function knowledgeApplicationGateBefore(directory, input, config3) {
104181
104327
  if (config3.mode === "enforce") {
104182
104328
  throw new Error("KNOWLEDGE_ENFORCE_GATE_DENY: missing sessionID on tool.execute.before; refusing to evaluate critical-directive ack state");
104183
104329
  }
104184
- _internals53.writeWarnEvent(directory, {
104330
+ _internals54.writeWarnEvent(directory, {
104185
104331
  timestamp: new Date().toISOString(),
104186
104332
  event: "knowledge_application_gate_warn",
104187
104333
  tool: toolName,
@@ -104264,7 +104410,7 @@ async function knowledgeApplicationTransformScan(directory, output, sessionID) {
104264
104410
  }
104265
104411
  }
104266
104412
  }
104267
- var _internals53 = {
104413
+ var _internals54 = {
104268
104414
  knowledgeApplicationGateBefore,
104269
104415
  knowledgeApplicationTransformScan,
104270
104416
  HIGH_RISK_TOOLS,
@@ -104400,10 +104546,10 @@ async function getRunMemorySummary(directory) {
104400
104546
  if (entries.length === 0) {
104401
104547
  return null;
104402
104548
  }
104403
- const groups = _internals54.groupByTaskId(entries);
104549
+ const groups = _internals55.groupByTaskId(entries);
104404
104550
  const summaries = [];
104405
104551
  for (const [taskId, taskEntries] of groups) {
104406
- const summary = _internals54.summarizeTask(taskId, taskEntries);
104552
+ const summary = _internals55.summarizeTask(taskId, taskEntries);
104407
104553
  if (summary) {
104408
104554
  summaries.push(summary);
104409
104555
  }
@@ -104436,7 +104582,7 @@ Use this data to avoid repeating known failure patterns.`;
104436
104582
  }
104437
104583
  return prefix + summaryText + suffix;
104438
104584
  }
104439
- var _internals54 = {
104585
+ var _internals55 = {
104440
104586
  generateTaskFingerprint,
104441
104587
  recordOutcome,
104442
104588
  getTaskHistory,
@@ -104629,7 +104775,7 @@ function createKnowledgeInjectorHook(directory, config3) {
104629
104775
  projectName,
104630
104776
  currentPhase: phaseDescription
104631
104777
  };
104632
- const searchFn = _internals56.searchKnowledge === defaultSearchKnowledge ? searchKnowledge : _internals56.searchKnowledge;
104778
+ const searchFn = _internals57.searchKnowledge === defaultSearchKnowledge ? searchKnowledge : _internals57.searchKnowledge;
104633
104779
  const search = await searchFn({
104634
104780
  directory,
104635
104781
  config: config3,
@@ -104738,7 +104884,7 @@ ${freshPreamble}` : `<curator_briefing>${truncatedBriefing}</curator_briefing>`;
104738
104884
  ranks[id] = idx + 1;
104739
104885
  scores[id] = scoreById.get(id) ?? 0;
104740
104886
  });
104741
- await _internals56.recordKnowledgeEvent(directory, {
104887
+ await _internals57.recordKnowledgeEvent(directory, {
104742
104888
  type: "retrieved",
104743
104889
  trace_id: search.trace_id,
104744
104890
  session_id: systemMsg?.info?.sessionID ?? "unknown",
@@ -104751,7 +104897,7 @@ ${freshPreamble}` : `<curator_briefing>${truncatedBriefing}</curator_briefing>`;
104751
104897
  ranks,
104752
104898
  scores
104753
104899
  });
104754
- _internals56.recordKnowledgeShown(directory, cachedShownIds, {
104900
+ _internals57.recordKnowledgeShown(directory, cachedShownIds, {
104755
104901
  phase: phaseLabel,
104756
104902
  tool: retrievalCtx.currentTool,
104757
104903
  action: retrievalCtx.currentAction,
@@ -104761,7 +104907,7 @@ ${freshPreamble}` : `<curator_briefing>${truncatedBriefing}</curator_briefing>`;
104761
104907
  }
104762
104908
  });
104763
104909
  }
104764
- var _internals56 = {
104910
+ var _internals57 = {
104765
104911
  searchKnowledge,
104766
104912
  recordKnowledgeEvent,
104767
104913
  recordKnowledgeShown
@@ -104946,7 +105092,7 @@ var TASK_DIVERSITY_WEIGHT = 0.05;
104946
105092
  var CONTEXT_WEIGHT = 0.2;
104947
105093
  var RECENCY_DECAY_MS = 30 * 24 * 60 * 60 * 1000;
104948
105094
  var SKILL_FRONTMATTER_READ_BYTES = 16 * 1024;
104949
- var _internals57 = {
105095
+ var _internals58 = {
104950
105096
  computeSkillRelevanceScore: null,
104951
105097
  rankSkillsForContext: null,
104952
105098
  getSkillStats: null,
@@ -105165,7 +105311,7 @@ function formatSkillIndexWithContext(skills, directory) {
105165
105311
  } catch {}
105166
105312
  if (!hasHistory) {
105167
105313
  return skills.map((sp) => {
105168
- const meta3 = _internals57.readSkillMetadata(sp, directory);
105314
+ const meta3 = _internals58.readSkillMetadata(sp, directory);
105169
105315
  return ` - file:${meta3.path} - ${meta3.name}: ${meta3.description}`;
105170
105316
  }).join(`
105171
105317
  `);
@@ -105173,7 +105319,7 @@ function formatSkillIndexWithContext(skills, directory) {
105173
105319
  const lines = [];
105174
105320
  for (const skillPath of skills) {
105175
105321
  const stats = getSkillStats(skillPath, directory);
105176
- const meta3 = _internals57.readSkillMetadata(skillPath, directory);
105322
+ const meta3 = _internals58.readSkillMetadata(skillPath, directory);
105177
105323
  const compliancePct = Math.round(stats.complianceRate * 100);
105178
105324
  const topAgentNames = stats.topAgents.slice(0, 3).map((a) => a.agent).join(", ");
105179
105325
  lines.push(` - file:${meta3.path} - ${meta3.name}: ${meta3.description} (used: ${stats.totalUsage}, compliance: ${compliancePct}%)` + (stats.topAgents.length > 0 ? ` → ${topAgentNames}` : ""));
@@ -105181,15 +105327,15 @@ function formatSkillIndexWithContext(skills, directory) {
105181
105327
  return lines.join(`
105182
105328
  `);
105183
105329
  }
105184
- _internals57.computeSkillRelevanceScore = computeSkillRelevanceScore;
105185
- _internals57.rankSkillsForContext = rankSkillsForContext;
105186
- _internals57.getSkillStats = getSkillStats;
105187
- _internals57.formatSkillIndexWithContext = formatSkillIndexWithContext;
105188
- _internals57.parseSkillFrontmatter = parseSkillFrontmatter;
105189
- _internals57.readSkillMetadata = readSkillMetadata;
105190
- _internals57.extractSkillName = extractSkillName;
105191
- _internals57.computeRecencyScore = computeRecencyScore;
105192
- _internals57.computeContextMatchScore = computeContextMatchScore;
105330
+ _internals58.computeSkillRelevanceScore = computeSkillRelevanceScore;
105331
+ _internals58.rankSkillsForContext = rankSkillsForContext;
105332
+ _internals58.getSkillStats = getSkillStats;
105333
+ _internals58.formatSkillIndexWithContext = formatSkillIndexWithContext;
105334
+ _internals58.parseSkillFrontmatter = parseSkillFrontmatter;
105335
+ _internals58.readSkillMetadata = readSkillMetadata;
105336
+ _internals58.extractSkillName = extractSkillName;
105337
+ _internals58.computeRecencyScore = computeRecencyScore;
105338
+ _internals58.computeContextMatchScore = computeContextMatchScore;
105193
105339
 
105194
105340
  // src/hooks/skill-propagation-gate.ts
105195
105341
  init_skill_usage_log();
@@ -105292,10 +105438,10 @@ function parseYamlValue(value) {
105292
105438
  }
105293
105439
  function loadRoutingSkills(directory, targetAgent) {
105294
105440
  const routingPath = path111.join(directory, ".opencode", "skill-routing.yaml");
105295
- if (!_internals58.existsSync(routingPath))
105441
+ if (!_internals59.existsSync(routingPath))
105296
105442
  return [];
105297
105443
  try {
105298
- const content = _internals58.readFileSync(routingPath, "utf-8");
105444
+ const content = _internals59.readFileSync(routingPath, "utf-8");
105299
105445
  const config3 = parseSimpleYaml(content);
105300
105446
  if (!config3?.routing)
105301
105447
  return [];
@@ -105322,7 +105468,7 @@ var SKILL_SEARCH_ROOTS = [
105322
105468
  ".claude/skills"
105323
105469
  ];
105324
105470
  var MAX_SCORING_SESSION_ENTRIES = 500;
105325
- var _internals58 = {
105471
+ var _internals59 = {
105326
105472
  readdirSync: fs73.readdirSync.bind(fs73),
105327
105473
  existsSync: fs73.existsSync.bind(fs73),
105328
105474
  statSync: fs73.statSync.bind(fs73),
@@ -105351,11 +105497,11 @@ function discoverAvailableSkills(directory) {
105351
105497
  const results = [];
105352
105498
  for (const root of SKILL_SEARCH_ROOTS) {
105353
105499
  const rootPath = path111.join(directory, root);
105354
- if (!_internals58.existsSync(rootPath))
105500
+ if (!_internals59.existsSync(rootPath))
105355
105501
  continue;
105356
105502
  let entries;
105357
105503
  try {
105358
- entries = _internals58.readdirSync(rootPath);
105504
+ entries = _internals59.readdirSync(rootPath);
105359
105505
  } catch {
105360
105506
  continue;
105361
105507
  }
@@ -105363,11 +105509,11 @@ function discoverAvailableSkills(directory) {
105363
105509
  if (entry.startsWith("."))
105364
105510
  continue;
105365
105511
  const skillDir = path111.join(rootPath, entry);
105366
- if (_internals58.existsSync(path111.join(skillDir, "retired.marker")))
105512
+ if (_internals59.existsSync(path111.join(skillDir, "retired.marker")))
105367
105513
  continue;
105368
105514
  const skillFile = path111.join(skillDir, "SKILL.md");
105369
105515
  try {
105370
- if (_internals58.statSync(skillDir).isDirectory() && _internals58.existsSync(skillFile)) {
105516
+ if (_internals59.statSync(skillDir).isDirectory() && _internals59.existsSync(skillFile)) {
105371
105517
  results.push(path111.join(root, entry, "SKILL.md").replace(/\\/g, "/"));
105372
105518
  }
105373
105519
  } catch (err2) {
@@ -105399,7 +105545,7 @@ function parseDelegationArgs(args2) {
105399
105545
  }
105400
105546
  if (!targetAgent)
105401
105547
  return null;
105402
- const skillsField = prompt ? _internals58.extractSkillsFieldFromPrompt(prompt) : "";
105548
+ const skillsField = prompt ? _internals59.extractSkillsFieldFromPrompt(prompt) : "";
105403
105549
  return { targetAgent, skillsField };
105404
105550
  }
105405
105551
  function extractSkillsFieldFromPrompt(prompt) {
@@ -105440,10 +105586,10 @@ function writeWarnEvent2(directory, record3) {
105440
105586
  const filePath = path111.join(directory, ".swarm", "events.jsonl");
105441
105587
  try {
105442
105588
  const dir = path111.dirname(filePath);
105443
- if (!_internals58.existsSync(dir)) {
105444
- _internals58.mkdirSync(dir, { recursive: true });
105589
+ if (!_internals59.existsSync(dir)) {
105590
+ _internals59.mkdirSync(dir, { recursive: true });
105445
105591
  }
105446
- _internals58.appendFileSync(filePath, `${JSON.stringify(record3)}
105592
+ _internals59.appendFileSync(filePath, `${JSON.stringify(record3)}
105447
105593
  `, "utf-8");
105448
105594
  } catch (err2) {
105449
105595
  warn(`[skill-propagation-gate] failed to write warning event: ${err2 instanceof Error ? err2.message : String(err2)}`);
@@ -105494,19 +105640,19 @@ async function skillPropagationGateBefore(directory, input, config3) {
105494
105640
  const baseAgent = stripKnownSwarmPrefix(agentRaw);
105495
105641
  if (baseAgent !== "architect")
105496
105642
  return { blocked: false, reason: null, recommendedSkills: undefined };
105497
- const parsed = _internals58.parseDelegationArgs(input.args);
105643
+ const parsed = _internals59.parseDelegationArgs(input.args);
105498
105644
  if (!parsed)
105499
105645
  return { blocked: false, reason: null, recommendedSkills: undefined };
105500
105646
  const targetBase = stripKnownSwarmPrefix(parsed.targetAgent);
105501
- if (!_internals58.SKILL_CAPABLE_AGENTS.has(targetBase))
105647
+ if (!_internals59.SKILL_CAPABLE_AGENTS.has(targetBase))
105502
105648
  return { blocked: false, reason: null, recommendedSkills: undefined };
105503
105649
  const sessionID = typeof input.sessionID === "string" ? input.sessionID : "unknown";
105504
- const availableSkills = _internals58.discoverAvailableSkills(directory);
105650
+ const availableSkills = _internals59.discoverAvailableSkills(directory);
105505
105651
  const skillsValue = parsed.skillsField.trim();
105506
105652
  if (skillsValue && skillsValue.toLowerCase() !== "none") {
105507
105653
  const prompt = typeof input.args?.prompt === "string" ? String(input.args.prompt) : "";
105508
- const taskId = _internals58.extractTaskIdFromPrompt(prompt);
105509
- const skillPaths = _internals58.parseSkillPaths(skillsValue);
105654
+ const taskId = _internals59.extractTaskIdFromPrompt(prompt);
105655
+ const skillPaths = _internals59.parseSkillPaths(skillsValue);
105510
105656
  let coderSkillPaths = [];
105511
105657
  if (prompt) {
105512
105658
  for (const line of prompt.split(`
@@ -105514,7 +105660,7 @@ async function skillPropagationGateBefore(directory, input, config3) {
105514
105660
  const trimmed = line.trim();
105515
105661
  if (trimmed.startsWith("SKILLS_USED_BY_CODER:")) {
105516
105662
  const fieldVal = trimmed.slice("SKILLS_USED_BY_CODER:".length).trim();
105517
- coderSkillPaths = _internals58.parseSkillPaths(fieldVal);
105663
+ coderSkillPaths = _internals59.parseSkillPaths(fieldVal);
105518
105664
  break;
105519
105665
  }
105520
105666
  }
@@ -105522,7 +105668,7 @@ async function skillPropagationGateBefore(directory, input, config3) {
105522
105668
  const allPaths = [...new Set([...skillPaths, ...coderSkillPaths])];
105523
105669
  for (const skillPath of allPaths) {
105524
105670
  try {
105525
- _internals58.appendSkillUsageEntry(directory, {
105671
+ _internals59.appendSkillUsageEntry(directory, {
105526
105672
  skillPath,
105527
105673
  agentName: targetBase,
105528
105674
  taskID: taskId,
@@ -105539,17 +105685,17 @@ async function skillPropagationGateBefore(directory, input, config3) {
105539
105685
  let scored = [];
105540
105686
  if (skillsValue && skillsValue.toLowerCase() !== "none" && availableSkills.length > 0) {
105541
105687
  try {
105542
- const sessionEntries = _internals58.readSkillUsageEntriesTail(directory, {
105688
+ const sessionEntries = _internals59.readSkillUsageEntriesTail(directory, {
105543
105689
  sessionID
105544
105690
  });
105545
- if (sessionEntries.length > _internals58.MAX_SCORING_SESSION_ENTRIES) {
105691
+ if (sessionEntries.length > _internals59.MAX_SCORING_SESSION_ENTRIES) {
105546
105692
  scoringSkipped = true;
105547
- warn(`[skill-propagation-gate] skipping scoring — tail window has ${sessionEntries.length} session entries (limit: ${_internals58.MAX_SCORING_SESSION_ENTRIES})`);
105693
+ warn(`[skill-propagation-gate] skipping scoring — tail window has ${sessionEntries.length} session entries (limit: ${_internals59.MAX_SCORING_SESSION_ENTRIES})`);
105548
105694
  } else {
105549
105695
  const prompt = typeof input.args?.prompt === "string" ? String(input.args.prompt) : "";
105550
105696
  scored = availableSkills.map((skillPath) => {
105551
105697
  const skillEntries = sessionEntries.filter((e) => e.skillPath === skillPath);
105552
- const score = _internals58.computeSkillRelevanceScore(skillPath, prompt, skillEntries);
105698
+ const score = _internals59.computeSkillRelevanceScore(skillPath, prompt, skillEntries);
105553
105699
  return { skillPath, score, usageCount: skillEntries.length };
105554
105700
  }).sort((a, b) => b.score - a.score || b.usageCount - a.usageCount);
105555
105701
  if (scored.length > 0) {
@@ -105563,12 +105709,12 @@ async function skillPropagationGateBefore(directory, input, config3) {
105563
105709
  }
105564
105710
  }
105565
105711
  try {
105566
- const routingPaths = _internals58.loadRoutingSkills(directory, targetBase);
105712
+ const routingPaths = _internals59.loadRoutingSkills(directory, targetBase);
105567
105713
  if (routingPaths.length > 0) {
105568
105714
  const existingPaths = new Set(scored.map((s) => s.skillPath));
105569
105715
  for (const routingPath of routingPaths) {
105570
105716
  const routedSkillDir = path111.dirname(path111.join(directory, routingPath));
105571
- if (_internals58.existsSync(path111.join(routedSkillDir, "retired.marker")))
105717
+ if (_internals59.existsSync(path111.join(routedSkillDir, "retired.marker")))
105572
105718
  continue;
105573
105719
  if (!existingPaths.has(routingPath)) {
105574
105720
  scored.push({
@@ -105594,12 +105740,12 @@ async function skillPropagationGateBefore(directory, input, config3) {
105594
105740
  } else if (typeof scored !== "undefined" && scored.length > 0) {
105595
105741
  skillsForIndex = scored.map((r) => r.skillPath);
105596
105742
  }
105597
- const formattedIndex = _internals58.formatSkillIndexWithContext(skillsForIndex, directory);
105743
+ const formattedIndex = _internals59.formatSkillIndexWithContext(skillsForIndex, directory);
105598
105744
  if (formattedIndex.length > 0) {
105599
105745
  const contextPath = path111.join(directory, ".swarm", "context.md");
105600
105746
  let existingContent = "";
105601
- if (_internals58.existsSync(contextPath)) {
105602
- existingContent = _internals58.readFileSync(contextPath, "utf-8");
105747
+ if (_internals59.existsSync(contextPath)) {
105748
+ existingContent = _internals59.readFileSync(contextPath, "utf-8");
105603
105749
  }
105604
105750
  const sectionHeader = "## Available Skills";
105605
105751
  const newSection = `${sectionHeader}
@@ -105619,10 +105765,10 @@ ${newSection}`;
105619
105765
  }
105620
105766
  }
105621
105767
  const swarmDir = path111.dirname(contextPath);
105622
- if (!_internals58.existsSync(swarmDir)) {
105623
- _internals58.mkdirSync(swarmDir, { recursive: true });
105768
+ if (!_internals59.existsSync(swarmDir)) {
105769
+ _internals59.mkdirSync(swarmDir, { recursive: true });
105624
105770
  }
105625
- _internals58.writeFileSync(contextPath, updatedContent, "utf-8");
105771
+ _internals59.writeFileSync(contextPath, updatedContent, "utf-8");
105626
105772
  }
105627
105773
  } catch (err2) {
105628
105774
  warn(`[skill-propagation-gate] failed to write skill index to context.md: ${err2 instanceof Error ? err2.message : String(err2)}`);
@@ -105648,7 +105794,7 @@ ${newSection}`;
105648
105794
  });
105649
105795
  const warningMsg = `Skill propagation warning: Delegating to ${targetBase} without SKILLS field. ` + `Available skills: ${skillNames.join(", ")}`;
105650
105796
  try {
105651
- _internals58.writeWarnEvent(directory, {
105797
+ _internals59.writeWarnEvent(directory, {
105652
105798
  type: "skill_propagation_warn",
105653
105799
  timestamp: new Date().toISOString(),
105654
105800
  tool: toolName,
@@ -105677,7 +105823,7 @@ async function skillPropagationTransformScan(directory, output, sessionID) {
105677
105823
  let dedupKeys = new Set;
105678
105824
  let existingEntries = [];
105679
105825
  try {
105680
- existingEntries = _internals58.readSkillUsageEntriesTail(directory, {
105826
+ existingEntries = _internals59.readSkillUsageEntriesTail(directory, {
105681
105827
  sessionID
105682
105828
  });
105683
105829
  dedupKeys = new Set(existingEntries.map((e, i2) => {
@@ -105709,7 +105855,7 @@ async function skillPropagationTransformScan(directory, output, sessionID) {
105709
105855
  `)) {
105710
105856
  const coderMatch = line.trim().match(CODER_SKILLS_PATTERN);
105711
105857
  if (coderMatch) {
105712
- const parsed = _internals58.parseSkillPaths(coderMatch[1]);
105858
+ const parsed = _internals59.parseSkillPaths(coderMatch[1]);
105713
105859
  skillPaths.push(...parsed);
105714
105860
  }
105715
105861
  }
@@ -105740,7 +105886,7 @@ async function skillPropagationTransformScan(directory, output, sessionID) {
105740
105886
  if (isDuplicate(skillPath, "reviewer", resolvedTaskID))
105741
105887
  continue;
105742
105888
  try {
105743
- _internals58.appendSkillUsageEntry(directory, {
105889
+ _internals59.appendSkillUsageEntry(directory, {
105744
105890
  skillPath,
105745
105891
  agentName: "reviewer",
105746
105892
  taskID: resolvedTaskID,
@@ -105784,15 +105930,15 @@ async function skillPropagationTransformScan(directory, output, sessionID) {
105784
105930
  skillsField = trimmed.slice("SKILLS:".length).trim();
105785
105931
  }
105786
105932
  if (currentTargetAgent && skillsField && skillsField.toLowerCase() !== "none") {
105787
- const skillPaths = _internals58.parseSkillPaths(skillsField);
105788
- const taskId = _internals58.extractTaskIdFromPrompt(text);
105933
+ const skillPaths = _internals59.parseSkillPaths(skillsField);
105934
+ const taskId = _internals59.extractTaskIdFromPrompt(text);
105789
105935
  for (const skillPath of skillPaths) {
105790
105936
  if (hadRecordingError)
105791
105937
  break;
105792
105938
  if (isDuplicate(skillPath, currentTargetAgent, taskId))
105793
105939
  continue;
105794
105940
  try {
105795
- _internals58.appendSkillUsageEntry(directory, {
105941
+ _internals59.appendSkillUsageEntry(directory, {
105796
105942
  skillPath,
105797
105943
  agentName: currentTargetAgent,
105798
105944
  taskID: taskId,
@@ -105812,16 +105958,16 @@ async function skillPropagationTransformScan(directory, output, sessionID) {
105812
105958
  break;
105813
105959
  }
105814
105960
  }
105815
- _internals58.skillPropagationGateBefore = skillPropagationGateBefore;
105816
- _internals58.skillPropagationTransformScan = skillPropagationTransformScan;
105817
- _internals58.writeWarnEvent = writeWarnEvent2;
105818
- _internals58.discoverAvailableSkills = discoverAvailableSkills;
105819
- _internals58.parseDelegationArgs = parseDelegationArgs;
105820
- _internals58.parseSkillPaths = parseSkillPaths;
105821
- _internals58.extractTaskIdFromPrompt = extractTaskIdFromPrompt;
105822
- _internals58.extractSkillsFieldFromPrompt = extractSkillsFieldFromPrompt;
105823
- _internals58.formatSkillIndexWithContext = formatSkillIndexWithContext;
105824
- _internals58.loadRoutingSkills = loadRoutingSkills;
105961
+ _internals59.skillPropagationGateBefore = skillPropagationGateBefore;
105962
+ _internals59.skillPropagationTransformScan = skillPropagationTransformScan;
105963
+ _internals59.writeWarnEvent = writeWarnEvent2;
105964
+ _internals59.discoverAvailableSkills = discoverAvailableSkills;
105965
+ _internals59.parseDelegationArgs = parseDelegationArgs;
105966
+ _internals59.parseSkillPaths = parseSkillPaths;
105967
+ _internals59.extractTaskIdFromPrompt = extractTaskIdFromPrompt;
105968
+ _internals59.extractSkillsFieldFromPrompt = extractSkillsFieldFromPrompt;
105969
+ _internals59.formatSkillIndexWithContext = formatSkillIndexWithContext;
105970
+ _internals59.loadRoutingSkills = loadRoutingSkills;
105825
105971
 
105826
105972
  // src/index.ts
105827
105973
  init_skill_usage_log();
@@ -109936,7 +110082,7 @@ var VALID_TASK_ID = /^\d+\.\d+(\.\d+)*$/;
109936
110082
  var COUNCIL_GATE_NAME = "council";
109937
110083
  var COUNCIL_AGENT_ID = "architect";
109938
110084
  var EvidenceFileSchema = exports_external.record(exports_external.string(), exports_external.unknown());
109939
- var _internals59 = {
110085
+ var _internals60 = {
109940
110086
  withTaskEvidenceLock
109941
110087
  };
109942
110088
  var FORBIDDEN_KEYS = new Set(["__proto__", "constructor", "prototype"]);
@@ -109971,7 +110117,7 @@ async function writeCouncilEvidence(workingDir, synthesis) {
109971
110117
  const dir = join102(workingDir, EVIDENCE_DIR2);
109972
110118
  mkdirSync32(dir, { recursive: true });
109973
110119
  const filePath = taskEvidencePath(workingDir, synthesis.taskId);
109974
- await _internals59.withTaskEvidenceLock(workingDir, synthesis.taskId, COUNCIL_AGENT_ID, async () => {
110120
+ await _internals60.withTaskEvidenceLock(workingDir, synthesis.taskId, COUNCIL_AGENT_ID, async () => {
109975
110121
  const existingRoot = Object.create(null);
109976
110122
  if (existsSync69(filePath)) {
109977
110123
  try {
@@ -110892,7 +111038,7 @@ var ArgsSchema2 = exports_external.object({
110892
111038
  working_directory: exports_external.string().optional()
110893
111039
  });
110894
111040
  var convene_general_council = createSwarmTool({
110895
- description: "Synthesize responses from a multi-model General Council. Accepts parallel member " + "responses (Round 1, optionally Round 2), detects disagreements, and returns " + "consensus points, persisting disagreements, and a structured synthesis. " + "Architect-only. Config-gated on council.general.enabled.",
111041
+ description: "Synthesize responses from a multi-model General Council. Accepts parallel member " + "responses (Round 1, optionally Round 2), detects disagreements, and returns " + "consensus points, persisting disagreements, and a structured synthesis. " + "Architect-only. Config-gated on council.general.enabled in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides.",
110896
111042
  args: {
110897
111043
  question: exports_external.string().min(1).max(8000).describe("The question put to the council, or the spec text to review."),
110898
111044
  mode: exports_external.enum(["general", "spec_review"]).optional().describe('"general" for /swarm council; "spec_review" for SPECIFY-COUNCIL-REVIEW gate.'),
@@ -110971,7 +111117,7 @@ var convene_general_council = createSwarmTool({
110971
111117
  const fail = {
110972
111118
  success: false,
110973
111119
  reason: "council_general_disabled",
110974
- message: "convene_general_council requires council.general.enabled: true in opencode-swarm.json."
111120
+ message: "convene_general_council requires council.general.enabled: true in the resolved config: global ~/.config/opencode/opencode-swarm.json or project .opencode/opencode-swarm.json."
110975
111121
  };
110976
111122
  return JSON.stringify(fail, null, 2);
110977
111123
  }
@@ -115092,7 +115238,7 @@ function resolveDefaultReviewerAgent(generatedAgentNames) {
115092
115238
  }
115093
115239
  async function compileReviewPackage(directory, phase, sessionID, requireDiffSummary) {
115094
115240
  const lanes = await listLaneEvidence(directory, phase);
115095
- const persisted = _internals60.readPersisted?.(directory) ?? null;
115241
+ const persisted = _internals61.readPersisted?.(directory) ?? null;
115096
115242
  if (persisted) {
115097
115243
  let matchingRunState = null;
115098
115244
  for (const sessionState of Object.values(persisted.sessions)) {
@@ -115284,7 +115430,7 @@ Be specific and evidence-based. Do not approve a phase with unresolved degraded
115284
115430
  client.session.delete({ path: { id: sessionId } }).catch(() => {});
115285
115431
  }
115286
115432
  }
115287
- var _internals60 = {
115433
+ var _internals61 = {
115288
115434
  compileReviewPackage,
115289
115435
  parseReviewerVerdict,
115290
115436
  writeReviewerEvidence,
@@ -115301,28 +115447,28 @@ async function dispatchPhaseReviewer(directory, phase, sessionID, config3) {
115301
115447
  };
115302
115448
  const generatedAgentNames = swarmState.generatedAgentNames;
115303
115449
  const agentName = mergedConfig.reviewerAgent || resolveDefaultReviewerAgent(generatedAgentNames);
115304
- const pkg = await _internals60.compileReviewPackage(directory, phase, sessionID, mergedConfig.requireDiffSummary);
115450
+ const pkg = await _internals61.compileReviewPackage(directory, phase, sessionID, mergedConfig.requireDiffSummary);
115305
115451
  let responseText;
115306
115452
  try {
115307
- responseText = await _internals60.dispatchReviewerAgent(directory, pkg, agentName, mergedConfig.timeoutMs);
115453
+ responseText = await _internals61.dispatchReviewerAgent(directory, pkg, agentName, mergedConfig.timeoutMs);
115308
115454
  } catch (error93) {
115309
- const evidencePath2 = await _internals60.writeReviewerEvidence(directory, phase, "REJECTED", error93 instanceof Error ? error93.message : String(error93));
115455
+ const evidencePath2 = await _internals61.writeReviewerEvidence(directory, phase, "REJECTED", error93 instanceof Error ? error93.message : String(error93));
115310
115456
  return {
115311
115457
  verdict: "REJECTED",
115312
115458
  reason: `Reviewer dispatch failed: ${error93 instanceof Error ? error93.message : String(error93)}`,
115313
115459
  evidencePath: evidencePath2
115314
115460
  };
115315
115461
  }
115316
- const parsed = _internals60.parseReviewerVerdict(responseText);
115462
+ const parsed = _internals61.parseReviewerVerdict(responseText);
115317
115463
  if (!parsed) {
115318
- const evidencePath2 = await _internals60.writeReviewerEvidence(directory, phase, "REJECTED", "Reviewer response could not be parsed");
115464
+ const evidencePath2 = await _internals61.writeReviewerEvidence(directory, phase, "REJECTED", "Reviewer response could not be parsed");
115319
115465
  return {
115320
115466
  verdict: "REJECTED",
115321
115467
  reason: "Reviewer response could not be parsed",
115322
115468
  evidencePath: evidencePath2
115323
115469
  };
115324
115470
  }
115325
- const evidencePath = await _internals60.writeReviewerEvidence(directory, phase, parsed.verdict, parsed.reason);
115471
+ const evidencePath = await _internals61.writeReviewerEvidence(directory, phase, parsed.verdict, parsed.reason);
115326
115472
  return {
115327
115473
  verdict: parsed.verdict,
115328
115474
  reason: parsed.reason,
@@ -115829,7 +115975,7 @@ ${fileList}
115829
115975
 
115830
115976
  // src/tools/lean-turbo-run-phase.ts
115831
115977
  init_create_tool();
115832
- var _internals61 = {
115978
+ var _internals62 = {
115833
115979
  LeanTurboRunner,
115834
115980
  loadPluginConfigWithMeta
115835
115981
  };
@@ -115839,9 +115985,9 @@ async function executeLeanTurboRunPhase(args2) {
115839
115985
  let runError = null;
115840
115986
  let runner = null;
115841
115987
  try {
115842
- const { config: config3 } = _internals61.loadPluginConfigWithMeta(directory);
115988
+ const { config: config3 } = _internals62.loadPluginConfigWithMeta(directory);
115843
115989
  const leanConfig = config3.turbo?.strategy === "lean" ? config3.turbo.lean : undefined;
115844
- runner = new _internals61.LeanTurboRunner({
115990
+ runner = new _internals62.LeanTurboRunner({
115845
115991
  directory,
115846
115992
  sessionID,
115847
115993
  opencodeClient: swarmState.opencodeClient ?? null,
@@ -116202,7 +116348,7 @@ function isStaticallyEquivalent(originalCode, mutatedCode) {
116202
116348
  const strippedMutated = stripCode(mutatedCode);
116203
116349
  return strippedOriginal === strippedMutated;
116204
116350
  }
116205
- var _internals62 = {
116351
+ var _internals63 = {
116206
116352
  isStaticallyEquivalent,
116207
116353
  checkEquivalence,
116208
116354
  batchCheckEquivalence
@@ -116242,7 +116388,7 @@ async function batchCheckEquivalence(patches, llmJudge) {
116242
116388
  const results = [];
116243
116389
  for (const { patch, originalCode, mutatedCode } of patches) {
116244
116390
  try {
116245
- const result = await _internals62.checkEquivalence(patch, originalCode, mutatedCode, llmJudge);
116391
+ const result = await _internals63.checkEquivalence(patch, originalCode, mutatedCode, llmJudge);
116246
116392
  results.push(result);
116247
116393
  } catch (err2) {
116248
116394
  results.push({
@@ -116261,7 +116407,7 @@ async function batchCheckEquivalence(patches, llmJudge) {
116261
116407
  var MUTATION_TIMEOUT_MS = 30000;
116262
116408
  var TOTAL_BUDGET_MS = 300000;
116263
116409
  var GIT_APPLY_TIMEOUT_MS = 5000;
116264
- var _internals63 = {
116410
+ var _internals64 = {
116265
116411
  executeMutation,
116266
116412
  computeReport,
116267
116413
  executeMutationSuite,
@@ -116293,7 +116439,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
116293
116439
  };
116294
116440
  }
116295
116441
  try {
116296
- const applyResult = _internals63.spawnSync("git", ["apply", "--", patchFile], {
116442
+ const applyResult = _internals64.spawnSync("git", ["apply", "--", patchFile], {
116297
116443
  cwd: workingDir,
116298
116444
  timeout: GIT_APPLY_TIMEOUT_MS,
116299
116445
  stdio: "pipe"
@@ -116322,7 +116468,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
116322
116468
  }
116323
116469
  let testPassed = false;
116324
116470
  try {
116325
- const spawnResult = _internals63.spawnSync(testCommand[0], testCommand.slice(1), {
116471
+ const spawnResult = _internals64.spawnSync(testCommand[0], testCommand.slice(1), {
116326
116472
  cwd: workingDir,
116327
116473
  timeout: MUTATION_TIMEOUT_MS,
116328
116474
  stdio: "pipe"
@@ -116355,7 +116501,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
116355
116501
  } finally {
116356
116502
  if (patchFile) {
116357
116503
  try {
116358
- const revertResult = _internals63.spawnSync("git", ["apply", "-R", "--", patchFile], {
116504
+ const revertResult = _internals64.spawnSync("git", ["apply", "-R", "--", patchFile], {
116359
116505
  cwd: workingDir,
116360
116506
  timeout: GIT_APPLY_TIMEOUT_MS,
116361
116507
  stdio: "pipe"
@@ -116548,7 +116694,7 @@ async function executeMutationSuite(patches, testCommand, testFiles, workingDir,
116548
116694
  }
116549
116695
 
116550
116696
  // src/mutation/gate.ts
116551
- var _internals64 = {
116697
+ var _internals65 = {
116552
116698
  evaluateMutationGate,
116553
116699
  buildTestImprovementPrompt,
116554
116700
  buildMessage
@@ -116569,8 +116715,8 @@ function evaluateMutationGate(report, passThreshold = PASS_THRESHOLD, warnThresh
116569
116715
  } else {
116570
116716
  verdict = "fail";
116571
116717
  }
116572
- const testImprovementPrompt = _internals64.buildTestImprovementPrompt(report, passThreshold, verdict);
116573
- const message = _internals64.buildMessage(verdict, adjustedKillRate, report.killed, report.totalMutants, report.equivalent, warnThreshold);
116718
+ const testImprovementPrompt = _internals65.buildTestImprovementPrompt(report, passThreshold, verdict);
116719
+ const message = _internals65.buildMessage(verdict, adjustedKillRate, report.killed, report.totalMutants, report.equivalent, warnThreshold);
116574
116720
  return {
116575
116721
  verdict,
116576
116722
  killRate: report.killRate,
@@ -116965,7 +117111,7 @@ function listLaneEvidenceSync(directory, phase) {
116965
117111
  }
116966
117112
  return laneIds;
116967
117113
  }
116968
- var _internals65 = {
117114
+ var _internals66 = {
116969
117115
  listActiveLocks,
116970
117116
  readPersisted: readPersisted2,
116971
117117
  readPlanJson: defaultReadPlanJson,
@@ -117026,7 +117172,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
117026
117172
  reason: "Lean Turbo state unreadable or missing"
117027
117173
  };
117028
117174
  }
117029
- const persisted = _internals65.readPersisted(directory);
117175
+ const persisted = _internals66.readPersisted(directory);
117030
117176
  if (!persisted) {
117031
117177
  return {
117032
117178
  ok: false,
@@ -117090,7 +117236,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
117090
117236
  }
117091
117237
  }
117092
117238
  if (runState.lanes.length > 0) {
117093
- const evidenceLaneIds = new Set(_internals65.listLaneEvidenceSync(directory, phase));
117239
+ const evidenceLaneIds = new Set(_internals66.listLaneEvidenceSync(directory, phase));
117094
117240
  for (const lane of runState.lanes) {
117095
117241
  if ((lane.status === "completed" || lane.status === "failed") && !evidenceLaneIds.has(lane.laneId)) {
117096
117242
  return {
@@ -117100,7 +117246,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
117100
117246
  }
117101
117247
  }
117102
117248
  }
117103
- const activeLocks = _internals65.listActiveLocks(directory);
117249
+ const activeLocks = _internals66.listActiveLocks(directory);
117104
117250
  const phaseLaneIds = new Set(laneIds);
117105
117251
  for (const lock of activeLocks) {
117106
117252
  if (lock.laneId && phaseLaneIds.has(lock.laneId)) {
@@ -117120,7 +117266,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
117120
117266
  }
117121
117267
  const serialDegradedTasks = runState.degradedTasks.filter((dt) => !laneTaskIds.has(dt.taskId));
117122
117268
  if (serialDegradedTasks.length > 0) {
117123
- const plan = _internals65.readPlanJson(directory);
117269
+ const plan = _internals66.readPlanJson(directory);
117124
117270
  if (!plan) {
117125
117271
  return {
117126
117272
  ok: false,
@@ -117164,7 +117310,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
117164
117310
  }
117165
117311
  const serializedTasks = runState.serializedTasks;
117166
117312
  if (Array.isArray(serializedTasks) && serializedTasks.length > 0) {
117167
- const plan = _internals65.readPlanJson(directory);
117313
+ const plan = _internals66.readPlanJson(directory);
117168
117314
  if (!plan) {
117169
117315
  return {
117170
117316
  ok: false,
@@ -117223,7 +117369,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
117223
117369
  }
117224
117370
  let reviewerVerdict = runState.lastReviewerVerdict;
117225
117371
  if (!reviewerVerdict) {
117226
- const evidence = _internals65.readReviewerEvidence(directory, phase);
117372
+ const evidence = _internals66.readReviewerEvidence(directory, phase);
117227
117373
  reviewerVerdict = evidence?.verdict ?? undefined;
117228
117374
  }
117229
117375
  if (mergedConfig.phase_reviewer) {
@@ -117236,7 +117382,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
117236
117382
  }
117237
117383
  let criticVerdict = runState.lastCriticVerdict;
117238
117384
  if (!criticVerdict) {
117239
- const evidence = _internals65.readCriticEvidence(directory, phase);
117385
+ const evidence = _internals66.readCriticEvidence(directory, phase);
117240
117386
  criticVerdict = evidence?.verdict ?? undefined;
117241
117387
  }
117242
117388
  if (mergedConfig.phase_critic) {
@@ -118336,7 +118482,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
118336
118482
  phase_critic: leanConfig.phase_critic,
118337
118483
  integrated_diff_required: leanConfig.integrated_diff_required
118338
118484
  } : undefined;
118339
- const leanCheck = _internals65.verifyLeanTurboPhaseReady(dir, phase, sessionID, leanPhaseReadyConfig);
118485
+ const leanCheck = _internals66.verifyLeanTurboPhaseReady(dir, phase, sessionID, leanPhaseReadyConfig);
118340
118486
  if (!leanCheck.ok) {
118341
118487
  return JSON.stringify({
118342
118488
  success: false,
@@ -120599,11 +120745,11 @@ var quality_budget = createSwarmTool({
120599
120745
  }).optional().describe("Quality budget thresholds")
120600
120746
  },
120601
120747
  async execute(args2, directory) {
120602
- const result = await _internals67.qualityBudget(args2, directory);
120748
+ const result = await _internals68.qualityBudget(args2, directory);
120603
120749
  return JSON.stringify(result);
120604
120750
  }
120605
120751
  });
120606
- var _internals67 = {
120752
+ var _internals68 = {
120607
120753
  qualityBudget
120608
120754
  };
120609
120755
 
@@ -121332,7 +121478,7 @@ import * as path149 from "node:path";
121332
121478
  var semgrepAvailableCache = null;
121333
121479
  var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
121334
121480
  var DEFAULT_TIMEOUT_MS3 = 30000;
121335
- var _internals68 = {
121481
+ var _internals69 = {
121336
121482
  isSemgrepAvailable,
121337
121483
  checkSemgrepAvailable,
121338
121484
  resetSemgrepCache,
@@ -121357,7 +121503,7 @@ function isSemgrepAvailable() {
121357
121503
  }
121358
121504
  }
121359
121505
  async function checkSemgrepAvailable() {
121360
- return _internals68.isSemgrepAvailable();
121506
+ return _internals69.isSemgrepAvailable();
121361
121507
  }
121362
121508
  function resetSemgrepCache() {
121363
121509
  semgrepAvailableCache = null;
@@ -121454,12 +121600,12 @@ async function runSemgrep(options) {
121454
121600
  const timeoutMs = options.timeoutMs || DEFAULT_TIMEOUT_MS3;
121455
121601
  if (files.length === 0) {
121456
121602
  return {
121457
- available: _internals68.isSemgrepAvailable(),
121603
+ available: _internals69.isSemgrepAvailable(),
121458
121604
  findings: [],
121459
121605
  engine: "tier_a"
121460
121606
  };
121461
121607
  }
121462
- if (!_internals68.isSemgrepAvailable()) {
121608
+ if (!_internals69.isSemgrepAvailable()) {
121463
121609
  return {
121464
121610
  available: false,
121465
121611
  findings: [],
@@ -121618,7 +121764,7 @@ function assignOccurrenceIndices(findings, directory) {
121618
121764
  }
121619
121765
  const occIdx = countMap.get(baseKey) ?? 0;
121620
121766
  countMap.set(baseKey, occIdx + 1);
121621
- const fp = _internals69.fingerprintFinding(finding, directory, occIdx);
121767
+ const fp = _internals70.fingerprintFinding(finding, directory, occIdx);
121622
121768
  return {
121623
121769
  finding,
121624
121770
  index: occIdx,
@@ -121687,7 +121833,7 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
121687
121833
  }
121688
121834
  } catch {}
121689
121835
  const scannedRelFiles = new Set(scannedFiles.map((f) => normalizeFindingPath(directory, f)));
121690
- const indexed = _internals69.assignOccurrenceIndices(findings, directory);
121836
+ const indexed = _internals70.assignOccurrenceIndices(findings, directory);
121691
121837
  if (existing && !opts?.force) {
121692
121838
  const prunedFingerprints = existing.fingerprints.filter((fp) => {
121693
121839
  const relFile = fp.slice(0, fp.indexOf("|"));
@@ -121827,7 +121973,7 @@ function loadBaseline(directory, phase) {
121827
121973
  };
121828
121974
  }
121829
121975
  }
121830
- var _internals69 = {
121976
+ var _internals70 = {
121831
121977
  fingerprintFinding,
121832
121978
  assignOccurrenceIndices,
121833
121979
  captureOrMergeBaseline,
@@ -122237,11 +122383,11 @@ var sast_scan = createSwarmTool({
122237
122383
  capture_baseline: safeArgs.capture_baseline,
122238
122384
  phase: safeArgs.phase
122239
122385
  };
122240
- const result = await _internals70.sastScan(input, directory);
122386
+ const result = await _internals71.sastScan(input, directory);
122241
122387
  return JSON.stringify(result, null, 2);
122242
122388
  }
122243
122389
  });
122244
- var _internals70 = {
122390
+ var _internals71 = {
122245
122391
  sastScan,
122246
122392
  sast_scan
122247
122393
  };
@@ -126008,7 +126154,7 @@ var set_qa_gates = createSwarmTool({
126008
126154
  hallucination_guard: exports_external.boolean().optional().describe("Enable hallucination_guard checks on plan and implementation claims."),
126009
126155
  sast_enabled: exports_external.boolean().optional().describe("Enable SAST scanning as a required QA gate."),
126010
126156
  mutation_test: exports_external.boolean().optional().describe("Enable the mutation-testing gate (default: off). Requires mutation " + "tests to achieve a passing kill rate before phase completion; " + "WARN verdict allows advancement, FAIL blocks."),
126011
- council_general_review: exports_external.boolean().optional().describe("Enable the council_general_review gate (default: off). When on, " + "MODE: SPECIFY runs convene_general_council on the draft spec " + "before the critic-gate, folding multi-model deliberation into " + "the spec. Requires council.general.enabled and a search API key."),
126157
+ council_general_review: exports_external.boolean().optional().describe("Enable the council_general_review gate (default: off). When on, " + "MODE: SPECIFY runs convene_general_council on the draft spec " + "before the critic-gate, folding multi-model deliberation into " + "the spec. Requires council.general.enabled and a search API key " + "in the resolved config: global ~/.config/opencode/opencode-swarm.json, " + "then project .opencode/opencode-swarm.json overrides."),
126012
126158
  drift_check: exports_external.boolean().optional().describe("Enable drift verification gate (default: on). Blocks phase_complete " + "until drift-verifier.json has an approved verdict. When disabled, " + "drift verification is skipped entirely."),
126013
126159
  final_council: exports_external.boolean().optional().describe("Enable the final_council gate (default: off). When on, " + "after all phases complete the architect dispatches critic, reviewer, " + "sme, test_engineer, and explorer with project-scoped context, " + "collects their CouncilMemberVerdict objects, and calls " + "write_final_council_evidence. This is not General Council mode " + "and does not require council.general.enabled."),
126014
126160
  project_type: exports_external.string().optional().describe('Project type label (e.g. "ts", "python"). Only applied when the profile is being created for the first time.')
@@ -127187,7 +127333,7 @@ var swarm_memory_propose = createSwarmTool({
127187
127333
  evidenceRefs: exports_external.array(exports_external.string().min(1).max(500)).max(20).optional().describe("Evidence refs such as files, commits, test outputs, or URLs")
127188
127334
  },
127189
127335
  execute: async (args2, directory, ctx) => {
127190
- const { config: config3 } = _internals71.loadPluginConfigWithMeta(directory);
127336
+ const { config: config3 } = _internals72.loadPluginConfigWithMeta(directory);
127191
127337
  if (config3.memory?.enabled !== true) {
127192
127338
  return JSON.stringify({
127193
127339
  success: false,
@@ -127203,7 +127349,7 @@ var swarm_memory_propose = createSwarmTool({
127203
127349
  });
127204
127350
  }
127205
127351
  const agent = getContextAgent2(ctx);
127206
- const gateway = _internals71.createMemoryGateway({
127352
+ const gateway = _internals72.createMemoryGateway({
127207
127353
  directory,
127208
127354
  sessionID: ctx?.sessionID,
127209
127355
  agentRole: agent,
@@ -127228,7 +127374,7 @@ var swarm_memory_propose = createSwarmTool({
127228
127374
  }
127229
127375
  }
127230
127376
  });
127231
- var _internals71 = {
127377
+ var _internals72 = {
127232
127378
  loadPluginConfigWithMeta,
127233
127379
  createMemoryGateway
127234
127380
  };
@@ -127266,7 +127412,7 @@ var swarm_memory_recall = createSwarmTool({
127266
127412
  maxItems: exports_external.number().int().min(1).max(20).optional().describe("Maximum memories to return")
127267
127413
  },
127268
127414
  execute: async (args2, directory, ctx) => {
127269
- const { config: config3 } = _internals72.loadPluginConfigWithMeta(directory);
127415
+ const { config: config3 } = _internals73.loadPluginConfigWithMeta(directory);
127270
127416
  if (config3.memory?.enabled !== true) {
127271
127417
  return JSON.stringify({
127272
127418
  success: false,
@@ -127282,7 +127428,7 @@ var swarm_memory_recall = createSwarmTool({
127282
127428
  });
127283
127429
  }
127284
127430
  const agent = getContextAgent3(ctx);
127285
- const gateway = _internals72.createMemoryGateway({
127431
+ const gateway = _internals73.createMemoryGateway({
127286
127432
  directory,
127287
127433
  sessionID: ctx?.sessionID,
127288
127434
  agentRole: agent,
@@ -127315,7 +127461,7 @@ var RecallArgsSchema = exports_external.object({
127315
127461
  kinds: exports_external.array(exports_external.enum(MEMORY_KINDS2)).optional(),
127316
127462
  maxItems: exports_external.number().int().min(1).max(20).optional()
127317
127463
  });
127318
- var _internals72 = {
127464
+ var _internals73 = {
127319
127465
  loadPluginConfigWithMeta,
127320
127466
  createMemoryGateway
127321
127467
  };
@@ -127830,7 +127976,7 @@ import * as path165 from "node:path";
127830
127976
  init_bun_compat();
127831
127977
  import * as fs122 from "node:fs";
127832
127978
  import * as path164 from "node:path";
127833
- var _internals73 = { bunSpawn };
127979
+ var _internals74 = { bunSpawn };
127834
127980
  var _swarmGitExcludedChecked = false;
127835
127981
  function fileCoversSwarm(content) {
127836
127982
  for (const rawLine of content.split(`
@@ -127863,7 +128009,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
127863
128009
  checkIgnoreExitCode
127864
128010
  ] = await Promise.all([
127865
128011
  (async () => {
127866
- const proc = _internals73.bunSpawn(["git", "-C", directory, "rev-parse", "--show-toplevel"], GIT_SPAWN_OPTIONS);
128012
+ const proc = _internals74.bunSpawn(["git", "-C", directory, "rev-parse", "--show-toplevel"], GIT_SPAWN_OPTIONS);
127867
128013
  try {
127868
128014
  return await Promise.all([proc.exited, proc.stdout.text()]);
127869
128015
  } finally {
@@ -127873,7 +128019,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
127873
128019
  }
127874
128020
  })(),
127875
128021
  (async () => {
127876
- const proc = _internals73.bunSpawn(["git", "-C", directory, "rev-parse", "--git-path", "info/exclude"], GIT_SPAWN_OPTIONS);
128022
+ const proc = _internals74.bunSpawn(["git", "-C", directory, "rev-parse", "--git-path", "info/exclude"], GIT_SPAWN_OPTIONS);
127877
128023
  try {
127878
128024
  return await Promise.all([proc.exited, proc.stdout.text()]);
127879
128025
  } finally {
@@ -127883,7 +128029,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
127883
128029
  }
127884
128030
  })(),
127885
128031
  (async () => {
127886
- const proc = _internals73.bunSpawn(["git", "-C", directory, "check-ignore", "-q", ".swarm/.gitkeep"], GIT_SPAWN_OPTIONS);
128032
+ const proc = _internals74.bunSpawn(["git", "-C", directory, "check-ignore", "-q", ".swarm/.gitkeep"], GIT_SPAWN_OPTIONS);
127887
128033
  try {
127888
128034
  return await proc.exited;
127889
128035
  } finally {
@@ -127922,7 +128068,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
127922
128068
  }
127923
128069
  } catch {}
127924
128070
  }
127925
- const trackedProc = _internals73.bunSpawn(["git", "-C", directory, "ls-files", "--", ".swarm"], GIT_SPAWN_OPTIONS);
128071
+ const trackedProc = _internals74.bunSpawn(["git", "-C", directory, "ls-files", "--", ".swarm"], GIT_SPAWN_OPTIONS);
127926
128072
  let trackedExitCode;
127927
128073
  let trackedOutput;
127928
128074
  try {
@@ -127947,7 +128093,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
127947
128093
  }
127948
128094
 
127949
128095
  // src/hooks/diff-scope.ts
127950
- var _internals74 = { bunSpawn };
128096
+ var _internals75 = { bunSpawn };
127951
128097
  function getDeclaredScope(taskId, directory) {
127952
128098
  try {
127953
128099
  const planPath = path165.join(directory, ".swarm", "plan.json");
@@ -127982,7 +128128,7 @@ var GIT_DIFF_SPAWN_OPTIONS = {
127982
128128
  };
127983
128129
  async function getChangedFiles(directory) {
127984
128130
  try {
127985
- const proc = _internals74.bunSpawn(["git", "diff", "--name-only", "HEAD~1"], {
128131
+ const proc = _internals75.bunSpawn(["git", "diff", "--name-only", "HEAD~1"], {
127986
128132
  cwd: directory,
127987
128133
  ...GIT_DIFF_SPAWN_OPTIONS
127988
128134
  });
@@ -127999,7 +128145,7 @@ async function getChangedFiles(directory) {
127999
128145
  return stdout.trim().split(`
128000
128146
  `).map((f) => f.trim()).filter((f) => f.length > 0);
128001
128147
  }
128002
- const proc2 = _internals74.bunSpawn(["git", "diff", "--name-only", "HEAD"], {
128148
+ const proc2 = _internals75.bunSpawn(["git", "diff", "--name-only", "HEAD"], {
128003
128149
  cwd: directory,
128004
128150
  ...GIT_DIFF_SPAWN_OPTIONS
128005
128151
  });
@@ -128057,7 +128203,7 @@ init_telemetry();
128057
128203
  init_file_locks();
128058
128204
  import * as fs124 from "node:fs";
128059
128205
  import * as path166 from "node:path";
128060
- var _internals75 = {
128206
+ var _internals76 = {
128061
128207
  listActiveLocks,
128062
128208
  verifyLeanTurboTaskCompletion
128063
128209
  };
@@ -128199,7 +128345,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
128199
128345
  }
128200
128346
  };
128201
128347
  }
128202
- const activeLocks = _internals75.listActiveLocks(directory);
128348
+ const activeLocks = _internals76.listActiveLocks(directory);
128203
128349
  const laneLocks = activeLocks.filter((lock) => lock.laneId === lane.laneId);
128204
128350
  if (laneLocks.length > 0) {
128205
128351
  return {
@@ -128806,6 +128952,52 @@ var update_task_status = createSwarmTool({
128806
128952
  init_zod();
128807
128953
  init_loader();
128808
128954
 
128955
+ // src/council/search-query-policy.ts
128956
+ var CURRENT_INTENT_RE = /\b(?:latest|current|currently|today|now|newest|recent|recently|up\s*-?\s*to\s*-?\s*date|this\s+(?:week|month|year)|as\s+of\s+(?:today|now))\b/i;
128957
+ var HISTORICAL_INTENT_RE = /\b(?:history|historical|archive|archived|in\s+20\d{2}|during\s+20\d{2}|from\s+20\d{2}|for\s+20\d{2}|as\s+of\s+20\d{2})\b/i;
128958
+ function applySearchQueryPolicy(rawQuery, now = new Date) {
128959
+ const originalQuery = rawQuery;
128960
+ let query = rawQuery.trim().replace(/\s+/g, " ");
128961
+ const currentYear = now.getUTCFullYear();
128962
+ const temporalIntent = detectTemporalIntent(query);
128963
+ const removedStaleYears = [];
128964
+ if (temporalIntent === "current") {
128965
+ query = removeTrailingStaleCutoffYears(query, currentYear, removedStaleYears);
128966
+ }
128967
+ return {
128968
+ originalQuery,
128969
+ query,
128970
+ temporalIntent,
128971
+ freshness: temporalIntent === "current" ? chooseFreshness(query) : undefined,
128972
+ removedStaleYears
128973
+ };
128974
+ }
128975
+ function detectTemporalIntent(query) {
128976
+ if (CURRENT_INTENT_RE.test(query))
128977
+ return "current";
128978
+ if (HISTORICAL_INTENT_RE.test(query))
128979
+ return "historical";
128980
+ return "unspecified";
128981
+ }
128982
+ function chooseFreshness(query) {
128983
+ if (/\b(?:today|now|as\s+of\s+(?:today|now))\b/i.test(query))
128984
+ return "day";
128985
+ if (/\bthis\s+week\b/i.test(query))
128986
+ return "week";
128987
+ if (/\b(?:recent|recently|this\s+month)\b/i.test(query))
128988
+ return "month";
128989
+ return "year";
128990
+ }
128991
+ function removeTrailingStaleCutoffYears(query, currentYear, removed) {
128992
+ return query.replace(/\s+(?:as\s+of\s+)?(20\d{2})\s*$/i, (match, year) => {
128993
+ const numericYear = Number(year);
128994
+ if (numericYear >= currentYear)
128995
+ return match;
128996
+ removed.push(year);
128997
+ return "";
128998
+ }).replace(/\s+/g, " ").trim();
128999
+ }
129000
+
128809
129001
  // src/council/web-search-provider.ts
128810
129002
  class WebSearchError extends Error {
128811
129003
  cause;
@@ -128828,18 +129020,22 @@ class TavilyProvider {
128828
129020
  constructor(apiKey) {
128829
129021
  this.apiKey = apiKey;
128830
129022
  }
128831
- async search(query, maxResults) {
129023
+ async search(query, maxResults, options = {}) {
129024
+ const requestBody = {
129025
+ api_key: this.apiKey,
129026
+ query,
129027
+ max_results: maxResults,
129028
+ search_depth: "advanced"
129029
+ };
129030
+ if (options.freshness) {
129031
+ requestBody.time_range = options.freshness;
129032
+ }
128832
129033
  let response;
128833
129034
  try {
128834
129035
  response = await fetch("https://api.tavily.com/search", {
128835
129036
  method: "POST",
128836
129037
  headers: { "Content-Type": "application/json" },
128837
- body: JSON.stringify({
128838
- api_key: this.apiKey,
128839
- query,
128840
- max_results: maxResults,
128841
- search_depth: "advanced"
128842
- })
129038
+ body: JSON.stringify(requestBody)
128843
129039
  });
128844
129040
  } catch (err3) {
128845
129041
  throw new WebSearchError(`Tavily network error for query "${query}"`, err3);
@@ -128871,10 +129067,14 @@ class BraveProvider {
128871
129067
  constructor(apiKey) {
128872
129068
  this.apiKey = apiKey;
128873
129069
  }
128874
- async search(query, maxResults) {
129070
+ async search(query, maxResults, options = {}) {
128875
129071
  const url3 = new URL("https://api.search.brave.com/res/v1/web/search");
128876
129072
  url3.searchParams.set("q", query);
128877
129073
  url3.searchParams.set("count", String(maxResults));
129074
+ const freshness = toBraveFreshness(options.freshness);
129075
+ if (freshness) {
129076
+ url3.searchParams.set("freshness", freshness);
129077
+ }
128878
129078
  let response;
128879
129079
  try {
128880
129080
  response = await fetch(url3.toString(), {
@@ -128908,6 +129108,20 @@ class BraveProvider {
128908
129108
  }));
128909
129109
  }
128910
129110
  }
129111
+ function toBraveFreshness(freshness) {
129112
+ switch (freshness) {
129113
+ case "day":
129114
+ return "pd";
129115
+ case "week":
129116
+ return "pw";
129117
+ case "month":
129118
+ return "pm";
129119
+ case "year":
129120
+ return "py";
129121
+ default:
129122
+ return;
129123
+ }
129124
+ }
128911
129125
  function resolveApiKey(provider, configKey) {
128912
129126
  if (configKey && configKey.length > 0) {
128913
129127
  return configKey;
@@ -128920,7 +129134,7 @@ function createWebSearchProvider(config3) {
128920
129134
  const apiKey = resolveApiKey(config3.searchProvider, config3.searchApiKey);
128921
129135
  if (!apiKey) {
128922
129136
  const envName = config3.searchProvider === "tavily" ? "TAVILY_API_KEY" : "BRAVE_SEARCH_API_KEY";
128923
- throw new WebSearchConfigError(`No API key for search provider "${config3.searchProvider}". Set ` + `council.general.searchApiKey in opencode-swarm.json or export ${envName}.`);
129137
+ throw new WebSearchConfigError(`No API key for search provider "${config3.searchProvider}". Set ` + `council.general.searchApiKey in the resolved config (global ~/.config/opencode/opencode-swarm.json, project .opencode/opencode-swarm.json override) or export ${envName}.`);
128924
129138
  }
128925
129139
  switch (config3.searchProvider) {
128926
129140
  case "tavily":
@@ -129014,12 +129228,14 @@ var MAX_RESULTS_HARD_CAP = 10;
129014
129228
  var ArgsSchema6 = exports_external.object({
129015
129229
  query: exports_external.string().min(1).max(500),
129016
129230
  max_results: exports_external.number().int().min(1).max(20).optional(),
129231
+ freshness: exports_external.enum(["auto", "none", "day", "week", "month", "year"]).default("auto"),
129017
129232
  working_directory: exports_external.string().optional()
129018
129233
  });
129019
129234
  var web_search = createSwarmTool({
129020
- description: "External web search for architect-driven council research. Returns titled results with snippets and URLs. " + "Used by the architect in MODE: COUNCIL to gather a RESEARCH CONTEXT before dispatching council agents. " + "Requires council.general.enabled and a configured search API key (Tavily or Brave). max_results is capped at 10 with default from council.general.maxSourcesPerMember.",
129235
+ description: "External web search for architect-driven council research. Returns titled results with snippets and URLs. " + "Used by the architect in MODE: COUNCIL to gather a RESEARCH CONTEXT before dispatching council agents. " + "Normalizes current-intent queries, strips trailing stale cutoff years, and applies provider freshness filters by default. " + "Requires council.general.enabled and a configured search API key (Tavily or Brave) in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides. max_results is capped at 10 with default from council.general.maxSourcesPerMember.",
129021
129236
  args: {
129022
129237
  query: exports_external.string().min(1).max(500).describe("Search query string (1–500 characters)."),
129238
+ freshness: exports_external.enum(["auto", "none", "day", "week", "month", "year"]).optional().describe('Optional freshness filter. Query normalization always runs; "auto" infers provider freshness from current/recency terms, while "none" disables provider freshness filtering.'),
129023
129239
  max_results: exports_external.number().int().min(1).max(20).optional().describe(`Number of results to request (1–20). Hard-capped at ${MAX_RESULTS_HARD_CAP}. Defaults to council.general.maxSourcesPerMember.`),
129024
129240
  working_directory: exports_external.string().optional().describe("Project root for config resolution. Optional.")
129025
129241
  },
@@ -129048,12 +129264,15 @@ var web_search = createSwarmTool({
129048
129264
  const fail = {
129049
129265
  success: false,
129050
129266
  reason: "council_general_disabled",
129051
- message: "web_search is disabled set council.general.enabled: true in opencode-swarm.json."
129267
+ message: "web_search is disabled - set council.general.enabled: true in the resolved config: global ~/.config/opencode/opencode-swarm.json or project .opencode/opencode-swarm.json."
129052
129268
  };
129053
129269
  return JSON.stringify(fail, null, 2);
129054
129270
  }
129055
129271
  const requested = parsed.data.max_results ?? generalConfig.maxSourcesPerMember;
129056
129272
  const maxResults = Math.min(requested, MAX_RESULTS_HARD_CAP);
129273
+ const policy = applySearchQueryPolicy(parsed.data.query);
129274
+ const requestedFreshness = parsed.data.freshness ?? "auto";
129275
+ const freshness = requestedFreshness === "auto" ? policy.freshness : requestedFreshness === "none" ? undefined : requestedFreshness;
129057
129276
  let provider;
129058
129277
  try {
129059
129278
  provider = createWebSearchProvider(generalConfig);
@@ -129066,11 +129285,17 @@ var web_search = createSwarmTool({
129066
129285
  return JSON.stringify(fail, null, 2);
129067
129286
  }
129068
129287
  try {
129069
- const results = await provider.search(parsed.data.query, maxResults);
129070
- const evidence = await captureSearchEvidence(dirResult.directory, parsed.data.query, results);
129288
+ const results = await provider.search(policy.query, maxResults, {
129289
+ freshness
129290
+ });
129291
+ const evidence = await captureSearchEvidence(dirResult.directory, policy.query, results);
129071
129292
  const ok2 = {
129072
129293
  success: true,
129073
- query: parsed.data.query,
129294
+ query: policy.query,
129295
+ originalQuery: policy.originalQuery,
129296
+ temporalIntent: policy.temporalIntent,
129297
+ freshness,
129298
+ removedStaleYears: policy.removedStaleYears,
129074
129299
  totalResults: results.length,
129075
129300
  results: results.map(({ title, url: url3, snippet }) => ({
129076
129301
  title,
@@ -129098,7 +129323,7 @@ var web_search = createSwarmTool({
129098
129323
  });
129099
129324
  async function captureSearchEvidence(directory, query, results) {
129100
129325
  try {
129101
- const written = await _internals76.writeEvidenceDocuments(directory, results.map((result) => ({
129326
+ const written = await _internals77.writeEvidenceDocuments(directory, results.map((result) => ({
129102
129327
  sourceType: "web_search",
129103
129328
  query,
129104
129329
  title: result.title,
@@ -129126,7 +129351,7 @@ async function captureSearchEvidence(directory, query, results) {
129126
129351
  };
129127
129352
  }
129128
129353
  }
129129
- var _internals76 = {
129354
+ var _internals77 = {
129130
129355
  writeEvidenceDocuments
129131
129356
  };
129132
129357
 
@@ -130376,7 +130601,7 @@ async function initializeOpenCodeSwarm(ctx) {
130376
130601
  ...opencodeConfig.command || {},
130377
130602
  swarm: {
130378
130603
  template: "/swarm $ARGUMENTS",
130379
- description: "Swarm management commands: /swarm [status|show-plan|plan|agents|history|config|help|evidence|handoff|archive|diagnose|diagnosis|preflight|sync-plan|benchmark|export|reset|rollback|retrieve|clarify|analyze|specify|brainstorm|council|pr-review|issue|qa-gates|dark-matter|knowledge|memory|curate|concurrency|turbo|full-auto|write-retro|reset-session|simulate|promote|checkpoint|acknowledge-spec-drift|doctor tools|finalize|close]"
130604
+ description: "Swarm management commands: /swarm [status|show-plan|plan|agents|history|config|help|evidence|handoff|archive|diagnose|diagnosis|preflight|sync-plan|benchmark|export|reset|rollback|retrieve|clarify|analyze|specify|brainstorm|council|pr-review|pr-feedback|deep-dive|design-docs|issue|qa-gates|dark-matter|knowledge|memory|curate|concurrency|turbo|full-auto|write-retro|reset-session|simulate|promote|checkpoint|acknowledge-spec-drift|doctor tools|finalize|close]"
130380
130605
  },
130381
130606
  "swarm-status": {
130382
130607
  template: "/swarm status",
@@ -130474,10 +130699,18 @@ async function initializeOpenCodeSwarm(ctx) {
130474
130699
  template: "/swarm pr-review $ARGUMENTS",
130475
130700
  description: "Use /swarm pr-review to launch deep PR review with multi-lane analysis"
130476
130701
  },
130702
+ "swarm-pr-feedback": {
130703
+ template: "/swarm pr-feedback $ARGUMENTS",
130704
+ description: "Use /swarm pr-feedback to ingest and close known PR feedback (review comments, CI failures, conflicts) without a fresh broad review"
130705
+ },
130477
130706
  "swarm-deep-dive": {
130478
130707
  template: "/swarm deep-dive $ARGUMENTS",
130479
130708
  description: "Use /swarm deep-dive to launch a read-only deep audit with parallel explorer waves, dual reviewers, and critic challenge"
130480
130709
  },
130710
+ "swarm-design-docs": {
130711
+ template: "/swarm design-docs $ARGUMENTS",
130712
+ description: "Use /swarm design-docs to generate or sync language-agnostic design docs for the project under build"
130713
+ },
130481
130714
  "swarm-issue": {
130482
130715
  template: "/swarm issue $ARGUMENTS",
130483
130716
  description: "Use /swarm issue to ingest a GitHub issue into the swarm workflow"