opencode-swarm 7.111.0 → 7.112.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) 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-llm-factory-vxa4pz48.js +40 -0
  9. package/dist/cli/{curator-2hm297yd.js → curator-ztdgdpb6.js} +19 -19
  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-gv1ht6b0.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-wdextf8h.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-7xfh4k71.js → index-20hyxe3z.js} +403 -291
  19. package/dist/cli/{index-c483hnn4.js → index-30ejh1tx.js} +3 -3
  20. package/dist/cli/{index-v8pk35h7.js → index-32bx4kch.js} +70 -5
  21. package/dist/cli/{index-cmjq1kg7.js → index-82v0d72f.js} +3 -3
  22. package/dist/cli/{index-yw8qpf51.js → index-9fxs0rm1.js} +1 -1
  23. package/dist/cli/{index-9ptp9kky.js → index-azf2bmr5.js} +2 -2
  24. package/dist/cli/{index-0g5xsrp4.js → index-cq2hgvd2.js} +13 -5
  25. package/dist/cli/{index-j2v3w1ds.js → index-d0w40jm3.js} +4 -4
  26. package/dist/cli/{index-40h0yp9e.js → index-db1fh1fv.js} +1 -1
  27. package/dist/cli/{index-dnbca696.js → index-fhmw7evd.js} +2 -2
  28. package/dist/cli/{index-vzzt3ygr.js → index-g55nzpwn.js} +1 -1
  29. package/dist/cli/{index-yhmt3dw3.js → index-hpp2r0sd.js} +3 -3
  30. package/dist/cli/{index-kf2h31c7.js → index-hy5r0mgf.js} +21 -21
  31. package/dist/cli/{index-53z1afgh.js → index-npxmfj48.js} +1 -1
  32. package/dist/cli/{index-6jng9c8t.js → index-pm992z24.js} +1 -1
  33. package/dist/cli/{index-85bacexr.js → index-q1jaeynn.js} +4 -1
  34. package/dist/cli/{index-mvg66d9n.js → index-t6wfwdm1.js} +3 -3
  35. package/dist/cli/{index-5rfxzgmt.js → index-w84stmkx.js} +1 -1
  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-4gbz527n.js} +6 -6
  39. package/dist/cli/{knowledge-events-bckbj6ah.js → knowledge-events-b6x28fgc.js} +4 -4
  40. package/dist/cli/{knowledge-store-dvjbdn00.js → knowledge-store-h3cjx4dg.js} +9 -5
  41. package/dist/cli/{knowledge-validator-bqr936sg.js → knowledge-validator-q6jw2p0t.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-fe6q8xgm.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/hooks/knowledge-events.d.ts +21 -1
  58. package/dist/hooks/knowledge-injector.d.ts +4 -0
  59. package/dist/hooks/knowledge-reader.d.ts +16 -0
  60. package/dist/hooks/knowledge-store.d.ts +23 -0
  61. package/dist/index.js +217 -192
  62. package/dist/tools/placeholder-scan.d.ts +14 -1
  63. package/dist/utils/bun-compat.d.ts +6 -0
  64. package/dist/worktree/merge.d.ts +12 -0
  65. package/package.json +7 -5
  66. package/dist/cli/curator-llm-factory-19s0r5v6.js +0 -40
  67. package/dist/cli/guardrail-explain-8w9rkdjx.js +0 -41
  68. /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-82v0d72f.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-30ejh1tx.js";
119
120
  import {
120
121
  readRecentEscalations
121
- } from "./index-mvg66d9n.js";
122
+ } from "./index-t6wfwdm1.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-hpp2r0sd.js";
130
131
  import {
131
132
  appendKnowledge,
132
133
  appendRejectedLesson,
@@ -135,6 +136,7 @@ import {
135
136
  computeConfidence,
136
137
  computeOutcomeSignal,
137
138
  enforceKnowledgeCap,
139
+ findActiveSwarmNearDuplicate,
138
140
  findNearDuplicate,
139
141
  getArchivedKnowledgeIds,
140
142
  inferTags,
@@ -142,13 +144,14 @@ import {
142
144
  readKnowledge,
143
145
  readRejectedLessons,
144
146
  readRetractionRecords,
147
+ reinforceSwarmKnowledgeEntry,
145
148
  resolveHiveKnowledgePath,
146
149
  resolveHiveRejectedPath,
147
150
  resolveSwarmKnowledgePath,
148
151
  rewriteKnowledge,
149
152
  transactFile,
150
153
  transactKnowledge
151
- } from "./index-v8pk35h7.js";
154
+ } from "./index-32bx4kch.js";
152
155
  import {
153
156
  KNOWLEDGE_SCHEMA_VERSION,
154
157
  OUTCOME_BLOCK_THRESHOLD,
@@ -162,7 +165,7 @@ import {
162
165
  resolveLinkDir,
163
166
  sanitizeLinkId,
164
167
  writeLinkPointer
165
- } from "./index-40h0yp9e.js";
168
+ } from "./index-db1fh1fv.js";
166
169
  import {
167
170
  CURATOR_INIT_PROMPT,
168
171
  CURATOR_PHASE_PROMPT,
@@ -174,12 +177,12 @@ import {
174
177
  } from "./index-wvrj16f0.js";
175
178
  import {
176
179
  clearAllScopes
177
- } from "./index-vzzt3ygr.js";
180
+ } from "./index-g55nzpwn.js";
178
181
  import {
179
182
  readSwarmFileAsync,
180
183
  safeHook,
181
184
  validateSwarmPath
182
- } from "./index-r3j3458j.js";
185
+ } from "./index-1rga1vvb.js";
183
186
  import {
184
187
  deepMerge
185
188
  } from "./index-p0arc26j.js";
@@ -191,7 +194,7 @@ import {
191
194
  } from "./index-zgwm4ryv.js";
192
195
  import {
193
196
  atomicWriteFile
194
- } from "./index-1cn967sa.js";
197
+ } from "./index-0dab9w37.js";
195
198
  import {
196
199
  exports_external
197
200
  } from "./index-293f68mj.js";
@@ -208,7 +211,7 @@ import {
208
211
  bunSpawn,
209
212
  bunWrite,
210
213
  mergeEnvForChild
211
- } from "./index-7xgqky26.js";
214
+ } from "./index-h91bv3hy.js";
212
215
  import {
213
216
  __require,
214
217
  __toESM
@@ -472,7 +475,8 @@ var _internals4 = {
472
475
  platform: process.platform,
473
476
  sleep: (ms) => new Promise((resolve2) => setTimeout(resolve2, ms)),
474
477
  cleanupOrphanedBranches,
475
- startupOrphanRecovery
478
+ startupOrphanRecovery,
479
+ extractSessionId
476
480
  };
477
481
  var MERGE_TIMEOUT_MS = 30000;
478
482
  async function runGit(args, cwd, timeoutMs = MERGE_TIMEOUT_MS) {
@@ -5034,11 +5038,11 @@ var BUNDLED_PROJECT_SKILLS = [
5034
5038
  "running-tests",
5035
5039
  "engineering-conventions",
5036
5040
  "commit-pr",
5037
- "worktree-retry-cleanup",
5038
- "skill-edit-validation",
5039
- "merge-queue-readiness",
5041
+ "ci-failure-batching",
5040
5042
  "gate-attribution",
5041
- "ci-failure-batching"
5043
+ "merge-queue-readiness",
5044
+ "skill-edit-validation",
5045
+ "worktree-retry-cleanup"
5042
5046
  ];
5043
5047
  var MAX_SKILL_FILES = 64;
5044
5048
  var MAX_SKILL_BYTES = 512000;
@@ -6557,6 +6561,8 @@ async function handleList2(directory) {
6557
6561
 
6558
6562
  // src/commands/ci-simulate.ts
6559
6563
  import * as fs4 from "fs";
6564
+ import * as fsPromises2 from "fs/promises";
6565
+ import * as os5 from "os";
6560
6566
  import * as path13 from "path";
6561
6567
 
6562
6568
  // src/utils/external-tool-runner.ts
@@ -6719,148 +6725,254 @@ var _internals7 = {
6719
6725
  };
6720
6726
 
6721
6727
  // 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) {
6728
+ var GIT_TIMEOUT_MS2 = 30000;
6729
+ var VALIDATION_TIMEOUT_MS = 5 * 60 * 1000;
6730
+ var OUTPUT_LIMIT_BYTES = 12000;
6731
+ var _internals8 = {
6732
+ runExternalTool,
6733
+ getDefaultBaseBranch,
6734
+ platform: process.platform,
6735
+ osTmpdir: () => os5.tmpdir(),
6736
+ fs: {
6737
+ existsSync: fs4.existsSync,
6738
+ rmSync: fs4.rmSync
6739
+ }
6740
+ };
6741
+ async function runGit2(args, cwd, timeoutMs = GIT_TIMEOUT_MS2) {
6742
+ const result = await _internals8.runExternalTool({
6743
+ executable: "git",
6744
+ args,
6745
+ cwd,
6746
+ timeoutMs,
6747
+ maxStdoutBytes: OUTPUT_LIMIT_BYTES,
6748
+ maxStderrBytes: OUTPUT_LIMIT_BYTES
6749
+ });
6750
+ return {
6751
+ exitCode: result.exitCode ?? 1,
6752
+ stdout: result.message ? [result.message, result.stdout].filter(Boolean).join(`
6753
+ `) : result.stdout,
6754
+ stderr: result.stderr,
6755
+ outputTruncated: result.stdoutTruncated || result.stderrTruncated
6756
+ };
6757
+ }
6758
+ async function runValidationCommand(cmd, cwd, timeoutMs = VALIDATION_TIMEOUT_MS) {
6738
6759
  const [executable, ...args] = cmd;
6739
- const result = await runExternalTool({
6760
+ const result = await _internals8.runExternalTool({
6740
6761
  executable,
6741
6762
  args,
6742
6763
  cwd,
6743
- timeoutMs: timeout,
6744
- maxStdoutBytes: OUTPUT_LIMIT,
6745
- maxStderrBytes: OUTPUT_LIMIT
6764
+ timeoutMs,
6765
+ maxStdoutBytes: OUTPUT_LIMIT_BYTES,
6766
+ maxStderrBytes: OUTPUT_LIMIT_BYTES
6746
6767
  });
6747
6768
  return {
6748
6769
  exitCode: result.exitCode ?? 1,
6749
6770
  stdout: result.message ? [result.message, result.stdout].filter(Boolean).join(`
6750
6771
  `) : result.stdout,
6751
6772
  stderr: result.stderr,
6752
- stdoutTruncated: result.stdoutTruncated,
6753
- stderrTruncated: result.stderrTruncated
6773
+ outputTruncated: result.stdoutTruncated || result.stderrTruncated
6754
6774
  };
6755
6775
  }
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;
6776
+ function isSafeGitRef(ref) {
6777
+ 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
6778
  }
6763
- function readFlag(args, name, fallback) {
6764
- return readOptionalFlag(args, name) ?? fallback;
6779
+ async function getCurrentBranchOrRef(directory) {
6780
+ const result = await runGit2(["branch", "--show-current"], directory);
6781
+ if (result.exitCode === 0 && result.stdout.trim()) {
6782
+ return result.stdout.trim();
6783
+ }
6784
+ const hashResult = await runGit2(["rev-parse", "HEAD"], directory);
6785
+ return hashResult.stdout.trim();
6765
6786
  }
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++;
6787
+ async function setupWorktree(projectRoot, prRef, baseBranch, onWorktreeCreated) {
6788
+ const worktreeBase = path13.join(_internals8.osTmpdir(), "swarm-ci-simulate");
6789
+ const worktreeName = `pr-${Date.now()}-${Math.floor(Math.random() * 1e6)}`;
6790
+ const worktreePath = path13.join(worktreeBase, worktreeName);
6791
+ await fsPromises2.mkdir(worktreeBase, { recursive: true });
6792
+ const addResult = await runGit2(["worktree", "add", "--detach", worktreePath, baseBranch], projectRoot);
6793
+ if (addResult.exitCode !== 0) {
6794
+ throw new Error(`Failed to create worktree: ${addResult.stderr.trim() || addResult.stdout.trim()}`);
6778
6795
  }
6779
- return null;
6796
+ onWorktreeCreated(worktreePath);
6797
+ const mergeResult = await runGit2(["merge", "--no-ff", "--no-edit", "--", prRef], worktreePath, GIT_TIMEOUT_MS2 * 2);
6798
+ if (mergeResult.exitCode !== 0) {
6799
+ throw new Error(`Merge failed for '${prRef}': ${mergeResult.stderr.trim() || mergeResult.stdout.trim()}`);
6800
+ }
6801
+ return worktreePath;
6780
6802
  }
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}`;
6803
+ async function cleanupWorktree(worktreePath, projectRoot) {
6804
+ const removeResult = await runGit2(["worktree", "remove", "--force", worktreePath], projectRoot);
6805
+ try {
6806
+ if (_internals8.fs.existsSync(worktreePath)) {
6807
+ _internals8.fs.rmSync(worktreePath, { recursive: true, force: true });
6808
+ }
6809
+ } catch {}
6810
+ if (removeResult.exitCode !== 0) {
6811
+ console.warn(`[ci-simulate] git worktree remove failed: ${removeResult.stderr.trim() || removeResult.stdout.trim()}`);
6812
+ }
6813
+ }
6814
+ async function runValidationSuite(worktreePath) {
6815
+ const steps = [];
6816
+ const commands = [
6817
+ { step: "typecheck", cmd: ["bun", "run", "typecheck"] },
6818
+ { step: "lint", cmd: ["bun", "run", "lint"] },
6819
+ { step: "build", cmd: ["bun", "run", "build"] },
6820
+ { step: "test", cmd: ["bun", "test"] }
6821
+ ];
6822
+ for (const { step, cmd } of commands) {
6823
+ const start = Date.now();
6824
+ const result = await runValidationCommand(cmd, worktreePath);
6825
+ const durationMs = Date.now() - start;
6826
+ steps.push({
6827
+ step,
6828
+ command: cmd.join(" "),
6829
+ exitCode: result.exitCode,
6830
+ stdout: result.stdout,
6831
+ stderr: result.stderr,
6832
+ durationMs,
6833
+ outputTruncated: result.outputTruncated
6834
+ });
6835
+ }
6836
+ return steps;
6837
+ }
6838
+ function formatStepOutput(stdout, stderr, outputTruncated, maxLength = 2000) {
6839
+ let output = stdout;
6840
+ if (stderr) {
6841
+ output += output ? `
6842
+ ${stderr}` : stderr;
6843
+ }
6844
+ if (output.length > maxLength) {
6845
+ output = `${output.slice(0, maxLength)}
6846
+ ... (output truncated)`;
6847
+ }
6848
+ if (outputTruncated) {
6849
+ output = `${output}
6850
+ ... (child output truncated to bounded limit)`;
6851
+ }
6852
+ return output;
6853
+ }
6854
+ function extractFileLineReferences(output) {
6855
+ const lines = [];
6856
+ const patterns = [
6857
+ /([A-Za-z]:[\\/])?[^\s:]+\.(ts|tsx|js|jsx):(\d+):(\d+)/g,
6858
+ /(?:error|Error|FAIL|Failed)[:\s]+([^\s]+\.(ts|tsx|js|jsx)?:?:\d+)/gi,
6859
+ /FAIL\s+([^\s]+\.(test|spec)\.(ts|tsx|js|jsx))/gi
6860
+ ];
6861
+ for (const pattern of patterns) {
6862
+ const matches = Array.from(output.matchAll(pattern));
6863
+ for (const match of matches) {
6864
+ if (match[0]) {
6865
+ lines.push(match[0]);
6866
+ }
6867
+ }
6868
+ }
6869
+ return Array.from(new Set(lines));
6795
6870
  }
6796
6871
  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;
6872
+ const prRef = args[0] ?? await getCurrentBranchOrRef(directory);
6873
+ if (!isSafeGitRef(prRef)) {
6874
+ return "CI simulation failed: PR ref must be a safe git branch or commit reference.";
6875
+ }
6876
+ const lines = [];
6877
+ lines.push(`# CI Simulation Report`);
6878
+ lines.push("");
6879
+ lines.push(`PR ref: **${prRef}**`);
6880
+ lines.push(`Started: ${new Date().toISOString()}`);
6881
+ lines.push("");
6882
+ let worktreePath;
6883
+ const result = {
6884
+ success: false,
6885
+ worktreePath: "",
6886
+ steps: []
6887
+ };
6888
+ try {
6889
+ const baseBranch = _internals8.getDefaultBaseBranch(directory);
6890
+ if (!isSafeGitRef(baseBranch)) {
6891
+ throw new Error("Detected default branch is not a safe git reference.");
6892
+ }
6893
+ lines.push("## Setup");
6894
+ lines.push("");
6895
+ lines.push(`Creating temporary worktree from ${baseBranch}...`);
6896
+ worktreePath = await setupWorktree(directory, prRef, baseBranch, (createdPath) => {
6897
+ worktreePath = createdPath;
6898
+ });
6899
+ result.worktreePath = worktreePath;
6900
+ lines.push(`Worktree: \`${worktreePath}\``);
6901
+ lines.push("");
6902
+ const mergeCheckResult = await runGit2(["log", "--oneline", "-1", "--format=%s"], worktreePath);
6903
+ const lastCommit = mergeCheckResult.stdout.trim();
6904
+ lines.push(`Last commit in worktree: \`${lastCommit}\``);
6905
+ lines.push("");
6906
+ lines.push("## Validation Suite");
6907
+ lines.push("");
6908
+ result.steps = await runValidationSuite(worktreePath);
6909
+ for (const step of result.steps) {
6910
+ const status = step.exitCode === 0 ? "\u2705 PASS" : "\u274C FAIL";
6911
+ lines.push(`### ${status}: ${step.step}`);
6912
+ lines.push("");
6913
+ lines.push(`Command: \`${step.command}\``);
6914
+ lines.push(`Duration: ${(step.durationMs / 1000).toFixed(1)}s`);
6915
+ if (step.exitCode !== 0) {
6916
+ lines.push(`Exit code: ${step.exitCode}`);
6917
+ const fileRefs = extractFileLineReferences(`${step.stdout}
6918
+ ${step.stderr}`);
6919
+ if (fileRefs.length > 0) {
6920
+ lines.push("");
6921
+ lines.push("**Failure locations:**");
6922
+ for (const ref of fileRefs.slice(0, 20)) {
6923
+ lines.push(` - \`${ref}\``);
6843
6924
  }
6844
6925
  }
6845
- response ??= `CI simulation passed after merging ${head2} into ${base}: ${ciCommands.map((cmd) => cmd.join(" ")).join(" && ")}`;
6926
+ lines.push("");
6927
+ lines.push("**Output:**");
6928
+ lines.push("```");
6929
+ lines.push(formatStepOutput(step.stdout, step.stderr, step.outputTruncated));
6930
+ lines.push("```");
6846
6931
  }
6932
+ lines.push("");
6847
6933
  }
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();
6934
+ const allPassed = result.steps.every((s) => s.exitCode === 0);
6935
+ result.success = allPassed;
6936
+ lines.push("## Summary");
6937
+ lines.push("");
6938
+ const passed = result.steps.filter((s) => s.exitCode === 0).length;
6939
+ const failed = result.steps.filter((s) => s.exitCode !== 0).length;
6940
+ lines.push(`Validation: ${passed}/${result.steps.length} steps passed, ${failed} failed`);
6941
+ lines.push("");
6942
+ if (allPassed) {
6943
+ lines.push("\u2705 **All checks passed \u2014 CI simulation succeeded**");
6944
+ } else {
6945
+ lines.push(`\u274C **CI simulation failed \u2014 these failures would cause a merge-queue kick-out**`);
6946
+ lines.push("");
6947
+ lines.push("To reproduce locally, run in the worktree:");
6948
+ lines.push(`\`\`\`bash`);
6949
+ lines.push(`cd "${worktreePath}"`);
6950
+ for (const step of result.steps.filter((s) => s.exitCode !== 0)) {
6951
+ lines.push(`# ${step.step}: ${step.command}`);
6853
6952
  }
6953
+ lines.push(`\`\`\``);
6954
+ }
6955
+ } catch (err) {
6956
+ const errMsg = err instanceof Error ? err.message : String(err);
6957
+ result.error = errMsg;
6958
+ lines.push("");
6959
+ lines.push("## Error");
6960
+ lines.push("");
6961
+ lines.push(`\`\`\``);
6962
+ lines.push(errMsg);
6963
+ lines.push(`\`\`\``);
6964
+ } finally {
6965
+ if (worktreePath) {
6966
+ lines.push("");
6967
+ lines.push("---");
6968
+ lines.push("");
6969
+ lines.push("*Cleaning up temporary worktree...*");
6970
+ await cleanupWorktree(worktreePath, directory);
6971
+ lines.push(`Worktree removed: \`${worktreePath}\``);
6854
6972
  }
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
6973
  }
6863
- return response ?? "CI simulation failed: no result was produced.";
6974
+ return lines.join(`
6975
+ `);
6864
6976
  }
6865
6977
 
6866
6978
  // src/commands/clarify.ts
@@ -6879,7 +6991,7 @@ import { promises as fs10 } from "fs";
6879
6991
  import path30 from "path";
6880
6992
 
6881
6993
  // src/hooks/curator-postmortem.ts
6882
- import { existsSync as existsSync10, readdirSync as readdirSync2, readFileSync as readFileSync6 } from "fs";
6994
+ import { existsSync as existsSync11, readdirSync as readdirSync2, readFileSync as readFileSync6 } from "fs";
6883
6995
  import * as path18 from "path";
6884
6996
 
6885
6997
  // src/hooks/curator.ts
@@ -7298,8 +7410,8 @@ import { readFile as readFile5, rename as rename4, writeFile as writeFile5 } fro
7298
7410
 
7299
7411
  // src/services/skill-improver-quota.ts
7300
7412
  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";
7413
+ import { existsSync as existsSync8 } from "fs";
7414
+ import { mkdir as mkdir5, readFile as readFile4, rename as rename3, writeFile as writeFile4 } from "fs/promises";
7303
7415
  import * as path14 from "path";
7304
7416
  var LOCK_ACQUIRE_TIMEOUT_MS = 1e4;
7305
7417
  var LOCK_RETRY_OPTS = {
@@ -7341,7 +7453,7 @@ function todayKey(window, now = new Date) {
7341
7453
  return `${yr}-${m}-${d}`;
7342
7454
  }
7343
7455
  async function readState(filePath) {
7344
- if (!existsSync7(filePath))
7456
+ if (!existsSync8(filePath))
7345
7457
  return null;
7346
7458
  try {
7347
7459
  const raw = await readFile4(filePath, "utf-8");
@@ -7355,7 +7467,7 @@ async function readState(filePath) {
7355
7467
  }
7356
7468
  }
7357
7469
  async function writeState(filePath, state) {
7358
- await mkdir4(path14.dirname(filePath), { recursive: true });
7470
+ await mkdir5(path14.dirname(filePath), { recursive: true });
7359
7471
  const tmp = `${filePath}.tmp-${process.pid}`;
7360
7472
  await writeFile4(tmp, JSON.stringify(state, null, 2), "utf-8");
7361
7473
  await rename3(tmp, filePath);
@@ -7378,7 +7490,7 @@ async function getQuotaState(directory, opts) {
7378
7490
  }
7379
7491
  async function reserveQuota(directory, opts) {
7380
7492
  const filePath = resolveQuotaPath(directory, opts.scope);
7381
- await mkdir4(path14.dirname(filePath), { recursive: true });
7493
+ await mkdir5(path14.dirname(filePath), { recursive: true });
7382
7494
  let release = null;
7383
7495
  try {
7384
7496
  release = await acquireLock(path14.dirname(filePath));
@@ -7408,7 +7520,7 @@ async function reserveQuota(directory, opts) {
7408
7520
  }
7409
7521
  async function releaseQuota(directory, opts) {
7410
7522
  const filePath = resolveQuotaPath(directory, opts.scope);
7411
- await mkdir4(path14.dirname(filePath), { recursive: true });
7523
+ await mkdir5(path14.dirname(filePath), { recursive: true });
7412
7524
  let release = null;
7413
7525
  try {
7414
7526
  release = await acquireLock(path14.dirname(filePath));
@@ -9087,7 +9199,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
9087
9199
  }
9088
9200
  if (config.skill_generation_enabled === true && skillCandidates.length > 0) {
9089
9201
  try {
9090
- const skillModule = await import("./skill-generator-5rsjmmfq.js");
9202
+ const skillModule = await import("./skill-generator-fe6q8xgm.js");
9091
9203
  for (const cand of skillCandidates) {
9092
9204
  if (cand.confidence < (config.min_skill_confidence ?? DEFAULT_SKILL_MIN_CONFIDENCE)) {
9093
9205
  continue;
@@ -9368,7 +9480,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
9368
9480
  } catch {}
9369
9481
  }
9370
9482
  if (contradictedEntries.length > 0 && knowledgeConfig.contradiction_threshold_action === "quarantine") {
9371
- const { maybeQuarantineOnContradiction } = await import("./knowledge-escalator-0dkkenp2.js");
9483
+ const { maybeQuarantineOnContradiction } = await import("./knowledge-escalator-4gbz527n.js");
9372
9484
  for (const { id } of contradictedEntries) {
9373
9485
  try {
9374
9486
  await maybeQuarantineOnContradiction(directory, id, knowledgeConfig.contradiction_quarantine_threshold, knowledgeConfig.contradiction_quarantine_window_days);
@@ -9872,7 +9984,7 @@ async function repairPostMortemActions(llmOutput, diagnostics, options) {
9872
9984
  }
9873
9985
  function readJsonlFile(filePath, maxLines) {
9874
9986
  try {
9875
- if (!existsSync10(filePath))
9987
+ if (!existsSync11(filePath))
9876
9988
  return [];
9877
9989
  const content = readFileSync6(filePath, "utf-8");
9878
9990
  const results = [];
@@ -9896,12 +10008,12 @@ function collectRetrospectives(directory) {
9896
10008
  const results = [];
9897
10009
  const evidenceDir = path18.join(directory, ".swarm", "evidence");
9898
10010
  try {
9899
- if (!existsSync10(evidenceDir))
10011
+ if (!existsSync11(evidenceDir))
9900
10012
  return results;
9901
10013
  const retroDirs = readdirSync2(evidenceDir, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name.startsWith("retro-")).slice(0, MAX_RETROSPECTIVES);
9902
10014
  for (const entry of retroDirs) {
9903
10015
  const retroPath = path18.join(evidenceDir, entry.name, "evidence.json");
9904
- if (existsSync10(retroPath)) {
10016
+ if (existsSync11(retroPath)) {
9905
10017
  try {
9906
10018
  results.push(readFileSync6(retroPath, "utf-8"));
9907
10019
  } catch {}
@@ -9921,7 +10033,7 @@ async function collectDriftReports(directory) {
9921
10033
  function collectPendingProposals(directory) {
9922
10034
  const results = [];
9923
10035
  const insightPath = path18.join(directory, ".swarm", "insight-candidates.jsonl");
9924
- if (existsSync10(insightPath)) {
10036
+ if (existsSync11(insightPath)) {
9925
10037
  try {
9926
10038
  results.push({
9927
10039
  source: "insight-candidates",
@@ -9931,7 +10043,7 @@ function collectPendingProposals(directory) {
9931
10043
  }
9932
10044
  const proposalsDir = path18.join(directory, ".swarm", "skills", "proposals");
9933
10045
  try {
9934
- if (existsSync10(proposalsDir)) {
10046
+ if (existsSync11(proposalsDir)) {
9935
10047
  const proposalFiles = readdirSync2(proposalsDir).filter((e) => e.endsWith(".md") || e.endsWith(".json")).slice(0, MAX_PROPOSALS);
9936
10048
  for (const entry of proposalFiles) {
9937
10049
  try {
@@ -9947,7 +10059,7 @@ function collectPendingProposals(directory) {
9947
10059
  }
9948
10060
  function isReportValid(reportPath) {
9949
10061
  try {
9950
- if (!existsSync10(reportPath))
10062
+ if (!existsSync11(reportPath))
9951
10063
  return false;
9952
10064
  const content = readFileSync6(reportPath, "utf-8").trim();
9953
10065
  if (content.length === 0)
@@ -10270,8 +10382,8 @@ ${actionSummary}`;
10270
10382
  reportContent = _internals12.buildDataOnlyReport(effectivePlanId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports, { scope, sessionID: options.sessionID, planLoaded });
10271
10383
  }
10272
10384
  try {
10273
- const { mkdirSync: mkdirSync9 } = await import("fs");
10274
- mkdirSync9(path18.dirname(reportPath), { recursive: true });
10385
+ const { mkdirSync: mkdirSync8 } = await import("fs");
10386
+ mkdirSync8(path18.dirname(reportPath), { recursive: true });
10275
10387
  await atomicWriteFile(reportPath, reportContent);
10276
10388
  } catch (err) {
10277
10389
  const msg = err instanceof Error ? err.message : String(err);
@@ -10325,15 +10437,15 @@ var _internals12 = {
10325
10437
  verifyPostMortemKnowledgeActions,
10326
10438
  repairPostMortemActions,
10327
10439
  loadDefaultKnowledgeConfig: async () => {
10328
- const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-s48je8zt.js");
10440
+ const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-2p15yrvn.js");
10329
10441
  return KnowledgeConfigSchema2.parse({});
10330
10442
  },
10331
10443
  applyCuratorKnowledgeUpdates: async (directory, recommendations, knowledgeConfig) => {
10332
- const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-2hm297yd.js");
10444
+ const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-ztdgdpb6.js");
10333
10445
  return applyCuratorKnowledgeUpdates2(directory, recommendations, knowledgeConfig);
10334
10446
  },
10335
10447
  checkHivePromotions: async (entries, knowledgeConfig) => {
10336
- const { checkHivePromotions } = await import("./hive-promoter-0f8xh2rn.js");
10448
+ const { checkHivePromotions } = await import("./hive-promoter-wdextf8h.js");
10337
10449
  return checkHivePromotions(entries, knowledgeConfig);
10338
10450
  },
10339
10451
  applyProposalTriage: async (directory, triage) => {
@@ -10342,7 +10454,7 @@ var _internals12 = {
10342
10454
  activateProposal,
10343
10455
  listSkills: listSkills2,
10344
10456
  sanitizeSlug
10345
- } = await import("./skill-generator-5rsjmmfq.js");
10457
+ } = await import("./skill-generator-fe6q8xgm.js");
10346
10458
  const result = {
10347
10459
  approved: [],
10348
10460
  rejected: [],
@@ -10384,7 +10496,7 @@ var _internals12 = {
10384
10496
  return result;
10385
10497
  },
10386
10498
  readPriorDriftReports: async (directory) => {
10387
- const { readPriorDriftReports } = await import("./curator-drift-169wgaxn.js");
10499
+ const { readPriorDriftReports } = await import("./curator-drift-jvs1v6em.js");
10388
10500
  return readPriorDriftReports(directory);
10389
10501
  },
10390
10502
  readSwarmKnowledge: (directory) => readKnowledge(resolveSwarmKnowledgePath(directory))
@@ -10673,14 +10785,14 @@ async function promoteFromSwarm(directory, lessonId) {
10673
10785
 
10674
10786
  // src/hooks/knowledge-curator.ts
10675
10787
  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";
10788
+ import { existsSync as existsSync14 } from "fs";
10789
+ import { appendFile as appendFile2, mkdir as mkdir7, readFile as readFile8, writeFile as writeFile8 } from "fs/promises";
10678
10790
  import * as path24 from "path";
10679
10791
 
10680
10792
  // src/services/synonym-map.ts
10681
10793
  var import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
10682
10794
  import {
10683
- mkdir as mkdir5,
10795
+ mkdir as mkdir6,
10684
10796
  readFile as readFile6,
10685
10797
  rename as rename5,
10686
10798
  stat as stat3,
@@ -10842,7 +10954,7 @@ async function readSynonymMap(directory, maxPairs = DEFAULT_MAX_PAIRS) {
10842
10954
  }
10843
10955
  }
10844
10956
  async function writeSynonymMapAtomic(filePath, map) {
10845
- await mkdir5(path20.dirname(filePath), { recursive: true });
10957
+ await mkdir6(path20.dirname(filePath), { recursive: true });
10846
10958
  const tmp = `${filePath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
10847
10959
  try {
10848
10960
  await writeFile6(tmp, JSON.stringify(map, null, 2), "utf-8");
@@ -10856,7 +10968,7 @@ async function writeSynonymMapAtomic(filePath, map) {
10856
10968
  async function rebuildSynonymMap(directory, entries, maxPairs = DEFAULT_MAX_PAIRS) {
10857
10969
  const filePath = resolveSynonymMapPath(directory);
10858
10970
  const dir = path20.dirname(filePath);
10859
- await mkdir5(dir, { recursive: true });
10971
+ await mkdir6(dir, { recursive: true });
10860
10972
  let release = null;
10861
10973
  try {
10862
10974
  release = await import_proper_lockfile2.default.lock(dir, {
@@ -10878,42 +10990,8 @@ async function rebuildSynonymMap(directory, entries, maxPairs = DEFAULT_MAX_PAIR
10878
10990
  // src/hooks/knowledge-curator.ts
10879
10991
  init_logger();
10880
10992
 
10881
- // src/hooks/knowledge-reinforcement.ts
10882
- function isActiveSwarmKnowledgeEntry(entry) {
10883
- return isActiveStatus(entry.status);
10884
- }
10885
- function findActiveSwarmNearDuplicate(lesson, entries, threshold) {
10886
- return findNearDuplicate(lesson, entries.filter(isActiveSwarmKnowledgeEntry), threshold);
10887
- }
10888
- function distinctPhaseCount(records) {
10889
- const phases = new Set;
10890
- for (const record of records ?? []) {
10891
- if (Number.isInteger(record.phase_number)) {
10892
- phases.add(record.phase_number);
10893
- }
10894
- }
10895
- return phases.size;
10896
- }
10897
- function reinforceSwarmKnowledgeEntry(entry, confirmation) {
10898
- if (!isActiveSwarmKnowledgeEntry(entry)) {
10899
- return { entryId: entry.id, reinforced: false, reason: "inactive" };
10900
- }
10901
- if ((entry.confirmed_by ?? []).some((record) => record.phase_number === confirmation.phase_number)) {
10902
- return {
10903
- entryId: entry.id,
10904
- reinforced: false,
10905
- reason: "already_confirmed_phase"
10906
- };
10907
- }
10908
- entry.confirmed_by = [...entry.confirmed_by ?? [], confirmation];
10909
- entry.updated_at = confirmation.confirmed_at;
10910
- entry.phases_alive = 0;
10911
- entry.confidence = computeConfidence(distinctPhaseCount(entry.confirmed_by), entry.auto_generated ?? false);
10912
- return { entryId: entry.id, reinforced: true, reason: "reinforced" };
10913
- }
10914
-
10915
10993
  // src/hooks/micro-reflector.ts
10916
- import { existsSync as existsSync12 } from "fs";
10994
+ import { existsSync as existsSync13 } from "fs";
10917
10995
  import { readFile as readFile7, writeFile as writeFile7 } from "fs/promises";
10918
10996
  import * as path23 from "path";
10919
10997
  init_logger();
@@ -11948,7 +12026,7 @@ async function readTaskTrajectory(directory, taskId) {
11948
12026
  try {
11949
12027
  const rel = path23.join("evidence", sanitizeTaskId(taskId), "trajectory.jsonl");
11950
12028
  const filePath = validateSwarmPath(directory, rel);
11951
- if (!existsSync12(filePath))
12029
+ if (!existsSync13(filePath))
11952
12030
  return [];
11953
12031
  const content = await readFile7(filePath, "utf-8");
11954
12032
  const out = [];
@@ -12377,7 +12455,7 @@ RETRY: your last output was missing ${result.missing.join("; ")}; produce valid
12377
12455
  async function appendCuratorSkippedEvent(directory, record) {
12378
12456
  try {
12379
12457
  const filePath = path24.join(directory, ".swarm", "events.jsonl");
12380
- await mkdir6(path24.dirname(filePath), { recursive: true });
12458
+ await mkdir7(path24.dirname(filePath), { recursive: true });
12381
12459
  await appendFile2(filePath, `${JSON.stringify({
12382
12460
  timestamp: new Date().toISOString(),
12383
12461
  event: "curator_skipped",
@@ -12417,7 +12495,7 @@ function readInsightJsonl(content) {
12417
12495
  async function consumeInsightCandidates(directory, batchLimit = MESO_INSIGHT_BATCH_LIMIT) {
12418
12496
  try {
12419
12497
  const filePath = resolveInsightCandidatesPath(directory);
12420
- if (!existsSync13(filePath))
12498
+ if (!existsSync14(filePath))
12421
12499
  return [];
12422
12500
  const consumed = [];
12423
12501
  await transactFile(filePath, async (p) => readInsightJsonl(await readFile8(p, "utf-8").catch(() => "")), async (p, data) => {
@@ -13342,13 +13420,13 @@ async function writeSessionReflection(directory, result) {
13342
13420
  }
13343
13421
 
13344
13422
  // 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";
13423
+ import { existsSync as existsSync16 } from "fs";
13424
+ import { mkdir as mkdir9, readFile as readFile9, rename as rename6, writeFile as writeFile10 } from "fs/promises";
13347
13425
  import * as path27 from "path";
13348
13426
  init_logger();
13349
13427
 
13350
13428
  // src/services/trajectory-cluster.ts
13351
- import { mkdir as mkdir7, writeFile as writeFile9 } from "fs/promises";
13429
+ import { mkdir as mkdir8, writeFile as writeFile9 } from "fs/promises";
13352
13430
  import * as path26 from "path";
13353
13431
  init_logger();
13354
13432
  var MACRO_TRAJECTORY_WINDOW = 200;
@@ -13482,7 +13560,7 @@ async function writeMotifProposals(directory, opts = {}) {
13482
13560
  return result;
13483
13561
  const max = opts.maxProposals ?? 10;
13484
13562
  const proposalsDir = validateSwarmPath(directory, path26.join("skills", "proposals"));
13485
- await mkdir7(proposalsDir, { recursive: true });
13563
+ await mkdir8(proposalsDir, { recursive: true });
13486
13564
  for (const motif of motifs.slice(0, max)) {
13487
13565
  const slug = `motif-${slugify(motif.signature)}`;
13488
13566
  const filePath = path26.join(proposalsDir, `${slug}.md`);
@@ -13627,7 +13705,7 @@ async function writeSuccessMotifProposals(directory, opts = {}) {
13627
13705
  return result;
13628
13706
  const max = opts.maxProposals ?? 10;
13629
13707
  const proposalsDir = validateSwarmPath(directory, path26.join("skills", "proposals"));
13630
- await mkdir7(proposalsDir, { recursive: true });
13708
+ await mkdir8(proposalsDir, { recursive: true });
13631
13709
  for (const motif of motifs.slice(0, max)) {
13632
13710
  const slug = workflowSlug(motif.signature);
13633
13711
  const filePath = path26.join(proposalsDir, `${slug}.md`);
@@ -13642,14 +13720,14 @@ async function writeSuccessMotifProposals(directory, opts = {}) {
13642
13720
  }
13643
13721
 
13644
13722
  // src/services/unactionable-hardening.ts
13645
- import { existsSync as existsSync14 } from "fs";
13723
+ import { existsSync as existsSync15 } from "fs";
13646
13724
  init_logger();
13647
13725
  var HARDENING_BATCH_LIMIT = 5;
13648
13726
  async function hardenUnactionableEntries(params) {
13649
13727
  const result = { hardened: 0, retired: 0, remaining: 0 };
13650
13728
  try {
13651
13729
  const queuePath = resolveUnactionablePath(params.directory);
13652
- if (!existsSync14(queuePath))
13730
+ if (!existsSync15(queuePath))
13653
13731
  return result;
13654
13732
  const limit = params.batchLimit ?? HARDENING_BATCH_LIMIT;
13655
13733
  const dedupThreshold = params.dedupThreshold ?? 0.6;
@@ -13753,7 +13831,7 @@ function timestampSlug(d) {
13753
13831
  return d.toISOString().replace(/[:.]/g, "-");
13754
13832
  }
13755
13833
  async function atomicWrite(p, content) {
13756
- await mkdir8(path27.dirname(p), { recursive: true });
13834
+ await mkdir9(path27.dirname(p), { recursive: true });
13757
13835
  const tmp = `${p}.tmp-${process.pid}-${Date.now()}`;
13758
13836
  await writeFile10(tmp, content, "utf-8");
13759
13837
  await rename6(tmp, p);
@@ -13761,7 +13839,7 @@ async function atomicWrite(p, content) {
13761
13839
  async function gatherInventory(directory) {
13762
13840
  const swarm = await readKnowledge(resolveSwarmKnowledgePath(directory));
13763
13841
  const hivePath = resolveHiveKnowledgePath();
13764
- const hive = existsSync15(hivePath) ? await readKnowledge(hivePath) : [];
13842
+ const hive = existsSync16(hivePath) ? await readKnowledge(hivePath) : [];
13765
13843
  const archived = [...swarm, ...hive].filter((e) => e.status === "archived").length;
13766
13844
  const skills = await listSkills(directory);
13767
13845
  const knowledgeById = new Map([...swarm, ...hive].map((entry) => [entry.id, entry]));
@@ -14226,7 +14304,7 @@ var _internals17 = {
14226
14304
  };
14227
14305
 
14228
14306
  // src/session/session-start-store.ts
14229
- import { existsSync as existsSync16, mkdirSync as mkdirSync10, readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "fs";
14307
+ import { existsSync as existsSync17, mkdirSync as mkdirSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "fs";
14230
14308
  import * as path28 from "path";
14231
14309
  var SESSION_START_FILE = "session-start.jsonl";
14232
14310
  function recordSessionStart(directory, startMs) {
@@ -14235,7 +14313,7 @@ function recordSessionStart(directory, startMs) {
14235
14313
  const sessionDir = path28.join(swarmDir, "session");
14236
14314
  const filePath = path28.join(sessionDir, SESSION_START_FILE);
14237
14315
  const line = JSON.stringify({ startMs, ts: Date.now() });
14238
- mkdirSync10(sessionDir, { recursive: true });
14316
+ mkdirSync9(sessionDir, { recursive: true });
14239
14317
  writeFileSync4(filePath, `${line}
14240
14318
  `, { flag: "a" });
14241
14319
  } catch {}
@@ -14243,7 +14321,7 @@ function recordSessionStart(directory, startMs) {
14243
14321
  function readEarliestSessionStart(directory) {
14244
14322
  try {
14245
14323
  const filePath = path28.join(directory, ".swarm", "session", SESSION_START_FILE);
14246
- if (!existsSync16(filePath))
14324
+ if (!existsSync17(filePath))
14247
14325
  return null;
14248
14326
  const content = readFileSync8(filePath, "utf-8");
14249
14327
  const lines = content.split(`
@@ -14268,7 +14346,7 @@ function readEarliestSessionStart(directory) {
14268
14346
  }
14269
14347
 
14270
14348
  // src/tools/write-retro.ts
14271
- import { existsSync as existsSync17 } from "fs";
14349
+ import { existsSync as existsSync18 } from "fs";
14272
14350
  import path29 from "path";
14273
14351
  async function executeWriteRetro(args, directory) {
14274
14352
  if (/^(CON|PRN|AUX|NUL|COM[0-9]|LPT[0-9])(:|$)/i.test(directory)) {
@@ -14277,7 +14355,7 @@ async function executeWriteRetro(args, directory) {
14277
14355
  message: "Invalid directory: reserved device name"
14278
14356
  }, null, 2);
14279
14357
  }
14280
- if (!existsSync17(path29.join(directory, ".swarm"))) {
14358
+ if (!existsSync18(path29.join(directory, ".swarm"))) {
14281
14359
  return JSON.stringify({
14282
14360
  success: false,
14283
14361
  message: `Cannot write evidence in "${directory}" \u2014 no .swarm/ folder was found. Run write_retro from an initialized project root.`
@@ -15042,7 +15120,7 @@ async function runFinalizeStage(ctx) {
15042
15120
  }
15043
15121
  }
15044
15122
  try {
15045
- const { CuratorConfigSchema: CCS } = await import("./schema-s48je8zt.js");
15123
+ const { CuratorConfigSchema: CCS } = await import("./schema-2p15yrvn.js");
15046
15124
  const { config: pmLoadedConfig } = _internals19.loadPluginConfigWithMeta(ctx.directory);
15047
15125
  const curatorCfg = CCS.parse(pmLoadedConfig.curator ?? {});
15048
15126
  if (curatorCfg.enabled && curatorCfg.postmortem_enabled) {
@@ -16021,10 +16099,10 @@ function buildStatusMessage(session, plan) {
16021
16099
  }
16022
16100
 
16023
16101
  // src/commands/config.ts
16024
- import * as os5 from "os";
16102
+ import * as os6 from "os";
16025
16103
  import * as path31 from "path";
16026
16104
  function getUserConfigDir2() {
16027
- return process.env.XDG_CONFIG_HOME || path31.join(os5.homedir(), ".config");
16105
+ return process.env.XDG_CONFIG_HOME || path31.join(os6.homedir(), ".config");
16028
16106
  }
16029
16107
  async function handleConfigCommand(directory, _args) {
16030
16108
  const config = loadPluginConfig(directory);
@@ -16047,8 +16125,8 @@ async function handleConfigCommand(directory, _args) {
16047
16125
  }
16048
16126
 
16049
16127
  // 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";
16128
+ import { existsSync as existsSync20 } from "fs";
16129
+ import { mkdir as mkdir10, readFile as readFile10, rename as rename7, writeFile as writeFile11 } from "fs/promises";
16052
16130
  import * as path32 from "path";
16053
16131
 
16054
16132
  // src/utils/timeout.ts
@@ -16078,7 +16156,7 @@ function consolidationStatePath(directory) {
16078
16156
  }
16079
16157
  async function readState2(directory) {
16080
16158
  const filePath = consolidationStatePath(directory);
16081
- if (!existsSync19(filePath))
16159
+ if (!existsSync20(filePath))
16082
16160
  return {};
16083
16161
  try {
16084
16162
  const parsed = JSON.parse(await readFile10(filePath, "utf-8"));
@@ -16090,7 +16168,7 @@ async function readState2(directory) {
16090
16168
  }
16091
16169
  }
16092
16170
  async function atomicWrite2(filePath, content) {
16093
- await mkdir9(path32.dirname(filePath), { recursive: true });
16171
+ await mkdir10(path32.dirname(filePath), { recursive: true });
16094
16172
  const tmp = `${filePath}.tmp-${process.pid}-${Date.now()}`;
16095
16173
  await writeFile11(tmp, content, "utf-8");
16096
16174
  await rename7(tmp, filePath);
@@ -17155,9 +17233,9 @@ var _internals23 = {
17155
17233
  readSwarmFileAsync,
17156
17234
  loadCuratorDeps: async () => {
17157
17235
  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")
17236
+ import("./schema-2p15yrvn.js"),
17237
+ import("./curator-ztdgdpb6.js"),
17238
+ import("./curator-llm-factory-vxa4pz48.js")
17161
17239
  ]);
17162
17240
  return { CuratorConfigSchema, curator, createCuratorLLMDelegate: createCuratorLLMDelegate2 };
17163
17241
  }
@@ -17647,13 +17725,13 @@ ${USAGE5}`;
17647
17725
 
17648
17726
  // src/services/diagnose-service.ts
17649
17727
  import * as child_process5 from "child_process";
17650
- import { existsSync as existsSync22, readdirSync as readdirSync4, readFileSync as readFileSync10, statSync as statSync6 } from "fs";
17728
+ import { existsSync as existsSync23, readdirSync as readdirSync4, readFileSync as readFileSync10, statSync as statSync6 } from "fs";
17651
17729
  import * as path37 from "path";
17652
17730
  import { fileURLToPath } from "url";
17653
17731
  // package.json
17654
17732
  var package_default = {
17655
17733
  name: "opencode-swarm",
17656
- version: "7.111.0",
17734
+ version: "7.112.1",
17657
17735
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
17658
17736
  main: "dist/index.js",
17659
17737
  types: "dist/index.d.ts",
@@ -17722,11 +17800,13 @@ var package_default = {
17722
17800
  ".opencode/skills/running-tests",
17723
17801
  ".opencode/skills/engineering-conventions",
17724
17802
  ".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
17803
  ".opencode/skills/ci-failure-batching",
17804
+ ".opencode/skills/gate-attribution",
17805
+ ".opencode/skills/merge-queue-readiness",
17806
+ ".opencode/skills/skill-edit-validation",
17807
+ ".opencode/skills/swarm",
17808
+ ".opencode/skills/swarm-ci-monitor",
17809
+ ".opencode/skills/worktree-retry-cleanup",
17730
17810
  "tests/fixtures/memory-recall",
17731
17811
  "README.md",
17732
17812
  "LICENSE"
@@ -17770,13 +17850,13 @@ var package_default = {
17770
17850
  };
17771
17851
 
17772
17852
  // src/config/cache-paths.ts
17773
- import * as os6 from "os";
17853
+ import * as os7 from "os";
17774
17854
  import * as path36 from "path";
17775
17855
  function getPluginConfigDir() {
17776
- return path36.join(process.env.XDG_CONFIG_HOME || path36.join(os6.homedir(), ".config"), "opencode");
17856
+ return path36.join(process.env.XDG_CONFIG_HOME || path36.join(os7.homedir(), ".config"), "opencode");
17777
17857
  }
17778
17858
  function getPluginCachePaths() {
17779
- const cacheBase = process.env.XDG_CACHE_HOME || path36.join(os6.homedir(), ".cache");
17859
+ const cacheBase = process.env.XDG_CACHE_HOME || path36.join(os7.homedir(), ".cache");
17780
17860
  const configDir = getPluginConfigDir();
17781
17861
  const paths = [
17782
17862
  path36.join(cacheBase, "opencode", "node_modules", "opencode-swarm"),
@@ -17784,18 +17864,18 @@ function getPluginCachePaths() {
17784
17864
  path36.join(configDir, "node_modules", "opencode-swarm")
17785
17865
  ];
17786
17866
  if (process.platform === "darwin") {
17787
- const libCaches = path36.join(os6.homedir(), "Library", "Caches");
17867
+ const libCaches = path36.join(os7.homedir(), "Library", "Caches");
17788
17868
  paths.push(path36.join(libCaches, "opencode", "node_modules", "opencode-swarm"), path36.join(libCaches, "opencode", "packages", "opencode-swarm@latest"));
17789
17869
  }
17790
17870
  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");
17871
+ const localAppData = process.env.LOCALAPPDATA || path36.join(os7.homedir(), "AppData", "Local");
17872
+ const appData = process.env.APPDATA || path36.join(os7.homedir(), "AppData", "Roaming");
17793
17873
  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
17874
  }
17795
17875
  return paths;
17796
17876
  }
17797
17877
  function getPluginLockFilePaths() {
17798
- const cacheBase = process.env.XDG_CACHE_HOME || path36.join(os6.homedir(), ".cache");
17878
+ const cacheBase = process.env.XDG_CACHE_HOME || path36.join(os7.homedir(), ".cache");
17799
17879
  const configDir = getPluginConfigDir();
17800
17880
  const paths = [
17801
17881
  path36.join(cacheBase, "opencode", "bun.lock"),
@@ -17803,11 +17883,11 @@ function getPluginLockFilePaths() {
17803
17883
  path36.join(configDir, "package-lock.json")
17804
17884
  ];
17805
17885
  if (process.platform === "darwin") {
17806
- const libCaches = path36.join(os6.homedir(), "Library", "Caches");
17886
+ const libCaches = path36.join(os7.homedir(), "Library", "Caches");
17807
17887
  paths.push(path36.join(libCaches, "opencode", "bun.lock"), path36.join(libCaches, "opencode", "bun.lockb"));
17808
17888
  }
17809
17889
  if (process.platform === "win32") {
17810
- const localAppData = process.env.LOCALAPPDATA || path36.join(os6.homedir(), "AppData", "Local");
17890
+ const localAppData = process.env.LOCALAPPDATA || path36.join(os7.homedir(), "AppData", "Local");
17811
17891
  paths.push(path36.join(localAppData, "opencode", "bun.lock"), path36.join(localAppData, "opencode", "bun.lockb"));
17812
17892
  }
17813
17893
  return paths;
@@ -17818,11 +17898,11 @@ init_capability_probe();
17818
17898
  init_executor();
17819
17899
 
17820
17900
  // src/services/knowledge-diagnostics.ts
17821
- import { existsSync as existsSync21 } from "fs";
17901
+ import { existsSync as existsSync22 } from "fs";
17822
17902
  import { readFile as readFile12 } from "fs/promises";
17823
17903
 
17824
17904
  // src/services/version-check.ts
17825
- import { existsSync as existsSync20, mkdirSync as mkdirSync12, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "fs";
17905
+ import { existsSync as existsSync21, mkdirSync as mkdirSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "fs";
17826
17906
  import { homedir as homedir6 } from "os";
17827
17907
  import { join as join31 } from "path";
17828
17908
  var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
@@ -17839,7 +17919,7 @@ function cacheFile() {
17839
17919
  function readVersionCache() {
17840
17920
  try {
17841
17921
  const path37 = cacheFile();
17842
- if (!existsSync20(path37))
17922
+ if (!existsSync21(path37))
17843
17923
  return null;
17844
17924
  const raw = readFileSync9(path37, "utf-8");
17845
17925
  const parsed = JSON.parse(raw);
@@ -17893,7 +17973,7 @@ var SEVEN_DAYS_MS2 = 7 * 24 * 60 * 60 * 1000;
17893
17973
  var UNACTIONABLE_BACKLOG_WARN = 100;
17894
17974
  var INSIGHT_BACKLOG_WARN = 50;
17895
17975
  async function readRawLines(filePath) {
17896
- if (!existsSync21(filePath))
17976
+ if (!existsSync22(filePath))
17897
17977
  return { entries: [], corrupt: 0 };
17898
17978
  const content = await readFile12(filePath, "utf-8");
17899
17979
  const entries = [];
@@ -18018,7 +18098,7 @@ async function computeKnowledgeDebug(directory) {
18018
18098
  };
18019
18099
  }
18020
18100
  async function safeJsonlCount(filePath) {
18021
- if (!filePath || !existsSync21(filePath))
18101
+ if (!filePath || !existsSync22(filePath))
18022
18102
  return 0;
18023
18103
  try {
18024
18104
  const content = await readFile12(filePath, "utf-8");
@@ -18097,7 +18177,7 @@ var REQUIRED_CACHE_GRAMMAR_ASSETS = [
18097
18177
  ];
18098
18178
  function resolveCachePackageRoot(cachePath) {
18099
18179
  const nestedPackageRoot = path37.join(cachePath, "node_modules", "opencode-swarm");
18100
- return existsSync22(nestedPackageRoot) ? nestedPackageRoot : cachePath;
18180
+ return existsSync23(nestedPackageRoot) ? nestedPackageRoot : cachePath;
18101
18181
  }
18102
18182
  var _internals24 = {
18103
18183
  detectSandboxCapability: () => sandboxCapabilityProbe.detect(),
@@ -18348,7 +18428,7 @@ async function checkConfigBackups(directory) {
18348
18428
  }
18349
18429
  async function checkGitRepository(directory) {
18350
18430
  try {
18351
- if (!existsSync22(directory) || !statSync6(directory).isDirectory()) {
18431
+ if (!existsSync23(directory) || !statSync6(directory).isDirectory()) {
18352
18432
  return {
18353
18433
  name: "Git Repository",
18354
18434
  status: "\u274C",
@@ -18413,7 +18493,7 @@ async function checkSpecStaleness(directory, plan) {
18413
18493
  }
18414
18494
  async function checkConfigParseability(directory) {
18415
18495
  const configPath = path37.join(directory, ".opencode/opencode-swarm.json");
18416
- if (!existsSync22(configPath)) {
18496
+ if (!existsSync23(configPath)) {
18417
18497
  return {
18418
18498
  name: "Config Parseability",
18419
18499
  status: "\u2705",
@@ -18468,11 +18548,11 @@ async function checkGrammarWasmFiles() {
18468
18548
  const thisDir = path37.dirname(fileURLToPath(import.meta.url));
18469
18549
  const grammarDir = resolveGrammarDir(thisDir);
18470
18550
  const missing = [];
18471
- if (!existsSync22(path37.join(grammarDir, "tree-sitter.wasm"))) {
18551
+ if (!existsSync23(path37.join(grammarDir, "tree-sitter.wasm"))) {
18472
18552
  missing.push("tree-sitter.wasm (core runtime)");
18473
18553
  }
18474
18554
  for (const file of grammarFiles) {
18475
- if (!existsSync22(path37.join(grammarDir, file))) {
18555
+ if (!existsSync23(path37.join(grammarDir, file))) {
18476
18556
  missing.push(file);
18477
18557
  }
18478
18558
  }
@@ -18491,7 +18571,7 @@ async function checkGrammarWasmFiles() {
18491
18571
  }
18492
18572
  async function checkCheckpointManifest(directory) {
18493
18573
  const manifestPath = path37.join(directory, ".swarm/checkpoints.json");
18494
- if (!existsSync22(manifestPath)) {
18574
+ if (!existsSync23(manifestPath)) {
18495
18575
  return {
18496
18576
  name: "Checkpoint Manifest",
18497
18577
  status: "\u2705",
@@ -18543,7 +18623,7 @@ async function checkCheckpointManifest(directory) {
18543
18623
  }
18544
18624
  async function checkEventStreamIntegrity(directory) {
18545
18625
  const eventsPath = path37.join(directory, ".swarm/events.jsonl");
18546
- if (!existsSync22(eventsPath)) {
18626
+ if (!existsSync23(eventsPath)) {
18547
18627
  return {
18548
18628
  name: "Event Stream",
18549
18629
  status: "\u2705",
@@ -18584,7 +18664,7 @@ async function checkEventStreamIntegrity(directory) {
18584
18664
  }
18585
18665
  async function checkSteeringDirectives(directory) {
18586
18666
  const eventsPath = path37.join(directory, ".swarm/events.jsonl");
18587
- if (!existsSync22(eventsPath)) {
18667
+ if (!existsSync23(eventsPath)) {
18588
18668
  return {
18589
18669
  name: "Steering Directives",
18590
18670
  status: "\u2705",
@@ -18640,7 +18720,7 @@ async function checkCurator(directory) {
18640
18720
  };
18641
18721
  }
18642
18722
  const summaryPath = path37.join(directory, ".swarm/curator-summary.json");
18643
- if (!existsSync22(summaryPath)) {
18723
+ if (!existsSync23(summaryPath)) {
18644
18724
  return {
18645
18725
  name: "Curator",
18646
18726
  status: "\u2705",
@@ -18842,7 +18922,7 @@ async function getDiagnoseData(directory) {
18842
18922
  checks.push(await checkKnowledgeHealth(directory));
18843
18923
  try {
18844
18924
  const evidenceDir = path37.join(directory, ".swarm", "evidence");
18845
- const snapshotFiles = existsSync22(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
18925
+ const snapshotFiles = existsSync23(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
18846
18926
  if (snapshotFiles.length > 0) {
18847
18927
  const latest = snapshotFiles.sort().pop();
18848
18928
  checks.push({
@@ -18875,13 +18955,13 @@ async function getDiagnoseData(directory) {
18875
18955
  const cacheRows = [];
18876
18956
  for (const cachePath of cachePaths) {
18877
18957
  try {
18878
- if (!existsSync22(cachePath)) {
18958
+ if (!existsSync23(cachePath)) {
18879
18959
  cacheRows.push(`\u2B1C ${cachePath} \u2014 absent`);
18880
18960
  continue;
18881
18961
  }
18882
18962
  const packageRoot = resolveCachePackageRoot(cachePath);
18883
18963
  const cacheLabel = packageRoot === cachePath ? cachePath : `${cachePath} -> ${packageRoot}`;
18884
- const missingGrammarAssets = REQUIRED_CACHE_GRAMMAR_ASSETS.filter((file) => !existsSync22(path37.join(packageRoot, "dist", "lang", "grammars", file)));
18964
+ const missingGrammarAssets = REQUIRED_CACHE_GRAMMAR_ASSETS.filter((file) => !existsSync23(path37.join(packageRoot, "dist", "lang", "grammars", file)));
18885
18965
  const pkgJsonPath = path37.join(packageRoot, "package.json");
18886
18966
  try {
18887
18967
  const raw = readFileSync10(pkgJsonPath, "utf-8");
@@ -19107,7 +19187,7 @@ async function handleDoctorCommand(directory, args) {
19107
19187
  const result = runConfigDoctor(config, directory);
19108
19188
  let output;
19109
19189
  if (enableAutoFix && result.hasAutoFixableIssues) {
19110
- const { runConfigDoctorWithFixes } = await import("./config-doctor-q5e9yzn6.js");
19190
+ const { runConfigDoctorWithFixes } = await import("./config-doctor-mmw4c50z.js");
19111
19191
  const fixResult = await runConfigDoctorWithFixes(directory, config, true);
19112
19192
  output = formatDoctorMarkdown(fixResult.result);
19113
19193
  } else {
@@ -19920,7 +20000,7 @@ async function handleEvidenceCommand(directory, args) {
19920
20000
  return formatTaskEvidenceMarkdown(evidenceData);
19921
20001
  }
19922
20002
  async function handleEvidenceSummaryCommand(directory) {
19923
- const { buildEvidenceSummary } = await import("./evidence-summary-service-8tasw2tt.js");
20003
+ const { buildEvidenceSummary } = await import("./evidence-summary-service-j6fnsfeq.js");
19924
20004
  const artifact = await buildEvidenceSummary(directory);
19925
20005
  if (!artifact) {
19926
20006
  return "No plan found. Run `/swarm plan` to check plan status.";
@@ -20007,7 +20087,8 @@ function emptyCounters() {
20007
20087
  reviewerRejections: 0,
20008
20088
  testFailures: 0,
20009
20089
  oversightChecks: 0,
20010
- consecutiveNoProgressTurns: 0
20090
+ consecutiveNoProgressTurns: 0,
20091
+ consecutiveOversightFailures: 0
20011
20092
  };
20012
20093
  }
20013
20094
  var VALID_RUN_MODES = new Set(["assisted", "supervised", "strict"]);
@@ -20237,6 +20318,11 @@ function startFullAutoRun(directory, sessionID, config, options = {}) {
20237
20318
  denialCounters: {
20238
20319
  consecutive: 0,
20239
20320
  total: existing.denialCounters.total
20321
+ },
20322
+ consecutiveOversightFailures: 0,
20323
+ counters: {
20324
+ ...existing.counters,
20325
+ consecutiveOversightFailures: 0
20240
20326
  }
20241
20327
  } : {
20242
20328
  ...emptyState(sessionID, mode),
@@ -20804,7 +20890,7 @@ var _internals27 = {
20804
20890
  };
20805
20891
 
20806
20892
  // src/session/snapshot-writer.ts
20807
- import { closeSync as closeSync5, fsyncSync as fsyncSync2, mkdirSync as mkdirSync17, openSync as openSync5, renameSync as renameSync8 } from "fs";
20893
+ import { closeSync as closeSync5, fsyncSync as fsyncSync2, mkdirSync as mkdirSync16, openSync as openSync5, renameSync as renameSync8 } from "fs";
20808
20894
  import * as path42 from "path";
20809
20895
  var _writeInFlight = Promise.resolve();
20810
20896
  function serializeAgentSession(s) {
@@ -20919,7 +21005,7 @@ async function writeSnapshot(directory, state) {
20919
21005
  const content = JSON.stringify(snapshot, null, 2);
20920
21006
  const resolvedPath = validateSwarmPath(directory, "session/state.json");
20921
21007
  const dir = path42.dirname(resolvedPath);
20922
- mkdirSync17(dir, { recursive: true });
21008
+ mkdirSync16(dir, { recursive: true });
20923
21009
  const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
20924
21010
  await bunWrite(tempPath, content);
20925
21011
  try {
@@ -21443,9 +21529,9 @@ import { join as join37 } from "path";
21443
21529
  // src/hooks/knowledge-migrator.ts
21444
21530
  init_logger();
21445
21531
  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";
21532
+ import { existsSync as existsSync28, readFileSync as readFileSync15 } from "fs";
21533
+ import { mkdir as mkdir11, readFile as readFile13, writeFile as writeFile12 } from "fs/promises";
21534
+ import * as os8 from "os";
21449
21535
  import * as path43 from "path";
21450
21536
  async function migrateKnowledgeToExternal(_directory, _config) {
21451
21537
  const externalSentinelPath = path43.join(_directory, ".swarm", ".knowledge-external-migrated");
@@ -21507,17 +21593,17 @@ var _internals30 = {
21507
21593
  inferProjectName,
21508
21594
  writeSentinel,
21509
21595
  resolveLegacyHiveKnowledgePath,
21510
- existsSync: existsSync27,
21596
+ existsSync: existsSync28,
21511
21597
  readFileSync: readFileSync15,
21512
21598
  readFile: readFile13,
21513
- mkdir: mkdir10,
21599
+ mkdir: mkdir11,
21514
21600
  writeFile: writeFile12
21515
21601
  };
21516
21602
  async function migrateContextToKnowledge(directory, config) {
21517
21603
  const sentinelPath = path43.join(directory, ".swarm", ".knowledge-migrated");
21518
21604
  const contextPath = path43.join(directory, ".swarm", "context.md");
21519
21605
  const knowledgePath = resolveSwarmKnowledgePath(directory);
21520
- if (existsSync27(sentinelPath)) {
21606
+ if (existsSync28(sentinelPath)) {
21521
21607
  return {
21522
21608
  migrated: false,
21523
21609
  entriesMigrated: 0,
@@ -21526,7 +21612,7 @@ async function migrateContextToKnowledge(directory, config) {
21526
21612
  skippedReason: "sentinel-exists"
21527
21613
  };
21528
21614
  }
21529
- if (!existsSync27(contextPath)) {
21615
+ if (!existsSync28(contextPath)) {
21530
21616
  return {
21531
21617
  migrated: false,
21532
21618
  entriesMigrated: 0,
@@ -21618,7 +21704,7 @@ async function migrateHiveKnowledgeLegacy(config) {
21618
21704
  const legacyHivePath = _internals30.resolveLegacyHiveKnowledgePath();
21619
21705
  const canonicalHivePath = resolveHiveKnowledgePath();
21620
21706
  const sentinelPath = path43.join(path43.dirname(canonicalHivePath), ".hive-knowledge-migrated");
21621
- if (existsSync27(sentinelPath)) {
21707
+ if (existsSync28(sentinelPath)) {
21622
21708
  return {
21623
21709
  migrated: false,
21624
21710
  entriesMigrated: 0,
@@ -21627,7 +21713,7 @@ async function migrateHiveKnowledgeLegacy(config) {
21627
21713
  skippedReason: "sentinel-exists"
21628
21714
  };
21629
21715
  }
21630
- if (!existsSync27(legacyHivePath)) {
21716
+ if (!existsSync28(legacyHivePath)) {
21631
21717
  return {
21632
21718
  migrated: false,
21633
21719
  entriesMigrated: 0,
@@ -21829,7 +21915,7 @@ function truncateLesson2(text) {
21829
21915
  }
21830
21916
  function inferProjectName(directory) {
21831
21917
  const packageJsonPath = path43.join(directory, "package.json");
21832
- if (existsSync27(packageJsonPath)) {
21918
+ if (existsSync28(packageJsonPath)) {
21833
21919
  try {
21834
21920
  const pkg = JSON.parse(readFileSync15(packageJsonPath, "utf-8"));
21835
21921
  if (pkg.name && typeof pkg.name === "string") {
@@ -21854,7 +21940,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
21854
21940
  }
21855
21941
  function resolveLegacyHiveKnowledgePath() {
21856
21942
  const platform = process.platform;
21857
- const home = process.env.HOME || os7.homedir();
21943
+ const home = process.env.HOME || os8.homedir();
21858
21944
  let dataDir;
21859
21945
  if (platform === "win32") {
21860
21946
  dataDir = path43.join(process.env.LOCALAPPDATA || path43.join(home, "AppData", "Local"), "opencode-swarm", "Data");
@@ -22293,7 +22379,7 @@ var _internals31 = {
22293
22379
  };
22294
22380
 
22295
22381
  // src/commands/link.ts
22296
- import { existsSync as existsSync28 } from "fs";
22382
+ import { existsSync as existsSync29 } from "fs";
22297
22383
  import * as path45 from "path";
22298
22384
 
22299
22385
  // src/knowledge/identity.ts
@@ -22323,7 +22409,7 @@ var DEDUP_THRESHOLD = 0.6;
22323
22409
  async function mergeLocalKnowledgeIntoLink(localSwarmDir, linkDir) {
22324
22410
  const localPath = path45.join(localSwarmDir, "knowledge.jsonl");
22325
22411
  const sharedPath = path45.join(linkDir, "knowledge.jsonl");
22326
- if (!existsSync28(localPath))
22412
+ if (!existsSync29(localPath))
22327
22413
  return { merged: 0, skipped: 0 };
22328
22414
  let merged = 0;
22329
22415
  let skipped = 0;
@@ -22616,12 +22702,12 @@ ${USAGE7}`;
22616
22702
  }
22617
22703
 
22618
22704
  // src/commands/memory.ts
22619
- import { existsSync as existsSync29 } from "fs";
22705
+ import { existsSync as existsSync30 } from "fs";
22620
22706
  import * as path48 from "path";
22621
22707
  import { fileURLToPath as fileURLToPath2 } from "url";
22622
22708
  // src/memory/evaluation.ts
22623
22709
  import * as fs16 from "fs/promises";
22624
- import * as os8 from "os";
22710
+ import * as os9 from "os";
22625
22711
  import * as path46 from "path";
22626
22712
  var DEFAULT_PROVIDERS = [
22627
22713
  "local-jsonl",
@@ -22643,7 +22729,7 @@ async function evaluateMemoryRecallFixtures(options) {
22643
22729
  for (const fixture of fixtures) {
22644
22730
  const materialized = materializeFixture(fixture);
22645
22731
  for (const providerName of providers) {
22646
- const tempRoot = await fs16.realpath(await fs16.mkdtemp(path46.join(os8.tmpdir(), "swarm-memory-eval-")));
22732
+ const tempRoot = await fs16.realpath(await fs16.mkdtemp(path46.join(os9.tmpdir(), "swarm-memory-eval-")));
22647
22733
  const provider = createEvaluationProvider(providerName, tempRoot);
22648
22734
  try {
22649
22735
  await provider.initialize?.();
@@ -22976,7 +23062,7 @@ var CuratorOutputMemoryDecisionSchema = exports_external.object({
22976
23062
  curatorMemoryDecisions: exports_external.array(CuratorMemoryDecisionSchema).max(20).optional()
22977
23063
  }).passthrough();
22978
23064
  // src/memory/consolidation-log.ts
22979
- import { appendFile as appendFile3, mkdir as mkdir11, readFile as readFile15 } from "fs/promises";
23065
+ import { appendFile as appendFile3, mkdir as mkdir12, readFile as readFile15 } from "fs/promises";
22980
23066
  import * as path47 from "path";
22981
23067
  var LOG_RELATIVE_PATH = path47.join("memory", "consolidation-log.jsonl");
22982
23068
  async function readConsolidationLog(directory) {
@@ -23060,7 +23146,7 @@ async function handleMemoryStatusCommand(directory, _args) {
23060
23146
  `- Provider: \`${config.provider}\``,
23061
23147
  `- Storage: \`${storageDir}\``,
23062
23148
  `- SQLite path: \`${sqlitePath}\``,
23063
- `- SQLite database exists: \`${existsSync29(sqlitePath)}\``,
23149
+ `- SQLite database exists: \`${existsSync30(sqlitePath)}\``,
23064
23150
  `- Automatic destructive cleanup: \`disabled\``,
23065
23151
  "",
23066
23152
  "### Legacy JSONL"
@@ -23962,8 +24048,21 @@ async function listMergeGroupRuns(directory, repoFullName, prNumber) {
23962
24048
  }
23963
24049
  return { runs: parseMergeGroupRuns(result.stdout, prNumber) };
23964
24050
  }
24051
+ function formatMergeGroupStatus(status, conclusion, htmlUrl) {
24052
+ if (!status)
24053
+ return "Merge group: unknown";
24054
+ const parts = [`Merge group: ${status}`];
24055
+ if (conclusion) {
24056
+ parts.push(conclusion);
24057
+ }
24058
+ if (htmlUrl) {
24059
+ parts.push(`(${htmlUrl})`);
24060
+ }
24061
+ return parts.join(" ");
24062
+ }
23965
24063
  var _internals35 = {
23966
24064
  formatRelativeTime,
24065
+ formatMergeGroupStatus,
23967
24066
  listActive,
23968
24067
  listMergeGroupRuns,
23969
24068
  parseMergeGroupRuns
@@ -24007,6 +24106,7 @@ async function handlePrMonitorStatusCommand(directory, _args, sessionID, source)
24007
24106
  }
24008
24107
  lines.push(` Last checked: ${formatRelativeTime(sub.lastCheckedAt)}`);
24009
24108
  lines.push(` Watching: ${sub.isWatching ? "yes" : "no"}`);
24109
+ lines.push(` ${formatMergeGroupStatus(sub.mergeGroupRunStatus, sub.mergeGroupRunConclusion, sub.mergeGroupRunHtmlUrl)}`);
24010
24110
  lines.push(` Errors: ${sub.errorCount}`);
24011
24111
  if (i < subs.length - 1) {
24012
24112
  lines.push("");
@@ -26698,7 +26798,7 @@ var DISPATCH_FRAMEWORK_MAP = {
26698
26798
  };
26699
26799
  async function detectTestFrameworkViaDispatch(cwd) {
26700
26800
  try {
26701
- const { pickBackend } = await import("./dispatch-zr1xja4t.js");
26801
+ const { pickBackend } = await import("./dispatch-wst7bypk.js");
26702
26802
  const backend = await pickBackend(cwd);
26703
26803
  if (!backend?.selectTestFramework)
26704
26804
  return "none";
@@ -26714,7 +26814,7 @@ async function buildTestCommandViaDispatch(framework, scope, files, coverage, ba
26714
26814
  if (framework === "none")
26715
26815
  return null;
26716
26816
  try {
26717
- const { pickBackend } = await import("./dispatch-zr1xja4t.js");
26817
+ const { pickBackend } = await import("./dispatch-wst7bypk.js");
26718
26818
  const backend = await pickBackend(baseDir);
26719
26819
  if (backend?.buildTestCommand) {
26720
26820
  const cmd = backend.buildTestCommand(framework, files, baseDir, {
@@ -26734,7 +26834,7 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
26734
26834
  if (framework === "none")
26735
26835
  return null;
26736
26836
  try {
26737
- const { pickBackend } = await import("./dispatch-zr1xja4t.js");
26837
+ const { pickBackend } = await import("./dispatch-wst7bypk.js");
26738
26838
  const backend = await pickBackend(baseDir);
26739
26839
  if (!backend?.parseTestOutput)
26740
26840
  return null;
@@ -32266,13 +32366,13 @@ function buildStatusMessage2(session, directory, sessionID) {
32266
32366
  }
32267
32367
 
32268
32368
  // src/commands/unlink.ts
32269
- import { existsSync as existsSync40 } from "fs";
32369
+ import { existsSync as existsSync41 } from "fs";
32270
32370
  import * as path65 from "path";
32271
32371
  var DEDUP_THRESHOLD2 = 0.6;
32272
32372
  async function copySharedKnowledgeToLocal(linkDir, localSwarmDir) {
32273
32373
  const sharedPath = path65.join(linkDir, "knowledge.jsonl");
32274
32374
  const localPath = path65.join(localSwarmDir, "knowledge.jsonl");
32275
- if (!existsSync40(sharedPath))
32375
+ if (!existsSync41(sharedPath))
32276
32376
  return 0;
32277
32377
  const sharedEntries = await readKnowledge(sharedPath);
32278
32378
  if (sharedEntries.length === 0)
@@ -32468,7 +32568,7 @@ function buildDetailedHelp(commandName, entry) {
32468
32568
  async function handleHelpCommand(ctx) {
32469
32569
  const targetCommand = ctx.args.join(" ");
32470
32570
  if (!targetCommand) {
32471
- const { buildHelpText } = await import("./index-kf2h31c7.js");
32571
+ const { buildHelpText } = await import("./index-hy5r0mgf.js");
32472
32572
  return buildHelpText();
32473
32573
  }
32474
32574
  const tokens = targetCommand.split(/\s+/);
@@ -32477,7 +32577,7 @@ async function handleHelpCommand(ctx) {
32477
32577
  return _internals48.buildDetailedHelp(resolved.key, resolved.entry);
32478
32578
  }
32479
32579
  const similar = _internals48.findSimilarCommands(targetCommand);
32480
- const { buildHelpText: fullHelp } = await import("./index-kf2h31c7.js");
32580
+ const { buildHelpText: fullHelp } = await import("./index-hy5r0mgf.js");
32481
32581
  if (similar.length > 0) {
32482
32582
  return `Command '/swarm ${targetCommand}' not found.
32483
32583
 
@@ -32610,7 +32710,7 @@ var COMMAND_REGISTRY = {
32610
32710
  },
32611
32711
  "guardrail explain": {
32612
32712
  handler: async (ctx) => {
32613
- const { handleGuardrailExplain } = await import("./guardrail-explain-8w9rkdjx.js");
32713
+ const { handleGuardrailExplain } = await import("./guardrail-explain-gv1ht6b0.js");
32614
32714
  return handleGuardrailExplain(ctx.directory, ctx.args);
32615
32715
  },
32616
32716
  description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
@@ -32620,7 +32720,7 @@ var COMMAND_REGISTRY = {
32620
32720
  },
32621
32721
  "guardrail-log": {
32622
32722
  handler: async (ctx) => {
32623
- const { handleGuardrailLog } = await import("./guardrail-log-973nan7m.js");
32723
+ const { handleGuardrailLog } = await import("./guardrail-log-xjgr00eq.js");
32624
32724
  return handleGuardrailLog(ctx.directory, ctx.args);
32625
32725
  },
32626
32726
  description: "Read the guardrail decision log (use --blocks-only for blocks)",
@@ -34589,6 +34689,18 @@ Every listed directive ID MUST appear exactly once. If a directive carries a ver
34589
34689
  FIXES: required changes if rejected
34590
34690
  Use INFO only inside ISSUES for non-blocking suggestions. RISK reflects the highest blocking severity, so it never uses INFO.
34591
34691
 
34692
+ ## MULTI-TASK COVERAGE (FR-007)
34693
+ 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:
34694
+
34695
+ [REVIEWED] | task-<taskId> | APPROVED | <brief summary>
34696
+ [REVIEWED] | task-<taskId> | REJECTED | <brief summary>
34697
+
34698
+ Example:
34699
+ [REVIEWED] | task-2.1 | APPROVED | No issues found in src/foo.ts
34700
+ [REVIEWED] | task-2.2 | REJECTED | Missing null check in bar() at line 42
34701
+
34702
+ If covering a single task only, you do not need to emit the structured verdict line.
34703
+
34592
34704
  ## OUTPUT ORDER FOR SKILL COMPLIANCE (when applicable)
34593
34705
  When SKILLS_USED_BY_CODER is provided, output TASK: immediately followed by SKILL_COMPLIANCE to ensure proper attribution:
34594
34706
  TASK: <task-id-or-unknown>
@@ -37564,7 +37676,7 @@ function hasActiveEpicMode(sessionID) {
37564
37676
  async function rehydratePrSubscriptions(sessionID, directory) {
37565
37677
  const map = new Map;
37566
37678
  try {
37567
- const { listActive: listActive2 } = await import("./pr-subscriptions-vv8byxe6.js");
37679
+ const { listActive: listActive2 } = await import("./pr-subscriptions-p8g2rzxd.js");
37568
37680
  const records = await listActive2(directory);
37569
37681
  for (const record of records) {
37570
37682
  if (record.sessionID !== sessionID)