opencode-swarm 7.111.0 → 7.112.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/.opencode/skills/swarm-pr-feedback/SKILL.md +24 -0
  2. package/dist/background/pr-event-subscribers.d.ts +28 -0
  3. package/dist/background/pr-monitor-worker.d.ts +8 -1
  4. package/dist/background/pr-subscriptions.d.ts +6 -0
  5. package/dist/cli/{config-doctor-q5e9yzn6.js → config-doctor-mmw4c50z.js} +2 -2
  6. package/dist/cli/{core-9a7nn51x.js → core-f4cbabe7.js} +2 -2
  7. package/dist/cli/{curator-drift-169wgaxn.js → curator-drift-jvs1v6em.js} +2 -2
  8. package/dist/cli/{curator-2hm297yd.js → curator-j7ty8k6t.js} +19 -19
  9. package/dist/cli/curator-llm-factory-8rnk2083.js +40 -0
  10. package/dist/cli/{dispatch-zr1xja4t.js → dispatch-wst7bypk.js} +2 -2
  11. package/dist/cli/{evidence-summary-service-8tasw2tt.js → evidence-summary-service-j6fnsfeq.js} +5 -5
  12. package/dist/cli/{gate-evidence-v6ds8rcp.js → gate-evidence-mk0ss1re.js} +3 -3
  13. package/dist/cli/guardrail-explain-2j0gw8f0.js +41 -0
  14. package/dist/cli/{guardrail-log-973nan7m.js → guardrail-log-xjgr00eq.js} +4 -4
  15. package/dist/cli/{hive-promoter-0f8xh2rn.js → hive-promoter-y179n7wx.js} +19 -19
  16. package/dist/cli/{index-1cn967sa.js → index-0dab9w37.js} +1 -1
  17. package/dist/cli/{index-r3j3458j.js → index-1rga1vvb.js} +1 -1
  18. package/dist/cli/{index-mvg66d9n.js → index-2aqs6daa.js} +3 -3
  19. package/dist/cli/{index-yw8qpf51.js → index-9fxs0rm1.js} +1 -1
  20. package/dist/cli/{index-cmjq1kg7.js → index-b83y9a7r.js} +3 -3
  21. package/dist/cli/{index-kf2h31c7.js → index-c3h3d8kh.js} +21 -21
  22. package/dist/cli/{index-0g5xsrp4.js → index-cq2hgvd2.js} +13 -5
  23. package/dist/cli/{index-yhmt3dw3.js → index-cye4g7zj.js} +3 -3
  24. package/dist/cli/{index-j2v3w1ds.js → index-d0w40jm3.js} +4 -4
  25. package/dist/cli/{index-40h0yp9e.js → index-db1fh1fv.js} +1 -1
  26. package/dist/cli/{index-dnbca696.js → index-fhmw7evd.js} +2 -2
  27. package/dist/cli/{index-vzzt3ygr.js → index-g55nzpwn.js} +1 -1
  28. package/dist/cli/{index-c483hnn4.js → index-hg0pamsa.js} +3 -3
  29. package/dist/cli/{index-7xfh4k71.js → index-j5c98bd9.js} +401 -257
  30. package/dist/cli/{index-53z1afgh.js → index-npxmfj48.js} +1 -1
  31. package/dist/cli/{index-6jng9c8t.js → index-pm992z24.js} +1 -1
  32. package/dist/cli/{index-85bacexr.js → index-q1jaeynn.js} +4 -1
  33. package/dist/cli/{index-v8pk35h7.js → index-t7efm8vz.js} +4 -4
  34. package/dist/cli/{index-5rfxzgmt.js → index-w84stmkx.js} +1 -1
  35. package/dist/cli/{index-9ptp9kky.js → index-x4bghdyv.js} +2 -2
  36. package/dist/cli/{index-xddysq89.js → index-xehrmy76.js} +1 -1
  37. package/dist/cli/index.js +19 -19
  38. package/dist/cli/{knowledge-escalator-0dkkenp2.js → knowledge-escalator-t1e2211j.js} +6 -6
  39. package/dist/cli/{knowledge-events-bckbj6ah.js → knowledge-events-2h3gvtfa.js} +4 -4
  40. package/dist/cli/{knowledge-store-dvjbdn00.js → knowledge-store-gpta9gzh.js} +4 -4
  41. package/dist/cli/{knowledge-validator-bqr936sg.js → knowledge-validator-03f0hm0p.js} +5 -5
  42. package/dist/cli/{pending-delegations-yyz3fcfn.js → pending-delegations-gc3a2hfx.js} +2 -2
  43. package/dist/cli/{pr-subscriptions-vv8byxe6.js → pr-subscriptions-p8g2rzxd.js} +3 -3
  44. package/dist/cli/{schema-s48je8zt.js → schema-2p15yrvn.js} +1 -1
  45. package/dist/cli/{scope-persistence-tgp00wtd.js → scope-persistence-5ccgtebg.js} +2 -2
  46. package/dist/cli/{skill-generator-5rsjmmfq.js → skill-generator-2tsqqaa2.js} +7 -7
  47. package/dist/commands/ci-simulate.d.ts +36 -12
  48. package/dist/commands/pr-monitor-status.d.ts +8 -0
  49. package/dist/config/bundled-skills.d.ts +1 -1
  50. package/dist/config/schema.d.ts +5 -0
  51. package/dist/full-auto/oversight.d.ts +4 -1
  52. package/dist/full-auto/state.d.ts +12 -0
  53. package/dist/git/pr.d.ts +23 -0
  54. package/dist/hooks/delegation-gate/worktree-isolation.d.ts +110 -0
  55. package/dist/hooks/delegation-gate.d.ts +17 -2
  56. package/dist/hooks/full-auto-intercept.d.ts +1 -1
  57. package/dist/index.js +211 -186
  58. package/dist/tools/placeholder-scan.d.ts +14 -1
  59. package/dist/utils/bun-compat.d.ts +6 -0
  60. package/dist/worktree/merge.d.ts +12 -0
  61. package/package.json +7 -5
  62. package/dist/cli/curator-llm-factory-19s0r5v6.js +0 -40
  63. package/dist/cli/guardrail-explain-8w9rkdjx.js +0 -41
  64. /package/dist/cli/{index-7xgqky26.js → index-h91bv3hy.js} +0 -0
@@ -7,7 +7,7 @@ import {
7
7
  readDoctorArtifact,
8
8
  removeStraySwarmDir,
9
9
  runConfigDoctor
10
- } from "./index-xddysq89.js";
10
+ } from "./index-xehrmy76.js";
11
11
  import {
12
12
  AGENT_TOOL_MAP,
13
13
  ALL_SUBAGENT_NAMES,
@@ -23,7 +23,7 @@ import {
23
23
  getCanonicalAgentRole,
24
24
  resolveExternalSkillsConfig,
25
25
  stripKnownSwarmPrefix
26
- } from "./index-0g5xsrp4.js";
26
+ } from "./index-cq2hgvd2.js";
27
27
  import {
28
28
  MAX_TRANSIENT_RETRIES,
29
29
  PlanSchema,
@@ -39,6 +39,7 @@ import {
39
39
  disableEpicMode,
40
40
  enableEpicMode,
41
41
  getAllWorktreeMergeFailures,
42
+ getDefaultBaseBranch,
42
43
  getDurableGateEvidenceStatusForTask,
43
44
  getExecutor,
44
45
  getGitRepositoryStatus,
@@ -67,7 +68,7 @@ import {
67
68
  savePlan,
68
69
  transientBackoff,
69
70
  validateProjectRoot
70
- } from "./index-j2v3w1ds.js";
71
+ } from "./index-d0w40jm3.js";
71
72
  import {
72
73
  buildOpenSpecProjectionSync,
73
74
  detectSpeckit,
@@ -82,13 +83,13 @@ import {
82
83
  _internals1 as _internals2,
83
84
  isCommandAvailable,
84
85
  tool
85
- } from "./index-yw8qpf51.js";
86
+ } from "./index-9fxs0rm1.js";
86
87
  import {
87
88
  buildCorrelationId,
88
89
  listActive,
89
90
  subscribe,
90
91
  unsubscribe
91
- } from "./index-85bacexr.js";
92
+ } from "./index-q1jaeynn.js";
92
93
  import {
93
94
  DEFAULT_SKILL_MIN_CONFIDENCE,
94
95
  DEFAULT_SKILL_MIN_CONFIRMATIONS,
@@ -105,7 +106,7 @@ import {
105
106
  retireOrMarkStale,
106
107
  retireSkill,
107
108
  selectCandidateEntries
108
- } from "./index-cmjq1kg7.js";
109
+ } from "./index-b83y9a7r.js";
109
110
  import {
110
111
  appendUnactionable,
111
112
  quarantineEntry,
@@ -115,10 +116,10 @@ import {
115
116
  validateActionability,
116
117
  validateActionableFields,
117
118
  validateLesson
118
- } from "./index-c483hnn4.js";
119
+ } from "./index-hg0pamsa.js";
119
120
  import {
120
121
  readRecentEscalations
121
- } from "./index-mvg66d9n.js";
122
+ } from "./index-2aqs6daa.js";
122
123
  import {
123
124
  effectiveRetrievalOutcomes,
124
125
  readKnowledgeCounterRollups,
@@ -126,7 +127,7 @@ import {
126
127
  recordHiveKnowledgeEvent,
127
128
  recordKnowledgeEvent,
128
129
  resolveKnowledgeEventsPath
129
- } from "./index-yhmt3dw3.js";
130
+ } from "./index-cye4g7zj.js";
130
131
  import {
131
132
  appendKnowledge,
132
133
  appendRejectedLesson,
@@ -148,7 +149,7 @@ import {
148
149
  rewriteKnowledge,
149
150
  transactFile,
150
151
  transactKnowledge
151
- } from "./index-v8pk35h7.js";
152
+ } from "./index-t7efm8vz.js";
152
153
  import {
153
154
  KNOWLEDGE_SCHEMA_VERSION,
154
155
  OUTCOME_BLOCK_THRESHOLD,
@@ -162,7 +163,7 @@ import {
162
163
  resolveLinkDir,
163
164
  sanitizeLinkId,
164
165
  writeLinkPointer
165
- } from "./index-40h0yp9e.js";
166
+ } from "./index-db1fh1fv.js";
166
167
  import {
167
168
  CURATOR_INIT_PROMPT,
168
169
  CURATOR_PHASE_PROMPT,
@@ -174,12 +175,12 @@ import {
174
175
  } from "./index-wvrj16f0.js";
175
176
  import {
176
177
  clearAllScopes
177
- } from "./index-vzzt3ygr.js";
178
+ } from "./index-g55nzpwn.js";
178
179
  import {
179
180
  readSwarmFileAsync,
180
181
  safeHook,
181
182
  validateSwarmPath
182
- } from "./index-r3j3458j.js";
183
+ } from "./index-1rga1vvb.js";
183
184
  import {
184
185
  deepMerge
185
186
  } from "./index-p0arc26j.js";
@@ -191,7 +192,7 @@ import {
191
192
  } from "./index-zgwm4ryv.js";
192
193
  import {
193
194
  atomicWriteFile
194
- } from "./index-1cn967sa.js";
195
+ } from "./index-0dab9w37.js";
195
196
  import {
196
197
  exports_external
197
198
  } from "./index-293f68mj.js";
@@ -208,7 +209,7 @@ import {
208
209
  bunSpawn,
209
210
  bunWrite,
210
211
  mergeEnvForChild
211
- } from "./index-7xgqky26.js";
212
+ } from "./index-h91bv3hy.js";
212
213
  import {
213
214
  __require,
214
215
  __toESM
@@ -472,7 +473,8 @@ var _internals4 = {
472
473
  platform: process.platform,
473
474
  sleep: (ms) => new Promise((resolve2) => setTimeout(resolve2, ms)),
474
475
  cleanupOrphanedBranches,
475
- startupOrphanRecovery
476
+ startupOrphanRecovery,
477
+ extractSessionId
476
478
  };
477
479
  var MERGE_TIMEOUT_MS = 30000;
478
480
  async function runGit(args, cwd, timeoutMs = MERGE_TIMEOUT_MS) {
@@ -5034,11 +5036,11 @@ var BUNDLED_PROJECT_SKILLS = [
5034
5036
  "running-tests",
5035
5037
  "engineering-conventions",
5036
5038
  "commit-pr",
5037
- "worktree-retry-cleanup",
5038
- "skill-edit-validation",
5039
- "merge-queue-readiness",
5039
+ "ci-failure-batching",
5040
5040
  "gate-attribution",
5041
- "ci-failure-batching"
5041
+ "merge-queue-readiness",
5042
+ "skill-edit-validation",
5043
+ "worktree-retry-cleanup"
5042
5044
  ];
5043
5045
  var MAX_SKILL_FILES = 64;
5044
5046
  var MAX_SKILL_BYTES = 512000;
@@ -6557,6 +6559,8 @@ async function handleList2(directory) {
6557
6559
 
6558
6560
  // src/commands/ci-simulate.ts
6559
6561
  import * as fs4 from "fs";
6562
+ import * as fsPromises2 from "fs/promises";
6563
+ import * as os5 from "os";
6560
6564
  import * as path13 from "path";
6561
6565
 
6562
6566
  // src/utils/external-tool-runner.ts
@@ -6719,148 +6723,254 @@ var _internals7 = {
6719
6723
  };
6720
6724
 
6721
6725
  // src/commands/ci-simulate.ts
6722
- var DEFAULT_BASE = "origin/main";
6723
- var DEFAULT_HEAD = "HEAD";
6724
- var DEFAULT_CI_COMMANDS = [
6725
- ["bun", "run", "typecheck"],
6726
- ["bun", "run", "lint:ci"],
6727
- ["bun", "run", "build"],
6728
- ["bun", "run", "test:unit:ci"],
6729
- ["bun", "test", "tests/integration", "--timeout", "120000"],
6730
- ["bun", "test", "tests/security", "--timeout", "120000"],
6731
- ["bun", "test", "tests/smoke", "--timeout", "120000"],
6732
- ["bun", "run", "drift:check"]
6733
- ];
6734
- var COMMAND_TIMEOUT_MS = 10 * 60 * 1000;
6735
- var GIT_TIMEOUT_MS2 = 60 * 1000;
6736
- var OUTPUT_LIMIT = 12000;
6737
- async function runCommand(cmd, cwd, timeout) {
6726
+ var GIT_TIMEOUT_MS2 = 30000;
6727
+ var VALIDATION_TIMEOUT_MS = 5 * 60 * 1000;
6728
+ var OUTPUT_LIMIT_BYTES = 12000;
6729
+ var _internals8 = {
6730
+ runExternalTool,
6731
+ getDefaultBaseBranch,
6732
+ platform: process.platform,
6733
+ osTmpdir: () => os5.tmpdir(),
6734
+ fs: {
6735
+ existsSync: fs4.existsSync,
6736
+ rmSync: fs4.rmSync
6737
+ }
6738
+ };
6739
+ async function runGit2(args, cwd, timeoutMs = GIT_TIMEOUT_MS2) {
6740
+ const result = await _internals8.runExternalTool({
6741
+ executable: "git",
6742
+ args,
6743
+ cwd,
6744
+ timeoutMs,
6745
+ maxStdoutBytes: OUTPUT_LIMIT_BYTES,
6746
+ maxStderrBytes: OUTPUT_LIMIT_BYTES
6747
+ });
6748
+ return {
6749
+ exitCode: result.exitCode ?? 1,
6750
+ stdout: result.message ? [result.message, result.stdout].filter(Boolean).join(`
6751
+ `) : result.stdout,
6752
+ stderr: result.stderr,
6753
+ outputTruncated: result.stdoutTruncated || result.stderrTruncated
6754
+ };
6755
+ }
6756
+ async function runValidationCommand(cmd, cwd, timeoutMs = VALIDATION_TIMEOUT_MS) {
6738
6757
  const [executable, ...args] = cmd;
6739
- const result = await runExternalTool({
6758
+ const result = await _internals8.runExternalTool({
6740
6759
  executable,
6741
6760
  args,
6742
6761
  cwd,
6743
- timeoutMs: timeout,
6744
- maxStdoutBytes: OUTPUT_LIMIT,
6745
- maxStderrBytes: OUTPUT_LIMIT
6762
+ timeoutMs,
6763
+ maxStdoutBytes: OUTPUT_LIMIT_BYTES,
6764
+ maxStderrBytes: OUTPUT_LIMIT_BYTES
6746
6765
  });
6747
6766
  return {
6748
6767
  exitCode: result.exitCode ?? 1,
6749
6768
  stdout: result.message ? [result.message, result.stdout].filter(Boolean).join(`
6750
6769
  `) : result.stdout,
6751
6770
  stderr: result.stderr,
6752
- stdoutTruncated: result.stdoutTruncated,
6753
- stderrTruncated: result.stderrTruncated
6771
+ outputTruncated: result.stdoutTruncated || result.stderrTruncated
6754
6772
  };
6755
6773
  }
6756
- function readOptionalFlag(args, name) {
6757
- const index = args.indexOf(name);
6758
- if (index < 0)
6759
- return null;
6760
- const value = args[index + 1];
6761
- return value && !value.startsWith("--") ? value : null;
6774
+ function isSafeGitRef(ref) {
6775
+ return ref.length > 0 && ref.length <= 255 && /^[A-Za-z0-9][A-Za-z0-9._/@-]*$/.test(ref) && !ref.includes("..") && !ref.includes("//") && !ref.includes("@{") && !ref.endsWith(".");
6762
6776
  }
6763
- function readFlag(args, name, fallback) {
6764
- return readOptionalFlag(args, name) ?? fallback;
6777
+ async function getCurrentBranchOrRef(directory) {
6778
+ const result = await runGit2(["branch", "--show-current"], directory);
6779
+ if (result.exitCode === 0 && result.stdout.trim()) {
6780
+ return result.stdout.trim();
6781
+ }
6782
+ const hashResult = await runGit2(["rev-parse", "HEAD"], directory);
6783
+ return hashResult.stdout.trim();
6765
6784
  }
6766
- function hasUnsupportedArgs(args) {
6767
- const allowedWithValue = new Set(["--base", "--head"]);
6768
- for (let i = 0;i < args.length; i++) {
6769
- const arg = args[i];
6770
- if (!arg.startsWith("--"))
6771
- return `unexpected positional argument ${arg}`;
6772
- if (!allowedWithValue.has(arg))
6773
- return arg;
6774
- const value = args[i + 1];
6775
- if (!value || value.startsWith("--"))
6776
- return `missing value for ${arg}`;
6777
- i++;
6785
+ async function setupWorktree(projectRoot, prRef, baseBranch, onWorktreeCreated) {
6786
+ const worktreeBase = path13.join(_internals8.osTmpdir(), "swarm-ci-simulate");
6787
+ const worktreeName = `pr-${Date.now()}-${Math.floor(Math.random() * 1e6)}`;
6788
+ const worktreePath = path13.join(worktreeBase, worktreeName);
6789
+ await fsPromises2.mkdir(worktreeBase, { recursive: true });
6790
+ const addResult = await runGit2(["worktree", "add", "--detach", worktreePath, baseBranch], projectRoot);
6791
+ if (addResult.exitCode !== 0) {
6792
+ throw new Error(`Failed to create worktree: ${addResult.stderr.trim() || addResult.stdout.trim()}`);
6778
6793
  }
6779
- return null;
6794
+ onWorktreeCreated(worktreePath);
6795
+ const mergeResult = await runGit2(["merge", "--no-ff", "--no-edit", "--", prRef], worktreePath, GIT_TIMEOUT_MS2 * 2);
6796
+ if (mergeResult.exitCode !== 0) {
6797
+ throw new Error(`Merge failed for '${prRef}': ${mergeResult.stderr.trim() || mergeResult.stdout.trim()}`);
6798
+ }
6799
+ return worktreePath;
6780
6800
  }
6781
- var _internals8 = {
6782
- runCommand,
6783
- now: () => Date.now(),
6784
- mkdirSync: fs4.mkdirSync
6785
- };
6786
- function formatResult(prefix, result) {
6787
- const output = [result.stdout.trim(), result.stderr.trim()].filter(Boolean).join(`
6788
- `);
6789
- const suffix = result.stdoutTruncated || result.stderrTruncated ? `
6790
-
6791
- [output truncated to bounded limit]` : "";
6792
- return output ? `${prefix}
6793
-
6794
- ${output}${suffix}` : `${prefix}${suffix}`;
6801
+ async function cleanupWorktree(worktreePath, projectRoot) {
6802
+ const removeResult = await runGit2(["worktree", "remove", "--force", worktreePath], projectRoot);
6803
+ try {
6804
+ if (_internals8.fs.existsSync(worktreePath)) {
6805
+ _internals8.fs.rmSync(worktreePath, { recursive: true, force: true });
6806
+ }
6807
+ } catch {}
6808
+ if (removeResult.exitCode !== 0) {
6809
+ console.warn(`[ci-simulate] git worktree remove failed: ${removeResult.stderr.trim() || removeResult.stdout.trim()}`);
6810
+ }
6811
+ }
6812
+ async function runValidationSuite(worktreePath) {
6813
+ const steps = [];
6814
+ const commands = [
6815
+ { step: "typecheck", cmd: ["bun", "run", "typecheck"] },
6816
+ { step: "lint", cmd: ["bun", "run", "lint"] },
6817
+ { step: "build", cmd: ["bun", "run", "build"] },
6818
+ { step: "test", cmd: ["bun", "test"] }
6819
+ ];
6820
+ for (const { step, cmd } of commands) {
6821
+ const start = Date.now();
6822
+ const result = await runValidationCommand(cmd, worktreePath);
6823
+ const durationMs = Date.now() - start;
6824
+ steps.push({
6825
+ step,
6826
+ command: cmd.join(" "),
6827
+ exitCode: result.exitCode,
6828
+ stdout: result.stdout,
6829
+ stderr: result.stderr,
6830
+ durationMs,
6831
+ outputTruncated: result.outputTruncated
6832
+ });
6833
+ }
6834
+ return steps;
6835
+ }
6836
+ function formatStepOutput(stdout, stderr, outputTruncated, maxLength = 2000) {
6837
+ let output = stdout;
6838
+ if (stderr) {
6839
+ output += output ? `
6840
+ ${stderr}` : stderr;
6841
+ }
6842
+ if (output.length > maxLength) {
6843
+ output = `${output.slice(0, maxLength)}
6844
+ ... (output truncated)`;
6845
+ }
6846
+ if (outputTruncated) {
6847
+ output = `${output}
6848
+ ... (child output truncated to bounded limit)`;
6849
+ }
6850
+ return output;
6851
+ }
6852
+ function extractFileLineReferences(output) {
6853
+ const lines = [];
6854
+ const patterns = [
6855
+ /([A-Za-z]:[\\/])?[^\s:]+\.(ts|tsx|js|jsx):(\d+):(\d+)/g,
6856
+ /(?:error|Error|FAIL|Failed)[:\s]+([^\s]+\.(ts|tsx|js|jsx)?:?:\d+)/gi,
6857
+ /FAIL\s+([^\s]+\.(test|spec)\.(ts|tsx|js|jsx))/gi
6858
+ ];
6859
+ for (const pattern of patterns) {
6860
+ const matches = Array.from(output.matchAll(pattern));
6861
+ for (const match of matches) {
6862
+ if (match[0]) {
6863
+ lines.push(match[0]);
6864
+ }
6865
+ }
6866
+ }
6867
+ return Array.from(new Set(lines));
6795
6868
  }
6796
6869
  async function handleCiSimulateCommand(directory, args) {
6797
- const unsupportedArg = hasUnsupportedArgs(args);
6798
- if (unsupportedArg) {
6799
- const reason = unsupportedArg.startsWith("--") ? `unsupported argument ${unsupportedArg}` : unsupportedArg;
6800
- return `CI simulation failed: ${reason}. Supported arguments: --base <ref> --head <ref>.`;
6801
- }
6802
- const base = readFlag(args, "--base", DEFAULT_BASE);
6803
- const headFlag = readOptionalFlag(args, "--head");
6804
- const ciCommands = DEFAULT_CI_COMMANDS;
6805
- let head2 = headFlag ?? DEFAULT_HEAD;
6806
- if (!headFlag) {
6807
- const currentHead = await _internals8.runCommand(["git", "-C", directory, "rev-parse", "HEAD"], directory, GIT_TIMEOUT_MS2);
6808
- if (currentHead.exitCode !== 0) {
6809
- return formatResult("CI simulation failed: could not resolve the current worktree HEAD.", currentHead);
6810
- }
6811
- head2 = currentHead.stdout.trim();
6812
- }
6813
- const worktreeBase = path13.join(directory, ".swarm", "ci-simulate");
6814
- const worktreePath = path13.join(worktreeBase, `merge-${_internals8.now()}-${Math.random().toString(36).slice(2)}`);
6815
- _internals8.mkdirSync(worktreeBase, { recursive: true });
6816
- let cleanupError;
6817
- let createdWorktree = false;
6818
- let response;
6819
- try {
6820
- const add = await _internals8.runCommand([
6821
- "git",
6822
- "-C",
6823
- directory,
6824
- "worktree",
6825
- "add",
6826
- "--detach",
6827
- worktreePath,
6828
- base
6829
- ], directory, GIT_TIMEOUT_MS2);
6830
- if (add.exitCode !== 0) {
6831
- response = formatResult(`CI simulation failed: could not create temp worktree from ${base}.`, add);
6832
- } else {
6833
- createdWorktree = true;
6834
- const merge = await _internals8.runCommand(["git", "-C", worktreePath, "merge", "--no-edit", head2], worktreePath, GIT_TIMEOUT_MS2);
6835
- if (merge.exitCode !== 0) {
6836
- response = formatResult(`CI simulation failed: ${head2} does not merge cleanly into ${base}.`, merge);
6837
- } else {
6838
- for (const ciCommand of ciCommands) {
6839
- const ci = await _internals8.runCommand(ciCommand, worktreePath, COMMAND_TIMEOUT_MS);
6840
- if (ci.exitCode !== 0) {
6841
- response = formatResult(`CI simulation failed after merging ${head2} into ${base}: ${ciCommand.join(" ")}`, ci);
6842
- break;
6870
+ const prRef = args[0] ?? await getCurrentBranchOrRef(directory);
6871
+ if (!isSafeGitRef(prRef)) {
6872
+ return "CI simulation failed: PR ref must be a safe git branch or commit reference.";
6873
+ }
6874
+ const lines = [];
6875
+ lines.push(`# CI Simulation Report`);
6876
+ lines.push("");
6877
+ lines.push(`PR ref: **${prRef}**`);
6878
+ lines.push(`Started: ${new Date().toISOString()}`);
6879
+ lines.push("");
6880
+ let worktreePath;
6881
+ const result = {
6882
+ success: false,
6883
+ worktreePath: "",
6884
+ steps: []
6885
+ };
6886
+ try {
6887
+ const baseBranch = _internals8.getDefaultBaseBranch(directory);
6888
+ if (!isSafeGitRef(baseBranch)) {
6889
+ throw new Error("Detected default branch is not a safe git reference.");
6890
+ }
6891
+ lines.push("## Setup");
6892
+ lines.push("");
6893
+ lines.push(`Creating temporary worktree from ${baseBranch}...`);
6894
+ worktreePath = await setupWorktree(directory, prRef, baseBranch, (createdPath) => {
6895
+ worktreePath = createdPath;
6896
+ });
6897
+ result.worktreePath = worktreePath;
6898
+ lines.push(`Worktree: \`${worktreePath}\``);
6899
+ lines.push("");
6900
+ const mergeCheckResult = await runGit2(["log", "--oneline", "-1", "--format=%s"], worktreePath);
6901
+ const lastCommit = mergeCheckResult.stdout.trim();
6902
+ lines.push(`Last commit in worktree: \`${lastCommit}\``);
6903
+ lines.push("");
6904
+ lines.push("## Validation Suite");
6905
+ lines.push("");
6906
+ result.steps = await runValidationSuite(worktreePath);
6907
+ for (const step of result.steps) {
6908
+ const status = step.exitCode === 0 ? "\u2705 PASS" : "\u274C FAIL";
6909
+ lines.push(`### ${status}: ${step.step}`);
6910
+ lines.push("");
6911
+ lines.push(`Command: \`${step.command}\``);
6912
+ lines.push(`Duration: ${(step.durationMs / 1000).toFixed(1)}s`);
6913
+ if (step.exitCode !== 0) {
6914
+ lines.push(`Exit code: ${step.exitCode}`);
6915
+ const fileRefs = extractFileLineReferences(`${step.stdout}
6916
+ ${step.stderr}`);
6917
+ if (fileRefs.length > 0) {
6918
+ lines.push("");
6919
+ lines.push("**Failure locations:**");
6920
+ for (const ref of fileRefs.slice(0, 20)) {
6921
+ lines.push(` - \`${ref}\``);
6843
6922
  }
6844
6923
  }
6845
- response ??= `CI simulation passed after merging ${head2} into ${base}: ${ciCommands.map((cmd) => cmd.join(" ")).join(" && ")}`;
6924
+ lines.push("");
6925
+ lines.push("**Output:**");
6926
+ lines.push("```");
6927
+ lines.push(formatStepOutput(step.stdout, step.stderr, step.outputTruncated));
6928
+ lines.push("```");
6846
6929
  }
6930
+ lines.push("");
6847
6931
  }
6848
- } finally {
6849
- if (createdWorktree) {
6850
- const remove = await _internals8.runCommand(["git", "-C", directory, "worktree", "remove", "--force", worktreePath], directory, GIT_TIMEOUT_MS2);
6851
- if (remove.exitCode !== 0) {
6852
- cleanupError = remove.stderr.trim() || remove.stdout.trim();
6932
+ const allPassed = result.steps.every((s) => s.exitCode === 0);
6933
+ result.success = allPassed;
6934
+ lines.push("## Summary");
6935
+ lines.push("");
6936
+ const passed = result.steps.filter((s) => s.exitCode === 0).length;
6937
+ const failed = result.steps.filter((s) => s.exitCode !== 0).length;
6938
+ lines.push(`Validation: ${passed}/${result.steps.length} steps passed, ${failed} failed`);
6939
+ lines.push("");
6940
+ if (allPassed) {
6941
+ lines.push("\u2705 **All checks passed \u2014 CI simulation succeeded**");
6942
+ } else {
6943
+ lines.push(`\u274C **CI simulation failed \u2014 these failures would cause a merge-queue kick-out**`);
6944
+ lines.push("");
6945
+ lines.push("To reproduce locally, run in the worktree:");
6946
+ lines.push(`\`\`\`bash`);
6947
+ lines.push(`cd "${worktreePath}"`);
6948
+ for (const step of result.steps.filter((s) => s.exitCode !== 0)) {
6949
+ lines.push(`# ${step.step}: ${step.command}`);
6853
6950
  }
6951
+ lines.push(`\`\`\``);
6952
+ }
6953
+ } catch (err) {
6954
+ const errMsg = err instanceof Error ? err.message : String(err);
6955
+ result.error = errMsg;
6956
+ lines.push("");
6957
+ lines.push("## Error");
6958
+ lines.push("");
6959
+ lines.push(`\`\`\``);
6960
+ lines.push(errMsg);
6961
+ lines.push(`\`\`\``);
6962
+ } finally {
6963
+ if (worktreePath) {
6964
+ lines.push("");
6965
+ lines.push("---");
6966
+ lines.push("");
6967
+ lines.push("*Cleaning up temporary worktree...*");
6968
+ await cleanupWorktree(worktreePath, directory);
6969
+ lines.push(`Worktree removed: \`${worktreePath}\``);
6854
6970
  }
6855
- await _internals8.runCommand(["git", "-C", directory, "worktree", "prune"], directory, GIT_TIMEOUT_MS2);
6856
- }
6857
- if (cleanupError) {
6858
- const cleanupMessage = `CI simulation cleanup failed: ${cleanupError}`;
6859
- return response ? `${response}
6860
-
6861
- ${cleanupMessage}` : cleanupMessage;
6862
6971
  }
6863
- return response ?? "CI simulation failed: no result was produced.";
6972
+ return lines.join(`
6973
+ `);
6864
6974
  }
6865
6975
 
6866
6976
  // src/commands/clarify.ts
@@ -6879,7 +6989,7 @@ import { promises as fs10 } from "fs";
6879
6989
  import path30 from "path";
6880
6990
 
6881
6991
  // src/hooks/curator-postmortem.ts
6882
- import { existsSync as existsSync10, readdirSync as readdirSync2, readFileSync as readFileSync6 } from "fs";
6992
+ import { existsSync as existsSync11, readdirSync as readdirSync2, readFileSync as readFileSync6 } from "fs";
6883
6993
  import * as path18 from "path";
6884
6994
 
6885
6995
  // src/hooks/curator.ts
@@ -7298,8 +7408,8 @@ import { readFile as readFile5, rename as rename4, writeFile as writeFile5 } fro
7298
7408
 
7299
7409
  // src/services/skill-improver-quota.ts
7300
7410
  var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
7301
- import { existsSync as existsSync7 } from "fs";
7302
- import { mkdir as mkdir4, readFile as readFile4, rename as rename3, writeFile as writeFile4 } from "fs/promises";
7411
+ import { existsSync as existsSync8 } from "fs";
7412
+ import { mkdir as mkdir5, readFile as readFile4, rename as rename3, writeFile as writeFile4 } from "fs/promises";
7303
7413
  import * as path14 from "path";
7304
7414
  var LOCK_ACQUIRE_TIMEOUT_MS = 1e4;
7305
7415
  var LOCK_RETRY_OPTS = {
@@ -7341,7 +7451,7 @@ function todayKey(window, now = new Date) {
7341
7451
  return `${yr}-${m}-${d}`;
7342
7452
  }
7343
7453
  async function readState(filePath) {
7344
- if (!existsSync7(filePath))
7454
+ if (!existsSync8(filePath))
7345
7455
  return null;
7346
7456
  try {
7347
7457
  const raw = await readFile4(filePath, "utf-8");
@@ -7355,7 +7465,7 @@ async function readState(filePath) {
7355
7465
  }
7356
7466
  }
7357
7467
  async function writeState(filePath, state) {
7358
- await mkdir4(path14.dirname(filePath), { recursive: true });
7468
+ await mkdir5(path14.dirname(filePath), { recursive: true });
7359
7469
  const tmp = `${filePath}.tmp-${process.pid}`;
7360
7470
  await writeFile4(tmp, JSON.stringify(state, null, 2), "utf-8");
7361
7471
  await rename3(tmp, filePath);
@@ -7378,7 +7488,7 @@ async function getQuotaState(directory, opts) {
7378
7488
  }
7379
7489
  async function reserveQuota(directory, opts) {
7380
7490
  const filePath = resolveQuotaPath(directory, opts.scope);
7381
- await mkdir4(path14.dirname(filePath), { recursive: true });
7491
+ await mkdir5(path14.dirname(filePath), { recursive: true });
7382
7492
  let release = null;
7383
7493
  try {
7384
7494
  release = await acquireLock(path14.dirname(filePath));
@@ -7408,7 +7518,7 @@ async function reserveQuota(directory, opts) {
7408
7518
  }
7409
7519
  async function releaseQuota(directory, opts) {
7410
7520
  const filePath = resolveQuotaPath(directory, opts.scope);
7411
- await mkdir4(path14.dirname(filePath), { recursive: true });
7521
+ await mkdir5(path14.dirname(filePath), { recursive: true });
7412
7522
  let release = null;
7413
7523
  try {
7414
7524
  release = await acquireLock(path14.dirname(filePath));
@@ -9087,7 +9197,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
9087
9197
  }
9088
9198
  if (config.skill_generation_enabled === true && skillCandidates.length > 0) {
9089
9199
  try {
9090
- const skillModule = await import("./skill-generator-5rsjmmfq.js");
9200
+ const skillModule = await import("./skill-generator-2tsqqaa2.js");
9091
9201
  for (const cand of skillCandidates) {
9092
9202
  if (cand.confidence < (config.min_skill_confidence ?? DEFAULT_SKILL_MIN_CONFIDENCE)) {
9093
9203
  continue;
@@ -9368,7 +9478,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
9368
9478
  } catch {}
9369
9479
  }
9370
9480
  if (contradictedEntries.length > 0 && knowledgeConfig.contradiction_threshold_action === "quarantine") {
9371
- const { maybeQuarantineOnContradiction } = await import("./knowledge-escalator-0dkkenp2.js");
9481
+ const { maybeQuarantineOnContradiction } = await import("./knowledge-escalator-t1e2211j.js");
9372
9482
  for (const { id } of contradictedEntries) {
9373
9483
  try {
9374
9484
  await maybeQuarantineOnContradiction(directory, id, knowledgeConfig.contradiction_quarantine_threshold, knowledgeConfig.contradiction_quarantine_window_days);
@@ -9872,7 +9982,7 @@ async function repairPostMortemActions(llmOutput, diagnostics, options) {
9872
9982
  }
9873
9983
  function readJsonlFile(filePath, maxLines) {
9874
9984
  try {
9875
- if (!existsSync10(filePath))
9985
+ if (!existsSync11(filePath))
9876
9986
  return [];
9877
9987
  const content = readFileSync6(filePath, "utf-8");
9878
9988
  const results = [];
@@ -9896,12 +10006,12 @@ function collectRetrospectives(directory) {
9896
10006
  const results = [];
9897
10007
  const evidenceDir = path18.join(directory, ".swarm", "evidence");
9898
10008
  try {
9899
- if (!existsSync10(evidenceDir))
10009
+ if (!existsSync11(evidenceDir))
9900
10010
  return results;
9901
10011
  const retroDirs = readdirSync2(evidenceDir, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name.startsWith("retro-")).slice(0, MAX_RETROSPECTIVES);
9902
10012
  for (const entry of retroDirs) {
9903
10013
  const retroPath = path18.join(evidenceDir, entry.name, "evidence.json");
9904
- if (existsSync10(retroPath)) {
10014
+ if (existsSync11(retroPath)) {
9905
10015
  try {
9906
10016
  results.push(readFileSync6(retroPath, "utf-8"));
9907
10017
  } catch {}
@@ -9921,7 +10031,7 @@ async function collectDriftReports(directory) {
9921
10031
  function collectPendingProposals(directory) {
9922
10032
  const results = [];
9923
10033
  const insightPath = path18.join(directory, ".swarm", "insight-candidates.jsonl");
9924
- if (existsSync10(insightPath)) {
10034
+ if (existsSync11(insightPath)) {
9925
10035
  try {
9926
10036
  results.push({
9927
10037
  source: "insight-candidates",
@@ -9931,7 +10041,7 @@ function collectPendingProposals(directory) {
9931
10041
  }
9932
10042
  const proposalsDir = path18.join(directory, ".swarm", "skills", "proposals");
9933
10043
  try {
9934
- if (existsSync10(proposalsDir)) {
10044
+ if (existsSync11(proposalsDir)) {
9935
10045
  const proposalFiles = readdirSync2(proposalsDir).filter((e) => e.endsWith(".md") || e.endsWith(".json")).slice(0, MAX_PROPOSALS);
9936
10046
  for (const entry of proposalFiles) {
9937
10047
  try {
@@ -9947,7 +10057,7 @@ function collectPendingProposals(directory) {
9947
10057
  }
9948
10058
  function isReportValid(reportPath) {
9949
10059
  try {
9950
- if (!existsSync10(reportPath))
10060
+ if (!existsSync11(reportPath))
9951
10061
  return false;
9952
10062
  const content = readFileSync6(reportPath, "utf-8").trim();
9953
10063
  if (content.length === 0)
@@ -10270,8 +10380,8 @@ ${actionSummary}`;
10270
10380
  reportContent = _internals12.buildDataOnlyReport(effectivePlanId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports, { scope, sessionID: options.sessionID, planLoaded });
10271
10381
  }
10272
10382
  try {
10273
- const { mkdirSync: mkdirSync9 } = await import("fs");
10274
- mkdirSync9(path18.dirname(reportPath), { recursive: true });
10383
+ const { mkdirSync: mkdirSync8 } = await import("fs");
10384
+ mkdirSync8(path18.dirname(reportPath), { recursive: true });
10275
10385
  await atomicWriteFile(reportPath, reportContent);
10276
10386
  } catch (err) {
10277
10387
  const msg = err instanceof Error ? err.message : String(err);
@@ -10325,15 +10435,15 @@ var _internals12 = {
10325
10435
  verifyPostMortemKnowledgeActions,
10326
10436
  repairPostMortemActions,
10327
10437
  loadDefaultKnowledgeConfig: async () => {
10328
- const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-s48je8zt.js");
10438
+ const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-2p15yrvn.js");
10329
10439
  return KnowledgeConfigSchema2.parse({});
10330
10440
  },
10331
10441
  applyCuratorKnowledgeUpdates: async (directory, recommendations, knowledgeConfig) => {
10332
- const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-2hm297yd.js");
10442
+ const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-j7ty8k6t.js");
10333
10443
  return applyCuratorKnowledgeUpdates2(directory, recommendations, knowledgeConfig);
10334
10444
  },
10335
10445
  checkHivePromotions: async (entries, knowledgeConfig) => {
10336
- const { checkHivePromotions } = await import("./hive-promoter-0f8xh2rn.js");
10446
+ const { checkHivePromotions } = await import("./hive-promoter-y179n7wx.js");
10337
10447
  return checkHivePromotions(entries, knowledgeConfig);
10338
10448
  },
10339
10449
  applyProposalTriage: async (directory, triage) => {
@@ -10342,7 +10452,7 @@ var _internals12 = {
10342
10452
  activateProposal,
10343
10453
  listSkills: listSkills2,
10344
10454
  sanitizeSlug
10345
- } = await import("./skill-generator-5rsjmmfq.js");
10455
+ } = await import("./skill-generator-2tsqqaa2.js");
10346
10456
  const result = {
10347
10457
  approved: [],
10348
10458
  rejected: [],
@@ -10384,7 +10494,7 @@ var _internals12 = {
10384
10494
  return result;
10385
10495
  },
10386
10496
  readPriorDriftReports: async (directory) => {
10387
- const { readPriorDriftReports } = await import("./curator-drift-169wgaxn.js");
10497
+ const { readPriorDriftReports } = await import("./curator-drift-jvs1v6em.js");
10388
10498
  return readPriorDriftReports(directory);
10389
10499
  },
10390
10500
  readSwarmKnowledge: (directory) => readKnowledge(resolveSwarmKnowledgePath(directory))
@@ -10673,14 +10783,14 @@ async function promoteFromSwarm(directory, lessonId) {
10673
10783
 
10674
10784
  // src/hooks/knowledge-curator.ts
10675
10785
  import { createHash as createHash4 } from "crypto";
10676
- import { existsSync as existsSync13 } from "fs";
10677
- import { appendFile as appendFile2, mkdir as mkdir6, readFile as readFile8, writeFile as writeFile8 } from "fs/promises";
10786
+ import { existsSync as existsSync14 } from "fs";
10787
+ import { appendFile as appendFile2, mkdir as mkdir7, readFile as readFile8, writeFile as writeFile8 } from "fs/promises";
10678
10788
  import * as path24 from "path";
10679
10789
 
10680
10790
  // src/services/synonym-map.ts
10681
10791
  var import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
10682
10792
  import {
10683
- mkdir as mkdir5,
10793
+ mkdir as mkdir6,
10684
10794
  readFile as readFile6,
10685
10795
  rename as rename5,
10686
10796
  stat as stat3,
@@ -10842,7 +10952,7 @@ async function readSynonymMap(directory, maxPairs = DEFAULT_MAX_PAIRS) {
10842
10952
  }
10843
10953
  }
10844
10954
  async function writeSynonymMapAtomic(filePath, map) {
10845
- await mkdir5(path20.dirname(filePath), { recursive: true });
10955
+ await mkdir6(path20.dirname(filePath), { recursive: true });
10846
10956
  const tmp = `${filePath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
10847
10957
  try {
10848
10958
  await writeFile6(tmp, JSON.stringify(map, null, 2), "utf-8");
@@ -10856,7 +10966,7 @@ async function writeSynonymMapAtomic(filePath, map) {
10856
10966
  async function rebuildSynonymMap(directory, entries, maxPairs = DEFAULT_MAX_PAIRS) {
10857
10967
  const filePath = resolveSynonymMapPath(directory);
10858
10968
  const dir = path20.dirname(filePath);
10859
- await mkdir5(dir, { recursive: true });
10969
+ await mkdir6(dir, { recursive: true });
10860
10970
  let release = null;
10861
10971
  try {
10862
10972
  release = await import_proper_lockfile2.default.lock(dir, {
@@ -10913,7 +11023,7 @@ function reinforceSwarmKnowledgeEntry(entry, confirmation) {
10913
11023
  }
10914
11024
 
10915
11025
  // src/hooks/micro-reflector.ts
10916
- import { existsSync as existsSync12 } from "fs";
11026
+ import { existsSync as existsSync13 } from "fs";
10917
11027
  import { readFile as readFile7, writeFile as writeFile7 } from "fs/promises";
10918
11028
  import * as path23 from "path";
10919
11029
  init_logger();
@@ -11948,7 +12058,7 @@ async function readTaskTrajectory(directory, taskId) {
11948
12058
  try {
11949
12059
  const rel = path23.join("evidence", sanitizeTaskId(taskId), "trajectory.jsonl");
11950
12060
  const filePath = validateSwarmPath(directory, rel);
11951
- if (!existsSync12(filePath))
12061
+ if (!existsSync13(filePath))
11952
12062
  return [];
11953
12063
  const content = await readFile7(filePath, "utf-8");
11954
12064
  const out = [];
@@ -12377,7 +12487,7 @@ RETRY: your last output was missing ${result.missing.join("; ")}; produce valid
12377
12487
  async function appendCuratorSkippedEvent(directory, record) {
12378
12488
  try {
12379
12489
  const filePath = path24.join(directory, ".swarm", "events.jsonl");
12380
- await mkdir6(path24.dirname(filePath), { recursive: true });
12490
+ await mkdir7(path24.dirname(filePath), { recursive: true });
12381
12491
  await appendFile2(filePath, `${JSON.stringify({
12382
12492
  timestamp: new Date().toISOString(),
12383
12493
  event: "curator_skipped",
@@ -12417,7 +12527,7 @@ function readInsightJsonl(content) {
12417
12527
  async function consumeInsightCandidates(directory, batchLimit = MESO_INSIGHT_BATCH_LIMIT) {
12418
12528
  try {
12419
12529
  const filePath = resolveInsightCandidatesPath(directory);
12420
- if (!existsSync13(filePath))
12530
+ if (!existsSync14(filePath))
12421
12531
  return [];
12422
12532
  const consumed = [];
12423
12533
  await transactFile(filePath, async (p) => readInsightJsonl(await readFile8(p, "utf-8").catch(() => "")), async (p, data) => {
@@ -13342,13 +13452,13 @@ async function writeSessionReflection(directory, result) {
13342
13452
  }
13343
13453
 
13344
13454
  // src/services/skill-improver.ts
13345
- import { existsSync as existsSync15 } from "fs";
13346
- import { mkdir as mkdir8, readFile as readFile9, rename as rename6, writeFile as writeFile10 } from "fs/promises";
13455
+ import { existsSync as existsSync16 } from "fs";
13456
+ import { mkdir as mkdir9, readFile as readFile9, rename as rename6, writeFile as writeFile10 } from "fs/promises";
13347
13457
  import * as path27 from "path";
13348
13458
  init_logger();
13349
13459
 
13350
13460
  // src/services/trajectory-cluster.ts
13351
- import { mkdir as mkdir7, writeFile as writeFile9 } from "fs/promises";
13461
+ import { mkdir as mkdir8, writeFile as writeFile9 } from "fs/promises";
13352
13462
  import * as path26 from "path";
13353
13463
  init_logger();
13354
13464
  var MACRO_TRAJECTORY_WINDOW = 200;
@@ -13482,7 +13592,7 @@ async function writeMotifProposals(directory, opts = {}) {
13482
13592
  return result;
13483
13593
  const max = opts.maxProposals ?? 10;
13484
13594
  const proposalsDir = validateSwarmPath(directory, path26.join("skills", "proposals"));
13485
- await mkdir7(proposalsDir, { recursive: true });
13595
+ await mkdir8(proposalsDir, { recursive: true });
13486
13596
  for (const motif of motifs.slice(0, max)) {
13487
13597
  const slug = `motif-${slugify(motif.signature)}`;
13488
13598
  const filePath = path26.join(proposalsDir, `${slug}.md`);
@@ -13627,7 +13737,7 @@ async function writeSuccessMotifProposals(directory, opts = {}) {
13627
13737
  return result;
13628
13738
  const max = opts.maxProposals ?? 10;
13629
13739
  const proposalsDir = validateSwarmPath(directory, path26.join("skills", "proposals"));
13630
- await mkdir7(proposalsDir, { recursive: true });
13740
+ await mkdir8(proposalsDir, { recursive: true });
13631
13741
  for (const motif of motifs.slice(0, max)) {
13632
13742
  const slug = workflowSlug(motif.signature);
13633
13743
  const filePath = path26.join(proposalsDir, `${slug}.md`);
@@ -13642,14 +13752,14 @@ async function writeSuccessMotifProposals(directory, opts = {}) {
13642
13752
  }
13643
13753
 
13644
13754
  // src/services/unactionable-hardening.ts
13645
- import { existsSync as existsSync14 } from "fs";
13755
+ import { existsSync as existsSync15 } from "fs";
13646
13756
  init_logger();
13647
13757
  var HARDENING_BATCH_LIMIT = 5;
13648
13758
  async function hardenUnactionableEntries(params) {
13649
13759
  const result = { hardened: 0, retired: 0, remaining: 0 };
13650
13760
  try {
13651
13761
  const queuePath = resolveUnactionablePath(params.directory);
13652
- if (!existsSync14(queuePath))
13762
+ if (!existsSync15(queuePath))
13653
13763
  return result;
13654
13764
  const limit = params.batchLimit ?? HARDENING_BATCH_LIMIT;
13655
13765
  const dedupThreshold = params.dedupThreshold ?? 0.6;
@@ -13753,7 +13863,7 @@ function timestampSlug(d) {
13753
13863
  return d.toISOString().replace(/[:.]/g, "-");
13754
13864
  }
13755
13865
  async function atomicWrite(p, content) {
13756
- await mkdir8(path27.dirname(p), { recursive: true });
13866
+ await mkdir9(path27.dirname(p), { recursive: true });
13757
13867
  const tmp = `${p}.tmp-${process.pid}-${Date.now()}`;
13758
13868
  await writeFile10(tmp, content, "utf-8");
13759
13869
  await rename6(tmp, p);
@@ -13761,7 +13871,7 @@ async function atomicWrite(p, content) {
13761
13871
  async function gatherInventory(directory) {
13762
13872
  const swarm = await readKnowledge(resolveSwarmKnowledgePath(directory));
13763
13873
  const hivePath = resolveHiveKnowledgePath();
13764
- const hive = existsSync15(hivePath) ? await readKnowledge(hivePath) : [];
13874
+ const hive = existsSync16(hivePath) ? await readKnowledge(hivePath) : [];
13765
13875
  const archived = [...swarm, ...hive].filter((e) => e.status === "archived").length;
13766
13876
  const skills = await listSkills(directory);
13767
13877
  const knowledgeById = new Map([...swarm, ...hive].map((entry) => [entry.id, entry]));
@@ -14226,7 +14336,7 @@ var _internals17 = {
14226
14336
  };
14227
14337
 
14228
14338
  // src/session/session-start-store.ts
14229
- import { existsSync as existsSync16, mkdirSync as mkdirSync10, readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "fs";
14339
+ import { existsSync as existsSync17, mkdirSync as mkdirSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "fs";
14230
14340
  import * as path28 from "path";
14231
14341
  var SESSION_START_FILE = "session-start.jsonl";
14232
14342
  function recordSessionStart(directory, startMs) {
@@ -14235,7 +14345,7 @@ function recordSessionStart(directory, startMs) {
14235
14345
  const sessionDir = path28.join(swarmDir, "session");
14236
14346
  const filePath = path28.join(sessionDir, SESSION_START_FILE);
14237
14347
  const line = JSON.stringify({ startMs, ts: Date.now() });
14238
- mkdirSync10(sessionDir, { recursive: true });
14348
+ mkdirSync9(sessionDir, { recursive: true });
14239
14349
  writeFileSync4(filePath, `${line}
14240
14350
  `, { flag: "a" });
14241
14351
  } catch {}
@@ -14243,7 +14353,7 @@ function recordSessionStart(directory, startMs) {
14243
14353
  function readEarliestSessionStart(directory) {
14244
14354
  try {
14245
14355
  const filePath = path28.join(directory, ".swarm", "session", SESSION_START_FILE);
14246
- if (!existsSync16(filePath))
14356
+ if (!existsSync17(filePath))
14247
14357
  return null;
14248
14358
  const content = readFileSync8(filePath, "utf-8");
14249
14359
  const lines = content.split(`
@@ -14268,7 +14378,7 @@ function readEarliestSessionStart(directory) {
14268
14378
  }
14269
14379
 
14270
14380
  // src/tools/write-retro.ts
14271
- import { existsSync as existsSync17 } from "fs";
14381
+ import { existsSync as existsSync18 } from "fs";
14272
14382
  import path29 from "path";
14273
14383
  async function executeWriteRetro(args, directory) {
14274
14384
  if (/^(CON|PRN|AUX|NUL|COM[0-9]|LPT[0-9])(:|$)/i.test(directory)) {
@@ -14277,7 +14387,7 @@ async function executeWriteRetro(args, directory) {
14277
14387
  message: "Invalid directory: reserved device name"
14278
14388
  }, null, 2);
14279
14389
  }
14280
- if (!existsSync17(path29.join(directory, ".swarm"))) {
14390
+ if (!existsSync18(path29.join(directory, ".swarm"))) {
14281
14391
  return JSON.stringify({
14282
14392
  success: false,
14283
14393
  message: `Cannot write evidence in "${directory}" \u2014 no .swarm/ folder was found. Run write_retro from an initialized project root.`
@@ -15042,7 +15152,7 @@ async function runFinalizeStage(ctx) {
15042
15152
  }
15043
15153
  }
15044
15154
  try {
15045
- const { CuratorConfigSchema: CCS } = await import("./schema-s48je8zt.js");
15155
+ const { CuratorConfigSchema: CCS } = await import("./schema-2p15yrvn.js");
15046
15156
  const { config: pmLoadedConfig } = _internals19.loadPluginConfigWithMeta(ctx.directory);
15047
15157
  const curatorCfg = CCS.parse(pmLoadedConfig.curator ?? {});
15048
15158
  if (curatorCfg.enabled && curatorCfg.postmortem_enabled) {
@@ -16021,10 +16131,10 @@ function buildStatusMessage(session, plan) {
16021
16131
  }
16022
16132
 
16023
16133
  // src/commands/config.ts
16024
- import * as os5 from "os";
16134
+ import * as os6 from "os";
16025
16135
  import * as path31 from "path";
16026
16136
  function getUserConfigDir2() {
16027
- return process.env.XDG_CONFIG_HOME || path31.join(os5.homedir(), ".config");
16137
+ return process.env.XDG_CONFIG_HOME || path31.join(os6.homedir(), ".config");
16028
16138
  }
16029
16139
  async function handleConfigCommand(directory, _args) {
16030
16140
  const config = loadPluginConfig(directory);
@@ -16047,8 +16157,8 @@ async function handleConfigCommand(directory, _args) {
16047
16157
  }
16048
16158
 
16049
16159
  // src/services/skill-consolidation.ts
16050
- import { existsSync as existsSync19 } from "fs";
16051
- import { mkdir as mkdir9, readFile as readFile10, rename as rename7, writeFile as writeFile11 } from "fs/promises";
16160
+ import { existsSync as existsSync20 } from "fs";
16161
+ import { mkdir as mkdir10, readFile as readFile10, rename as rename7, writeFile as writeFile11 } from "fs/promises";
16052
16162
  import * as path32 from "path";
16053
16163
 
16054
16164
  // src/utils/timeout.ts
@@ -16078,7 +16188,7 @@ function consolidationStatePath(directory) {
16078
16188
  }
16079
16189
  async function readState2(directory) {
16080
16190
  const filePath = consolidationStatePath(directory);
16081
- if (!existsSync19(filePath))
16191
+ if (!existsSync20(filePath))
16082
16192
  return {};
16083
16193
  try {
16084
16194
  const parsed = JSON.parse(await readFile10(filePath, "utf-8"));
@@ -16090,7 +16200,7 @@ async function readState2(directory) {
16090
16200
  }
16091
16201
  }
16092
16202
  async function atomicWrite2(filePath, content) {
16093
- await mkdir9(path32.dirname(filePath), { recursive: true });
16203
+ await mkdir10(path32.dirname(filePath), { recursive: true });
16094
16204
  const tmp = `${filePath}.tmp-${process.pid}-${Date.now()}`;
16095
16205
  await writeFile11(tmp, content, "utf-8");
16096
16206
  await rename7(tmp, filePath);
@@ -17155,9 +17265,9 @@ var _internals23 = {
17155
17265
  readSwarmFileAsync,
17156
17266
  loadCuratorDeps: async () => {
17157
17267
  const [{ CuratorConfigSchema }, curator, { createCuratorLLMDelegate: createCuratorLLMDelegate2 }] = await Promise.all([
17158
- import("./schema-s48je8zt.js"),
17159
- import("./curator-2hm297yd.js"),
17160
- import("./curator-llm-factory-19s0r5v6.js")
17268
+ import("./schema-2p15yrvn.js"),
17269
+ import("./curator-j7ty8k6t.js"),
17270
+ import("./curator-llm-factory-8rnk2083.js")
17161
17271
  ]);
17162
17272
  return { CuratorConfigSchema, curator, createCuratorLLMDelegate: createCuratorLLMDelegate2 };
17163
17273
  }
@@ -17647,13 +17757,13 @@ ${USAGE5}`;
17647
17757
 
17648
17758
  // src/services/diagnose-service.ts
17649
17759
  import * as child_process5 from "child_process";
17650
- import { existsSync as existsSync22, readdirSync as readdirSync4, readFileSync as readFileSync10, statSync as statSync6 } from "fs";
17760
+ import { existsSync as existsSync23, readdirSync as readdirSync4, readFileSync as readFileSync10, statSync as statSync6 } from "fs";
17651
17761
  import * as path37 from "path";
17652
17762
  import { fileURLToPath } from "url";
17653
17763
  // package.json
17654
17764
  var package_default = {
17655
17765
  name: "opencode-swarm",
17656
- version: "7.111.0",
17766
+ version: "7.112.0",
17657
17767
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
17658
17768
  main: "dist/index.js",
17659
17769
  types: "dist/index.d.ts",
@@ -17722,11 +17832,13 @@ var package_default = {
17722
17832
  ".opencode/skills/running-tests",
17723
17833
  ".opencode/skills/engineering-conventions",
17724
17834
  ".opencode/skills/commit-pr",
17725
- ".opencode/skills/worktree-retry-cleanup",
17726
- ".opencode/skills/skill-edit-validation",
17727
- ".opencode/skills/merge-queue-readiness",
17728
- ".opencode/skills/gate-attribution",
17729
17835
  ".opencode/skills/ci-failure-batching",
17836
+ ".opencode/skills/gate-attribution",
17837
+ ".opencode/skills/merge-queue-readiness",
17838
+ ".opencode/skills/skill-edit-validation",
17839
+ ".opencode/skills/swarm",
17840
+ ".opencode/skills/swarm-ci-monitor",
17841
+ ".opencode/skills/worktree-retry-cleanup",
17730
17842
  "tests/fixtures/memory-recall",
17731
17843
  "README.md",
17732
17844
  "LICENSE"
@@ -17770,13 +17882,13 @@ var package_default = {
17770
17882
  };
17771
17883
 
17772
17884
  // src/config/cache-paths.ts
17773
- import * as os6 from "os";
17885
+ import * as os7 from "os";
17774
17886
  import * as path36 from "path";
17775
17887
  function getPluginConfigDir() {
17776
- return path36.join(process.env.XDG_CONFIG_HOME || path36.join(os6.homedir(), ".config"), "opencode");
17888
+ return path36.join(process.env.XDG_CONFIG_HOME || path36.join(os7.homedir(), ".config"), "opencode");
17777
17889
  }
17778
17890
  function getPluginCachePaths() {
17779
- const cacheBase = process.env.XDG_CACHE_HOME || path36.join(os6.homedir(), ".cache");
17891
+ const cacheBase = process.env.XDG_CACHE_HOME || path36.join(os7.homedir(), ".cache");
17780
17892
  const configDir = getPluginConfigDir();
17781
17893
  const paths = [
17782
17894
  path36.join(cacheBase, "opencode", "node_modules", "opencode-swarm"),
@@ -17784,18 +17896,18 @@ function getPluginCachePaths() {
17784
17896
  path36.join(configDir, "node_modules", "opencode-swarm")
17785
17897
  ];
17786
17898
  if (process.platform === "darwin") {
17787
- const libCaches = path36.join(os6.homedir(), "Library", "Caches");
17899
+ const libCaches = path36.join(os7.homedir(), "Library", "Caches");
17788
17900
  paths.push(path36.join(libCaches, "opencode", "node_modules", "opencode-swarm"), path36.join(libCaches, "opencode", "packages", "opencode-swarm@latest"));
17789
17901
  }
17790
17902
  if (process.platform === "win32") {
17791
- const localAppData = process.env.LOCALAPPDATA || path36.join(os6.homedir(), "AppData", "Local");
17792
- const appData = process.env.APPDATA || path36.join(os6.homedir(), "AppData", "Roaming");
17903
+ const localAppData = process.env.LOCALAPPDATA || path36.join(os7.homedir(), "AppData", "Local");
17904
+ const appData = process.env.APPDATA || path36.join(os7.homedir(), "AppData", "Roaming");
17793
17905
  paths.push(path36.join(localAppData, "opencode", "node_modules", "opencode-swarm"), path36.join(localAppData, "opencode", "packages", "opencode-swarm@latest"), path36.join(appData, "opencode", "node_modules", "opencode-swarm"));
17794
17906
  }
17795
17907
  return paths;
17796
17908
  }
17797
17909
  function getPluginLockFilePaths() {
17798
- const cacheBase = process.env.XDG_CACHE_HOME || path36.join(os6.homedir(), ".cache");
17910
+ const cacheBase = process.env.XDG_CACHE_HOME || path36.join(os7.homedir(), ".cache");
17799
17911
  const configDir = getPluginConfigDir();
17800
17912
  const paths = [
17801
17913
  path36.join(cacheBase, "opencode", "bun.lock"),
@@ -17803,11 +17915,11 @@ function getPluginLockFilePaths() {
17803
17915
  path36.join(configDir, "package-lock.json")
17804
17916
  ];
17805
17917
  if (process.platform === "darwin") {
17806
- const libCaches = path36.join(os6.homedir(), "Library", "Caches");
17918
+ const libCaches = path36.join(os7.homedir(), "Library", "Caches");
17807
17919
  paths.push(path36.join(libCaches, "opencode", "bun.lock"), path36.join(libCaches, "opencode", "bun.lockb"));
17808
17920
  }
17809
17921
  if (process.platform === "win32") {
17810
- const localAppData = process.env.LOCALAPPDATA || path36.join(os6.homedir(), "AppData", "Local");
17922
+ const localAppData = process.env.LOCALAPPDATA || path36.join(os7.homedir(), "AppData", "Local");
17811
17923
  paths.push(path36.join(localAppData, "opencode", "bun.lock"), path36.join(localAppData, "opencode", "bun.lockb"));
17812
17924
  }
17813
17925
  return paths;
@@ -17818,11 +17930,11 @@ init_capability_probe();
17818
17930
  init_executor();
17819
17931
 
17820
17932
  // src/services/knowledge-diagnostics.ts
17821
- import { existsSync as existsSync21 } from "fs";
17933
+ import { existsSync as existsSync22 } from "fs";
17822
17934
  import { readFile as readFile12 } from "fs/promises";
17823
17935
 
17824
17936
  // src/services/version-check.ts
17825
- import { existsSync as existsSync20, mkdirSync as mkdirSync12, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "fs";
17937
+ import { existsSync as existsSync21, mkdirSync as mkdirSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "fs";
17826
17938
  import { homedir as homedir6 } from "os";
17827
17939
  import { join as join31 } from "path";
17828
17940
  var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
@@ -17839,7 +17951,7 @@ function cacheFile() {
17839
17951
  function readVersionCache() {
17840
17952
  try {
17841
17953
  const path37 = cacheFile();
17842
- if (!existsSync20(path37))
17954
+ if (!existsSync21(path37))
17843
17955
  return null;
17844
17956
  const raw = readFileSync9(path37, "utf-8");
17845
17957
  const parsed = JSON.parse(raw);
@@ -17893,7 +18005,7 @@ var SEVEN_DAYS_MS2 = 7 * 24 * 60 * 60 * 1000;
17893
18005
  var UNACTIONABLE_BACKLOG_WARN = 100;
17894
18006
  var INSIGHT_BACKLOG_WARN = 50;
17895
18007
  async function readRawLines(filePath) {
17896
- if (!existsSync21(filePath))
18008
+ if (!existsSync22(filePath))
17897
18009
  return { entries: [], corrupt: 0 };
17898
18010
  const content = await readFile12(filePath, "utf-8");
17899
18011
  const entries = [];
@@ -18018,7 +18130,7 @@ async function computeKnowledgeDebug(directory) {
18018
18130
  };
18019
18131
  }
18020
18132
  async function safeJsonlCount(filePath) {
18021
- if (!filePath || !existsSync21(filePath))
18133
+ if (!filePath || !existsSync22(filePath))
18022
18134
  return 0;
18023
18135
  try {
18024
18136
  const content = await readFile12(filePath, "utf-8");
@@ -18097,7 +18209,7 @@ var REQUIRED_CACHE_GRAMMAR_ASSETS = [
18097
18209
  ];
18098
18210
  function resolveCachePackageRoot(cachePath) {
18099
18211
  const nestedPackageRoot = path37.join(cachePath, "node_modules", "opencode-swarm");
18100
- return existsSync22(nestedPackageRoot) ? nestedPackageRoot : cachePath;
18212
+ return existsSync23(nestedPackageRoot) ? nestedPackageRoot : cachePath;
18101
18213
  }
18102
18214
  var _internals24 = {
18103
18215
  detectSandboxCapability: () => sandboxCapabilityProbe.detect(),
@@ -18348,7 +18460,7 @@ async function checkConfigBackups(directory) {
18348
18460
  }
18349
18461
  async function checkGitRepository(directory) {
18350
18462
  try {
18351
- if (!existsSync22(directory) || !statSync6(directory).isDirectory()) {
18463
+ if (!existsSync23(directory) || !statSync6(directory).isDirectory()) {
18352
18464
  return {
18353
18465
  name: "Git Repository",
18354
18466
  status: "\u274C",
@@ -18413,7 +18525,7 @@ async function checkSpecStaleness(directory, plan) {
18413
18525
  }
18414
18526
  async function checkConfigParseability(directory) {
18415
18527
  const configPath = path37.join(directory, ".opencode/opencode-swarm.json");
18416
- if (!existsSync22(configPath)) {
18528
+ if (!existsSync23(configPath)) {
18417
18529
  return {
18418
18530
  name: "Config Parseability",
18419
18531
  status: "\u2705",
@@ -18468,11 +18580,11 @@ async function checkGrammarWasmFiles() {
18468
18580
  const thisDir = path37.dirname(fileURLToPath(import.meta.url));
18469
18581
  const grammarDir = resolveGrammarDir(thisDir);
18470
18582
  const missing = [];
18471
- if (!existsSync22(path37.join(grammarDir, "tree-sitter.wasm"))) {
18583
+ if (!existsSync23(path37.join(grammarDir, "tree-sitter.wasm"))) {
18472
18584
  missing.push("tree-sitter.wasm (core runtime)");
18473
18585
  }
18474
18586
  for (const file of grammarFiles) {
18475
- if (!existsSync22(path37.join(grammarDir, file))) {
18587
+ if (!existsSync23(path37.join(grammarDir, file))) {
18476
18588
  missing.push(file);
18477
18589
  }
18478
18590
  }
@@ -18491,7 +18603,7 @@ async function checkGrammarWasmFiles() {
18491
18603
  }
18492
18604
  async function checkCheckpointManifest(directory) {
18493
18605
  const manifestPath = path37.join(directory, ".swarm/checkpoints.json");
18494
- if (!existsSync22(manifestPath)) {
18606
+ if (!existsSync23(manifestPath)) {
18495
18607
  return {
18496
18608
  name: "Checkpoint Manifest",
18497
18609
  status: "\u2705",
@@ -18543,7 +18655,7 @@ async function checkCheckpointManifest(directory) {
18543
18655
  }
18544
18656
  async function checkEventStreamIntegrity(directory) {
18545
18657
  const eventsPath = path37.join(directory, ".swarm/events.jsonl");
18546
- if (!existsSync22(eventsPath)) {
18658
+ if (!existsSync23(eventsPath)) {
18547
18659
  return {
18548
18660
  name: "Event Stream",
18549
18661
  status: "\u2705",
@@ -18584,7 +18696,7 @@ async function checkEventStreamIntegrity(directory) {
18584
18696
  }
18585
18697
  async function checkSteeringDirectives(directory) {
18586
18698
  const eventsPath = path37.join(directory, ".swarm/events.jsonl");
18587
- if (!existsSync22(eventsPath)) {
18699
+ if (!existsSync23(eventsPath)) {
18588
18700
  return {
18589
18701
  name: "Steering Directives",
18590
18702
  status: "\u2705",
@@ -18640,7 +18752,7 @@ async function checkCurator(directory) {
18640
18752
  };
18641
18753
  }
18642
18754
  const summaryPath = path37.join(directory, ".swarm/curator-summary.json");
18643
- if (!existsSync22(summaryPath)) {
18755
+ if (!existsSync23(summaryPath)) {
18644
18756
  return {
18645
18757
  name: "Curator",
18646
18758
  status: "\u2705",
@@ -18842,7 +18954,7 @@ async function getDiagnoseData(directory) {
18842
18954
  checks.push(await checkKnowledgeHealth(directory));
18843
18955
  try {
18844
18956
  const evidenceDir = path37.join(directory, ".swarm", "evidence");
18845
- const snapshotFiles = existsSync22(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
18957
+ const snapshotFiles = existsSync23(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
18846
18958
  if (snapshotFiles.length > 0) {
18847
18959
  const latest = snapshotFiles.sort().pop();
18848
18960
  checks.push({
@@ -18875,13 +18987,13 @@ async function getDiagnoseData(directory) {
18875
18987
  const cacheRows = [];
18876
18988
  for (const cachePath of cachePaths) {
18877
18989
  try {
18878
- if (!existsSync22(cachePath)) {
18990
+ if (!existsSync23(cachePath)) {
18879
18991
  cacheRows.push(`\u2B1C ${cachePath} \u2014 absent`);
18880
18992
  continue;
18881
18993
  }
18882
18994
  const packageRoot = resolveCachePackageRoot(cachePath);
18883
18995
  const cacheLabel = packageRoot === cachePath ? cachePath : `${cachePath} -> ${packageRoot}`;
18884
- const missingGrammarAssets = REQUIRED_CACHE_GRAMMAR_ASSETS.filter((file) => !existsSync22(path37.join(packageRoot, "dist", "lang", "grammars", file)));
18996
+ const missingGrammarAssets = REQUIRED_CACHE_GRAMMAR_ASSETS.filter((file) => !existsSync23(path37.join(packageRoot, "dist", "lang", "grammars", file)));
18885
18997
  const pkgJsonPath = path37.join(packageRoot, "package.json");
18886
18998
  try {
18887
18999
  const raw = readFileSync10(pkgJsonPath, "utf-8");
@@ -19107,7 +19219,7 @@ async function handleDoctorCommand(directory, args) {
19107
19219
  const result = runConfigDoctor(config, directory);
19108
19220
  let output;
19109
19221
  if (enableAutoFix && result.hasAutoFixableIssues) {
19110
- const { runConfigDoctorWithFixes } = await import("./config-doctor-q5e9yzn6.js");
19222
+ const { runConfigDoctorWithFixes } = await import("./config-doctor-mmw4c50z.js");
19111
19223
  const fixResult = await runConfigDoctorWithFixes(directory, config, true);
19112
19224
  output = formatDoctorMarkdown(fixResult.result);
19113
19225
  } else {
@@ -19920,7 +20032,7 @@ async function handleEvidenceCommand(directory, args) {
19920
20032
  return formatTaskEvidenceMarkdown(evidenceData);
19921
20033
  }
19922
20034
  async function handleEvidenceSummaryCommand(directory) {
19923
- const { buildEvidenceSummary } = await import("./evidence-summary-service-8tasw2tt.js");
20035
+ const { buildEvidenceSummary } = await import("./evidence-summary-service-j6fnsfeq.js");
19924
20036
  const artifact = await buildEvidenceSummary(directory);
19925
20037
  if (!artifact) {
19926
20038
  return "No plan found. Run `/swarm plan` to check plan status.";
@@ -20007,7 +20119,8 @@ function emptyCounters() {
20007
20119
  reviewerRejections: 0,
20008
20120
  testFailures: 0,
20009
20121
  oversightChecks: 0,
20010
- consecutiveNoProgressTurns: 0
20122
+ consecutiveNoProgressTurns: 0,
20123
+ consecutiveOversightFailures: 0
20011
20124
  };
20012
20125
  }
20013
20126
  var VALID_RUN_MODES = new Set(["assisted", "supervised", "strict"]);
@@ -20237,6 +20350,11 @@ function startFullAutoRun(directory, sessionID, config, options = {}) {
20237
20350
  denialCounters: {
20238
20351
  consecutive: 0,
20239
20352
  total: existing.denialCounters.total
20353
+ },
20354
+ consecutiveOversightFailures: 0,
20355
+ counters: {
20356
+ ...existing.counters,
20357
+ consecutiveOversightFailures: 0
20240
20358
  }
20241
20359
  } : {
20242
20360
  ...emptyState(sessionID, mode),
@@ -20804,7 +20922,7 @@ var _internals27 = {
20804
20922
  };
20805
20923
 
20806
20924
  // src/session/snapshot-writer.ts
20807
- import { closeSync as closeSync5, fsyncSync as fsyncSync2, mkdirSync as mkdirSync17, openSync as openSync5, renameSync as renameSync8 } from "fs";
20925
+ import { closeSync as closeSync5, fsyncSync as fsyncSync2, mkdirSync as mkdirSync16, openSync as openSync5, renameSync as renameSync8 } from "fs";
20808
20926
  import * as path42 from "path";
20809
20927
  var _writeInFlight = Promise.resolve();
20810
20928
  function serializeAgentSession(s) {
@@ -20919,7 +21037,7 @@ async function writeSnapshot(directory, state) {
20919
21037
  const content = JSON.stringify(snapshot, null, 2);
20920
21038
  const resolvedPath = validateSwarmPath(directory, "session/state.json");
20921
21039
  const dir = path42.dirname(resolvedPath);
20922
- mkdirSync17(dir, { recursive: true });
21040
+ mkdirSync16(dir, { recursive: true });
20923
21041
  const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
20924
21042
  await bunWrite(tempPath, content);
20925
21043
  try {
@@ -21443,9 +21561,9 @@ import { join as join37 } from "path";
21443
21561
  // src/hooks/knowledge-migrator.ts
21444
21562
  init_logger();
21445
21563
  import { randomUUID as randomUUID7 } from "crypto";
21446
- import { existsSync as existsSync27, readFileSync as readFileSync15 } from "fs";
21447
- import { mkdir as mkdir10, readFile as readFile13, writeFile as writeFile12 } from "fs/promises";
21448
- import * as os7 from "os";
21564
+ import { existsSync as existsSync28, readFileSync as readFileSync15 } from "fs";
21565
+ import { mkdir as mkdir11, readFile as readFile13, writeFile as writeFile12 } from "fs/promises";
21566
+ import * as os8 from "os";
21449
21567
  import * as path43 from "path";
21450
21568
  async function migrateKnowledgeToExternal(_directory, _config) {
21451
21569
  const externalSentinelPath = path43.join(_directory, ".swarm", ".knowledge-external-migrated");
@@ -21507,17 +21625,17 @@ var _internals30 = {
21507
21625
  inferProjectName,
21508
21626
  writeSentinel,
21509
21627
  resolveLegacyHiveKnowledgePath,
21510
- existsSync: existsSync27,
21628
+ existsSync: existsSync28,
21511
21629
  readFileSync: readFileSync15,
21512
21630
  readFile: readFile13,
21513
- mkdir: mkdir10,
21631
+ mkdir: mkdir11,
21514
21632
  writeFile: writeFile12
21515
21633
  };
21516
21634
  async function migrateContextToKnowledge(directory, config) {
21517
21635
  const sentinelPath = path43.join(directory, ".swarm", ".knowledge-migrated");
21518
21636
  const contextPath = path43.join(directory, ".swarm", "context.md");
21519
21637
  const knowledgePath = resolveSwarmKnowledgePath(directory);
21520
- if (existsSync27(sentinelPath)) {
21638
+ if (existsSync28(sentinelPath)) {
21521
21639
  return {
21522
21640
  migrated: false,
21523
21641
  entriesMigrated: 0,
@@ -21526,7 +21644,7 @@ async function migrateContextToKnowledge(directory, config) {
21526
21644
  skippedReason: "sentinel-exists"
21527
21645
  };
21528
21646
  }
21529
- if (!existsSync27(contextPath)) {
21647
+ if (!existsSync28(contextPath)) {
21530
21648
  return {
21531
21649
  migrated: false,
21532
21650
  entriesMigrated: 0,
@@ -21618,7 +21736,7 @@ async function migrateHiveKnowledgeLegacy(config) {
21618
21736
  const legacyHivePath = _internals30.resolveLegacyHiveKnowledgePath();
21619
21737
  const canonicalHivePath = resolveHiveKnowledgePath();
21620
21738
  const sentinelPath = path43.join(path43.dirname(canonicalHivePath), ".hive-knowledge-migrated");
21621
- if (existsSync27(sentinelPath)) {
21739
+ if (existsSync28(sentinelPath)) {
21622
21740
  return {
21623
21741
  migrated: false,
21624
21742
  entriesMigrated: 0,
@@ -21627,7 +21745,7 @@ async function migrateHiveKnowledgeLegacy(config) {
21627
21745
  skippedReason: "sentinel-exists"
21628
21746
  };
21629
21747
  }
21630
- if (!existsSync27(legacyHivePath)) {
21748
+ if (!existsSync28(legacyHivePath)) {
21631
21749
  return {
21632
21750
  migrated: false,
21633
21751
  entriesMigrated: 0,
@@ -21829,7 +21947,7 @@ function truncateLesson2(text) {
21829
21947
  }
21830
21948
  function inferProjectName(directory) {
21831
21949
  const packageJsonPath = path43.join(directory, "package.json");
21832
- if (existsSync27(packageJsonPath)) {
21950
+ if (existsSync28(packageJsonPath)) {
21833
21951
  try {
21834
21952
  const pkg = JSON.parse(readFileSync15(packageJsonPath, "utf-8"));
21835
21953
  if (pkg.name && typeof pkg.name === "string") {
@@ -21854,7 +21972,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
21854
21972
  }
21855
21973
  function resolveLegacyHiveKnowledgePath() {
21856
21974
  const platform = process.platform;
21857
- const home = process.env.HOME || os7.homedir();
21975
+ const home = process.env.HOME || os8.homedir();
21858
21976
  let dataDir;
21859
21977
  if (platform === "win32") {
21860
21978
  dataDir = path43.join(process.env.LOCALAPPDATA || path43.join(home, "AppData", "Local"), "opencode-swarm", "Data");
@@ -22293,7 +22411,7 @@ var _internals31 = {
22293
22411
  };
22294
22412
 
22295
22413
  // src/commands/link.ts
22296
- import { existsSync as existsSync28 } from "fs";
22414
+ import { existsSync as existsSync29 } from "fs";
22297
22415
  import * as path45 from "path";
22298
22416
 
22299
22417
  // src/knowledge/identity.ts
@@ -22323,7 +22441,7 @@ var DEDUP_THRESHOLD = 0.6;
22323
22441
  async function mergeLocalKnowledgeIntoLink(localSwarmDir, linkDir) {
22324
22442
  const localPath = path45.join(localSwarmDir, "knowledge.jsonl");
22325
22443
  const sharedPath = path45.join(linkDir, "knowledge.jsonl");
22326
- if (!existsSync28(localPath))
22444
+ if (!existsSync29(localPath))
22327
22445
  return { merged: 0, skipped: 0 };
22328
22446
  let merged = 0;
22329
22447
  let skipped = 0;
@@ -22616,12 +22734,12 @@ ${USAGE7}`;
22616
22734
  }
22617
22735
 
22618
22736
  // src/commands/memory.ts
22619
- import { existsSync as existsSync29 } from "fs";
22737
+ import { existsSync as existsSync30 } from "fs";
22620
22738
  import * as path48 from "path";
22621
22739
  import { fileURLToPath as fileURLToPath2 } from "url";
22622
22740
  // src/memory/evaluation.ts
22623
22741
  import * as fs16 from "fs/promises";
22624
- import * as os8 from "os";
22742
+ import * as os9 from "os";
22625
22743
  import * as path46 from "path";
22626
22744
  var DEFAULT_PROVIDERS = [
22627
22745
  "local-jsonl",
@@ -22643,7 +22761,7 @@ async function evaluateMemoryRecallFixtures(options) {
22643
22761
  for (const fixture of fixtures) {
22644
22762
  const materialized = materializeFixture(fixture);
22645
22763
  for (const providerName of providers) {
22646
- const tempRoot = await fs16.realpath(await fs16.mkdtemp(path46.join(os8.tmpdir(), "swarm-memory-eval-")));
22764
+ const tempRoot = await fs16.realpath(await fs16.mkdtemp(path46.join(os9.tmpdir(), "swarm-memory-eval-")));
22647
22765
  const provider = createEvaluationProvider(providerName, tempRoot);
22648
22766
  try {
22649
22767
  await provider.initialize?.();
@@ -22976,7 +23094,7 @@ var CuratorOutputMemoryDecisionSchema = exports_external.object({
22976
23094
  curatorMemoryDecisions: exports_external.array(CuratorMemoryDecisionSchema).max(20).optional()
22977
23095
  }).passthrough();
22978
23096
  // src/memory/consolidation-log.ts
22979
- import { appendFile as appendFile3, mkdir as mkdir11, readFile as readFile15 } from "fs/promises";
23097
+ import { appendFile as appendFile3, mkdir as mkdir12, readFile as readFile15 } from "fs/promises";
22980
23098
  import * as path47 from "path";
22981
23099
  var LOG_RELATIVE_PATH = path47.join("memory", "consolidation-log.jsonl");
22982
23100
  async function readConsolidationLog(directory) {
@@ -23060,7 +23178,7 @@ async function handleMemoryStatusCommand(directory, _args) {
23060
23178
  `- Provider: \`${config.provider}\``,
23061
23179
  `- Storage: \`${storageDir}\``,
23062
23180
  `- SQLite path: \`${sqlitePath}\``,
23063
- `- SQLite database exists: \`${existsSync29(sqlitePath)}\``,
23181
+ `- SQLite database exists: \`${existsSync30(sqlitePath)}\``,
23064
23182
  `- Automatic destructive cleanup: \`disabled\``,
23065
23183
  "",
23066
23184
  "### Legacy JSONL"
@@ -23962,8 +24080,21 @@ async function listMergeGroupRuns(directory, repoFullName, prNumber) {
23962
24080
  }
23963
24081
  return { runs: parseMergeGroupRuns(result.stdout, prNumber) };
23964
24082
  }
24083
+ function formatMergeGroupStatus(status, conclusion, htmlUrl) {
24084
+ if (!status)
24085
+ return "Merge group: unknown";
24086
+ const parts = [`Merge group: ${status}`];
24087
+ if (conclusion) {
24088
+ parts.push(conclusion);
24089
+ }
24090
+ if (htmlUrl) {
24091
+ parts.push(`(${htmlUrl})`);
24092
+ }
24093
+ return parts.join(" ");
24094
+ }
23965
24095
  var _internals35 = {
23966
24096
  formatRelativeTime,
24097
+ formatMergeGroupStatus,
23967
24098
  listActive,
23968
24099
  listMergeGroupRuns,
23969
24100
  parseMergeGroupRuns
@@ -24007,6 +24138,7 @@ async function handlePrMonitorStatusCommand(directory, _args, sessionID, source)
24007
24138
  }
24008
24139
  lines.push(` Last checked: ${formatRelativeTime(sub.lastCheckedAt)}`);
24009
24140
  lines.push(` Watching: ${sub.isWatching ? "yes" : "no"}`);
24141
+ lines.push(` ${formatMergeGroupStatus(sub.mergeGroupRunStatus, sub.mergeGroupRunConclusion, sub.mergeGroupRunHtmlUrl)}`);
24010
24142
  lines.push(` Errors: ${sub.errorCount}`);
24011
24143
  if (i < subs.length - 1) {
24012
24144
  lines.push("");
@@ -26698,7 +26830,7 @@ var DISPATCH_FRAMEWORK_MAP = {
26698
26830
  };
26699
26831
  async function detectTestFrameworkViaDispatch(cwd) {
26700
26832
  try {
26701
- const { pickBackend } = await import("./dispatch-zr1xja4t.js");
26833
+ const { pickBackend } = await import("./dispatch-wst7bypk.js");
26702
26834
  const backend = await pickBackend(cwd);
26703
26835
  if (!backend?.selectTestFramework)
26704
26836
  return "none";
@@ -26714,7 +26846,7 @@ async function buildTestCommandViaDispatch(framework, scope, files, coverage, ba
26714
26846
  if (framework === "none")
26715
26847
  return null;
26716
26848
  try {
26717
- const { pickBackend } = await import("./dispatch-zr1xja4t.js");
26849
+ const { pickBackend } = await import("./dispatch-wst7bypk.js");
26718
26850
  const backend = await pickBackend(baseDir);
26719
26851
  if (backend?.buildTestCommand) {
26720
26852
  const cmd = backend.buildTestCommand(framework, files, baseDir, {
@@ -26734,7 +26866,7 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
26734
26866
  if (framework === "none")
26735
26867
  return null;
26736
26868
  try {
26737
- const { pickBackend } = await import("./dispatch-zr1xja4t.js");
26869
+ const { pickBackend } = await import("./dispatch-wst7bypk.js");
26738
26870
  const backend = await pickBackend(baseDir);
26739
26871
  if (!backend?.parseTestOutput)
26740
26872
  return null;
@@ -32266,13 +32398,13 @@ function buildStatusMessage2(session, directory, sessionID) {
32266
32398
  }
32267
32399
 
32268
32400
  // src/commands/unlink.ts
32269
- import { existsSync as existsSync40 } from "fs";
32401
+ import { existsSync as existsSync41 } from "fs";
32270
32402
  import * as path65 from "path";
32271
32403
  var DEDUP_THRESHOLD2 = 0.6;
32272
32404
  async function copySharedKnowledgeToLocal(linkDir, localSwarmDir) {
32273
32405
  const sharedPath = path65.join(linkDir, "knowledge.jsonl");
32274
32406
  const localPath = path65.join(localSwarmDir, "knowledge.jsonl");
32275
- if (!existsSync40(sharedPath))
32407
+ if (!existsSync41(sharedPath))
32276
32408
  return 0;
32277
32409
  const sharedEntries = await readKnowledge(sharedPath);
32278
32410
  if (sharedEntries.length === 0)
@@ -32468,7 +32600,7 @@ function buildDetailedHelp(commandName, entry) {
32468
32600
  async function handleHelpCommand(ctx) {
32469
32601
  const targetCommand = ctx.args.join(" ");
32470
32602
  if (!targetCommand) {
32471
- const { buildHelpText } = await import("./index-kf2h31c7.js");
32603
+ const { buildHelpText } = await import("./index-c3h3d8kh.js");
32472
32604
  return buildHelpText();
32473
32605
  }
32474
32606
  const tokens = targetCommand.split(/\s+/);
@@ -32477,7 +32609,7 @@ async function handleHelpCommand(ctx) {
32477
32609
  return _internals48.buildDetailedHelp(resolved.key, resolved.entry);
32478
32610
  }
32479
32611
  const similar = _internals48.findSimilarCommands(targetCommand);
32480
- const { buildHelpText: fullHelp } = await import("./index-kf2h31c7.js");
32612
+ const { buildHelpText: fullHelp } = await import("./index-c3h3d8kh.js");
32481
32613
  if (similar.length > 0) {
32482
32614
  return `Command '/swarm ${targetCommand}' not found.
32483
32615
 
@@ -32610,7 +32742,7 @@ var COMMAND_REGISTRY = {
32610
32742
  },
32611
32743
  "guardrail explain": {
32612
32744
  handler: async (ctx) => {
32613
- const { handleGuardrailExplain } = await import("./guardrail-explain-8w9rkdjx.js");
32745
+ const { handleGuardrailExplain } = await import("./guardrail-explain-2j0gw8f0.js");
32614
32746
  return handleGuardrailExplain(ctx.directory, ctx.args);
32615
32747
  },
32616
32748
  description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
@@ -32620,7 +32752,7 @@ var COMMAND_REGISTRY = {
32620
32752
  },
32621
32753
  "guardrail-log": {
32622
32754
  handler: async (ctx) => {
32623
- const { handleGuardrailLog } = await import("./guardrail-log-973nan7m.js");
32755
+ const { handleGuardrailLog } = await import("./guardrail-log-xjgr00eq.js");
32624
32756
  return handleGuardrailLog(ctx.directory, ctx.args);
32625
32757
  },
32626
32758
  description: "Read the guardrail decision log (use --blocks-only for blocks)",
@@ -34589,6 +34721,18 @@ Every listed directive ID MUST appear exactly once. If a directive carries a ver
34589
34721
  FIXES: required changes if rejected
34590
34722
  Use INFO only inside ISSUES for non-blocking suggestions. RISK reflects the highest blocking severity, so it never uses INFO.
34591
34723
 
34724
+ ## MULTI-TASK COVERAGE (FR-007)
34725
+ When you are asked to review multiple tasks in a single dispatch (set-dispatch), emit one structured verdict line PER TASK at the END of your output (after all other output fields). This enables per-task attribution in the gate tracker:
34726
+
34727
+ [REVIEWED] | task-<taskId> | APPROVED | <brief summary>
34728
+ [REVIEWED] | task-<taskId> | REJECTED | <brief summary>
34729
+
34730
+ Example:
34731
+ [REVIEWED] | task-2.1 | APPROVED | No issues found in src/foo.ts
34732
+ [REVIEWED] | task-2.2 | REJECTED | Missing null check in bar() at line 42
34733
+
34734
+ If covering a single task only, you do not need to emit the structured verdict line.
34735
+
34592
34736
  ## OUTPUT ORDER FOR SKILL COMPLIANCE (when applicable)
34593
34737
  When SKILLS_USED_BY_CODER is provided, output TASK: immediately followed by SKILL_COMPLIANCE to ensure proper attribution:
34594
34738
  TASK: <task-id-or-unknown>
@@ -37564,7 +37708,7 @@ function hasActiveEpicMode(sessionID) {
37564
37708
  async function rehydratePrSubscriptions(sessionID, directory) {
37565
37709
  const map = new Map;
37566
37710
  try {
37567
- const { listActive: listActive2 } = await import("./pr-subscriptions-vv8byxe6.js");
37711
+ const { listActive: listActive2 } = await import("./pr-subscriptions-p8g2rzxd.js");
37568
37712
  const records = await listActive2(directory);
37569
37713
  for (const record of records) {
37570
37714
  if (record.sessionID !== sessionID)