opencode-swarm 7.113.4 → 7.114.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.
@@ -6,7 +6,7 @@ description: Protocol for splitting test files that exceed the FR-006 500-line h
6
6
 
7
7
  # Test File Split Protocol (FR-006)
8
8
 
9
- CI enforces a **hard 500-line limit** per test file (FR-006 / SC-006.1). Files exceeding this limit fail the quality gate and block PR merge. This skill covers the complete splitting protocol.
9
+ `scripts/check-test-file-cap.sh` enforces the **500-line cap** per test file (FR-006 / SC-006.1) as a **diff-scoped ratchet**: new test files over 500 lines and existing over-cap files that grew fail the quality gate and block PR merge. Pre-existing over-cap files not touched by the PR are non-blocking. Escape hatch: `TEST_CAP_ENFORCE=0` soft-warns. This skill covers the complete splitting protocol.
10
10
 
11
11
  Read first: `.opencode/skills/writing-tests/SKILL.md` (or `.claude/skills/writing-tests/SKILL.md`) for bun:test framework rules, mock isolation patterns, and file placement conventions.
12
12
 
@@ -613,7 +613,7 @@ authority checks:
613
613
 
614
614
  ## FR-006: Test File Size Limit (500 lines)
615
615
 
616
- CI enforces a **hard 500-line limit** per test file (FR-006). Files exceeding this limit fail the quality gate and block PR merge.
616
+ `scripts/check-test-file-cap.sh` enforces the **500-line cap** per test file (FR-006) as a **diff-scoped ratchet**: new test files over 500 lines and existing over-cap files that grew fail the quality gate and block PR merge. Pre-existing over-cap files not touched by the PR are non-blocking. Escape hatch: `TEST_CAP_ENFORCE=0` soft-warns (use only for a deliberate growth PR).
617
617
 
618
618
  ### Checking file length
619
619
 
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  createCuratorLLMDelegate
4
- } from "./index-ct9e0y0q.js";
4
+ } from "./index-zezjy05g.js";
5
5
  import"./index-g6va6n3t.js";
6
6
  import"./index-c8s9a3zh.js";
7
7
  import"./index-2148358e.js";
@@ -14,7 +14,7 @@ import {
14
14
  runCuratorInit,
15
15
  runCuratorPhase,
16
16
  writeCuratorSummary
17
- } from "./index-ct9e0y0q.js";
17
+ } from "./index-zezjy05g.js";
18
18
  import"./index-g6va6n3t.js";
19
19
  import"./index-c8s9a3zh.js";
20
20
  import"./index-2148358e.js";
@@ -1,8 +1,8 @@
1
1
  // @bun
2
2
  import {
3
3
  handleGuardrailExplain
4
- } from "./index-10v7hrkj.js";
5
- import"./index-ct9e0y0q.js";
4
+ } from "./index-jhdv0jdf.js";
5
+ import"./index-zezjy05g.js";
6
6
  import"./index-g6va6n3t.js";
7
7
  import"./index-c8s9a3zh.js";
8
8
  import"./index-2148358e.js";
@@ -6,7 +6,7 @@ import {
6
6
  isHiveEligible,
7
7
  promoteFromSwarm,
8
8
  promoteToHive
9
- } from "./index-ct9e0y0q.js";
9
+ } from "./index-zezjy05g.js";
10
10
  import"./index-g6va6n3t.js";
11
11
  import"./index-c8s9a3zh.js";
12
12
  import"./index-2148358e.js";
@@ -12,7 +12,7 @@ import {
12
12
  detectPosixWrites,
13
13
  detectWindowsWrites,
14
14
  resolveWriteTargets
15
- } from "./index-ct9e0y0q.js";
15
+ } from "./index-zezjy05g.js";
16
16
  import {
17
17
  checkFileAuthority,
18
18
  classifyFile,
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  handleGuardrailExplain
4
- } from "./index-10v7hrkj.js";
4
+ } from "./index-jhdv0jdf.js";
5
5
  import {
6
6
  handleGuardrailLog
7
7
  } from "./index-xbe1wtme.js";
@@ -81,7 +81,7 @@ import {
81
81
  handleWriteRetroCommand,
82
82
  normalizeSwarmCommandInput,
83
83
  resolveCommand
84
- } from "./index-ct9e0y0q.js";
84
+ } from "./index-zezjy05g.js";
85
85
  import"./index-g6va6n3t.js";
86
86
  import"./index-c8s9a3zh.js";
87
87
  import"./index-2148358e.js";
@@ -10432,11 +10432,11 @@ var _internals12 = {
10432
10432
  return KnowledgeConfigSchema2.parse({});
10433
10433
  },
10434
10434
  applyCuratorKnowledgeUpdates: async (directory, recommendations, knowledgeConfig) => {
10435
- const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-nh9raf1a.js");
10435
+ const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-wvv628sv.js");
10436
10436
  return applyCuratorKnowledgeUpdates2(directory, recommendations, knowledgeConfig);
10437
10437
  },
10438
10438
  checkHivePromotions: async (entries, knowledgeConfig) => {
10439
- const { checkHivePromotions } = await import("./hive-promoter-c0fd3j02.js");
10439
+ const { checkHivePromotions } = await import("./hive-promoter-1qkybw79.js");
10440
10440
  return checkHivePromotions(entries, knowledgeConfig);
10441
10441
  },
10442
10442
  applyProposalTriage: async (directory, triage) => {
@@ -17586,8 +17586,8 @@ var _internals24 = {
17586
17586
  loadCuratorDeps: async () => {
17587
17587
  const [{ CuratorConfigSchema }, curator, { createCuratorLLMDelegate: createCuratorLLMDelegate2 }] = await Promise.all([
17588
17588
  import("./schema-e5kd993s.js"),
17589
- import("./curator-nh9raf1a.js"),
17590
- import("./curator-llm-factory-b3g0g0cd.js")
17589
+ import("./curator-wvv628sv.js"),
17590
+ import("./curator-llm-factory-awp6xgvt.js")
17591
17591
  ]);
17592
17592
  return { CuratorConfigSchema, curator, createCuratorLLMDelegate: createCuratorLLMDelegate2 };
17593
17593
  }
@@ -18083,7 +18083,7 @@ import { fileURLToPath } from "url";
18083
18083
  // package.json
18084
18084
  var package_default = {
18085
18085
  name: "opencode-swarm",
18086
- version: "7.113.4",
18086
+ version: "7.114.0",
18087
18087
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
18088
18088
  main: "dist/index.js",
18089
18089
  types: "dist/index.d.ts",
@@ -18177,6 +18177,7 @@ var package_default = {
18177
18177
  "lint:ci": "biome ci .",
18178
18178
  "test:unit:ci": "bun scripts/ci/run-unit-tests-local.ts",
18179
18179
  "drift:check": "bun run scripts/drift-check.ts",
18180
+ "drift:fix": "bun run scripts/drift-check.ts --fix --confirm",
18180
18181
  format: "biome format . --write",
18181
18182
  check: "biome check --write .",
18182
18183
  dev: "bun run build && opencode",
@@ -32211,7 +32212,9 @@ var DEFAULT_CONTEXT_BUDGET_CONFIG = {
32211
32212
  var _internals47 = {
32212
32213
  loadLeanTurboRunState,
32213
32214
  hasActiveLeanTurbo,
32214
- hasActiveFullAuto
32215
+ hasActiveFullAuto,
32216
+ getActiveFullAutoSessionID,
32217
+ loadFullAutoRunState
32215
32218
  };
32216
32219
  function readSpecStalenessSnapshot(directory) {
32217
32220
  try {
@@ -32309,6 +32312,21 @@ async function getStatusData(directory, agents) {
32309
32312
  status.pendingProposals = await countProposals(directory);
32310
32313
  status.unactionableQueueDepth = await safeLineCount(resolveUnactionablePath(directory));
32311
32314
  status.insightCandidatesPending = await safeLineCount(validateSwarmPath(directory, "insight-candidates.jsonl"));
32315
+ status.fullAutoActive = _internals47.hasActiveFullAuto();
32316
+ if (status.fullAutoActive) {
32317
+ const sid = _internals47.getActiveFullAutoSessionID();
32318
+ if (sid) {
32319
+ const runState = _internals47.loadFullAutoRunState(directory, sid);
32320
+ if (runState?.lastEscalation) {
32321
+ status.fullAutoEscalation = {
32322
+ reason: runState.lastEscalation.reason,
32323
+ interactionCount: runState.lastEscalation.interactionCount,
32324
+ deadlockCount: runState.lastEscalation.deadlockCount,
32325
+ phase: runState.lastEscalation.phase
32326
+ };
32327
+ }
32328
+ }
32329
+ }
32312
32330
  return enrichWithLeanTurbo(status, directory);
32313
32331
  }
32314
32332
  function enrichWithLeanTurbo(status, directory) {
@@ -32364,7 +32382,6 @@ function enrichWithLeanTurbo(status, directory) {
32364
32382
  }
32365
32383
  }
32366
32384
  }
32367
- status.fullAutoActive = _internals47.hasActiveFullAuto();
32368
32385
  return status;
32369
32386
  }
32370
32387
  function formatStatusMarkdown(status) {
@@ -32405,13 +32422,19 @@ function formatStatusMarkdown(status) {
32405
32422
  } else {
32406
32423
  lines.push(`**Turbo**: standard`);
32407
32424
  }
32408
- if (status.fullAutoActive) {
32409
- lines.push(`**Full-Auto**: active`);
32410
- }
32411
32425
  } else if (status.turboStrategy === undefined && status.turboMode === true) {
32412
32426
  lines.push("");
32413
32427
  lines.push("**TURBO MODE**: active");
32414
32428
  }
32429
+ if (status.fullAutoActive) {
32430
+ lines.push("");
32431
+ lines.push("**Full-Auto**: active");
32432
+ if (status.fullAutoEscalation) {
32433
+ const e = status.fullAutoEscalation;
32434
+ const phaseStr = e.phase !== undefined ? ` | Phase ${e.phase}` : "";
32435
+ lines.push(` - Escalation: ${e.reason} (interactions=${e.interactionCount}, deadlocks=${e.deadlockCount}${phaseStr})`);
32436
+ }
32437
+ }
32415
32438
  if (status.contextBudgetPct !== null && status.contextBudgetPct > 0) {
32416
32439
  const pct = status.contextBudgetPct.toFixed(1);
32417
32440
  const budgetTokens = DEFAULT_CONTEXT_BUDGET_CONFIG.budgetTokens;
@@ -32949,7 +32972,7 @@ function buildDetailedHelp(commandName, entry) {
32949
32972
  async function handleHelpCommand(ctx) {
32950
32973
  const targetCommand = ctx.args.join(" ");
32951
32974
  if (!targetCommand) {
32952
- const { buildHelpText } = await import("./index-5yzr9fk6.js");
32975
+ const { buildHelpText } = await import("./index-p35ayncy.js");
32953
32976
  return buildHelpText();
32954
32977
  }
32955
32978
  const tokens = targetCommand.split(/\s+/);
@@ -32958,7 +32981,7 @@ async function handleHelpCommand(ctx) {
32958
32981
  return _internals49.buildDetailedHelp(resolved.key, resolved.entry);
32959
32982
  }
32960
32983
  const similar = _internals49.findSimilarCommands(targetCommand);
32961
- const { buildHelpText: fullHelp } = await import("./index-5yzr9fk6.js");
32984
+ const { buildHelpText: fullHelp } = await import("./index-p35ayncy.js");
32962
32985
  if (similar.length > 0) {
32963
32986
  return `Command '/swarm ${targetCommand}' not found.
32964
32987
 
@@ -33091,7 +33114,7 @@ var COMMAND_REGISTRY = {
33091
33114
  },
33092
33115
  "guardrail explain": {
33093
33116
  handler: async (ctx) => {
33094
- const { handleGuardrailExplain } = await import("./guardrail-explain-wpv5eskq.js");
33117
+ const { handleGuardrailExplain } = await import("./guardrail-explain-hhdtrm60.js");
33095
33118
  return handleGuardrailExplain(ctx.directory, ctx.args);
33096
33119
  },
33097
33120
  description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
@@ -33101,7 +33124,7 @@ var COMMAND_REGISTRY = {
33101
33124
  },
33102
33125
  "guardrail-explain": {
33103
33126
  handler: async (ctx) => {
33104
- const { handleGuardrailExplain } = await import("./guardrail-explain-wpv5eskq.js");
33127
+ const { handleGuardrailExplain } = await import("./guardrail-explain-hhdtrm60.js");
33105
33128
  return handleGuardrailExplain(ctx.directory, ctx.args);
33106
33129
  },
33107
33130
  description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
@@ -39053,6 +39076,20 @@ function hasActiveFullAuto(sessionID) {
39053
39076
  }
39054
39077
  return false;
39055
39078
  }
39079
+ function getActiveFullAutoSessionID() {
39080
+ let activeId;
39081
+ let activeLastToolCall = -1;
39082
+ for (const [id, session] of swarmState.agentSessions) {
39083
+ if (session.fullAutoMode !== true)
39084
+ continue;
39085
+ const lastToolCall = session.lastToolCallTime ?? 0;
39086
+ if (activeId === undefined || lastToolCall > activeLastToolCall) {
39087
+ activeId = id;
39088
+ activeLastToolCall = lastToolCall;
39089
+ }
39090
+ }
39091
+ return activeId;
39092
+ }
39056
39093
  function hasActiveLeanTurbo(sessionID) {
39057
39094
  if (sessionID) {
39058
39095
  const session = swarmState.agentSessions.get(sessionID);
package/dist/cli/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  getPluginLockFilePaths,
8
8
  package_default,
9
9
  resolveCommand
10
- } from "./index-ct9e0y0q.js";
10
+ } from "./index-zezjy05g.js";
11
11
  import"./index-g6va6n3t.js";
12
12
  import"./index-c8s9a3zh.js";
13
13
  import"./index-2148358e.js";
@@ -14,10 +14,20 @@
14
14
  * Architect MODE skills whose `.opencode` and `.claude` mirrors must be
15
15
  * byte-identical. `.opencode` is the operative protocol loaded by
16
16
  * `src/agents/architect.ts` MODE stubs; the `.claude` mirror must match so
17
- * Claude Code and OpenCode sessions cannot diverge silently. Tuple shape is
18
- * `[slug, opencodePath, claudePath]`.
17
+ * Claude Code and OpenCode sessions cannot diverge silently.
18
+ *
19
+ * `canonical` records which side wins when they drift (fix direction only;
20
+ * detection is symmetric). For architect MODE skills `.opencode` is always
21
+ * canonical because it is the operative protocol the MODE stubs load. Issue
22
+ * #1781 E3 added this field so `drift:fix` can copy the canonical side to the
23
+ * mirror without guessing.
19
24
  */
20
- export declare const MIRRORED_ARCHITECT_MODE_SKILLS: readonly [readonly ["brainstorm", ".opencode/skills/brainstorm/SKILL.md", ".claude/skills/brainstorm/SKILL.md"], readonly ["specify", ".opencode/skills/specify/SKILL.md", ".claude/skills/specify/SKILL.md"], readonly ["clarify-spec", ".opencode/skills/clarify-spec/SKILL.md", ".claude/skills/clarify-spec/SKILL.md"], readonly ["resume", ".opencode/skills/resume/SKILL.md", ".claude/skills/resume/SKILL.md"], readonly ["clarify", ".opencode/skills/clarify/SKILL.md", ".claude/skills/clarify/SKILL.md"], readonly ["discover", ".opencode/skills/discover/SKILL.md", ".claude/skills/discover/SKILL.md"], readonly ["consult", ".opencode/skills/consult/SKILL.md", ".claude/skills/consult/SKILL.md"], readonly ["pre-phase-briefing", ".opencode/skills/pre-phase-briefing/SKILL.md", ".claude/skills/pre-phase-briefing/SKILL.md"], readonly ["council", ".opencode/skills/council/SKILL.md", ".claude/skills/council/SKILL.md"], readonly ["deep-dive", ".opencode/skills/deep-dive/SKILL.md", ".claude/skills/deep-dive/SKILL.md"], readonly ["deep-research", ".opencode/skills/deep-research/SKILL.md", ".claude/skills/deep-research/SKILL.md"], readonly ["issue-ingest", ".opencode/skills/issue-ingest/SKILL.md", ".claude/skills/issue-ingest/SKILL.md"], readonly ["plan", ".opencode/skills/plan/SKILL.md", ".claude/skills/plan/SKILL.md"], readonly ["critic-gate", ".opencode/skills/critic-gate/SKILL.md", ".claude/skills/critic-gate/SKILL.md"], readonly ["design-docs", ".opencode/skills/design-docs/SKILL.md", ".claude/skills/design-docs/SKILL.md"]];
25
+ export declare const MIRRORED_ARCHITECT_MODE_SKILLS: Array<{
26
+ slug: string;
27
+ opencodePath: string;
28
+ claudePath: string;
29
+ canonical: '.opencode' | '.claude';
30
+ }>;
21
31
  /**
22
32
  * Architect MODE skills where `.opencode` is the full operative protocol and
23
33
  * `.claude` is an intentionally different surface. Both must exist; byte
@@ -37,6 +37,19 @@ export interface FullAutoRunState {
37
37
  terminateReason?: string;
38
38
  /** Consecutive oversight dispatch failures for auto-degrade. */
39
39
  consecutiveOversightFailures?: number;
40
+ /**
41
+ * Issue #1781 E2: the most recent oversight-escalation detail, persisted so
42
+ * `/swarm status` can surface the reason + interaction/deadlock counts +
43
+ * phase without parsing the human-readable `.swarm/escalation-report.md`.
44
+ * Updated atomically by `recordFullAutoEscalation` at escalation time.
45
+ */
46
+ lastEscalation?: {
47
+ reason: string;
48
+ interactionCount: number;
49
+ deadlockCount: number;
50
+ phase?: number;
51
+ escalatedAt: string;
52
+ };
40
53
  }
41
54
  export interface FullAutoPersistedState {
42
55
  version: 2;
@@ -129,6 +142,19 @@ export declare function resetFullAutoDenials(directory: string, sessionID: strin
129
142
  */
130
143
  export declare function nextFullAutoOversightSequence(directory: string): number;
131
144
  export declare function recordFullAutoOversight(directory: string, sessionID: string, verdict: string, reason: string): FullAutoRunState | undefined;
145
+ /**
146
+ * Issue #1781 E2: persist the most recent oversight-escalation detail
147
+ * (reason, interaction/deadlock counts, phase) to the durable run state so
148
+ * `/swarm status` can surface it. Called from `handleEscalation` in
149
+ * `src/hooks/full-auto-intercept.ts` alongside the existing pause/terminate
150
+ * state writes — those writes spread `...state`, so this field survives them.
151
+ */
152
+ export declare function recordFullAutoEscalation(directory: string, sessionID: string, detail: {
153
+ reason: string;
154
+ interactionCount: number;
155
+ deadlockCount: number;
156
+ phase?: number;
157
+ }): FullAutoRunState | undefined;
132
158
  export interface DenialLimitDecision {
133
159
  pause: boolean;
134
160
  reason?: string;