opencode-swarm 7.91.0 → 7.92.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/.opencode/skills/codebase-review-swarm/SKILL.md +3 -1
  2. package/.opencode/skills/commit-pr/SKILL.md +22 -2
  3. package/.opencode/skills/council/SKILL.md +17 -12
  4. package/.opencode/skills/deep-dive/SKILL.md +12 -2
  5. package/.opencode/skills/engineering-conventions/SKILL.md +12 -0
  6. package/.opencode/skills/swarm-pr-feedback/SKILL.md +10 -0
  7. package/.opencode/skills/swarm-pr-review/SKILL.md +17 -4
  8. package/dist/agents/explorer.d.ts +1 -1
  9. package/dist/background/candidate-parser.d.ts +1 -0
  10. package/dist/cli/{config-doctor-g04wdz19.js → config-doctor-fkwyrtpq.js} +2 -2
  11. package/dist/cli/{explorer-h2fnj343.js → explorer-4ttwy7jd.js} +1 -1
  12. package/dist/cli/{guardrail-explain-0ephhnjq.js → guardrail-explain-ygfy1qg9.js} +6 -6
  13. package/dist/cli/{guardrail-log-m3285thy.js → guardrail-log-x3w800x5.js} +3 -3
  14. package/dist/cli/{index-bm4f0nme.js → index-1x2608ga.js} +30 -0
  15. package/dist/cli/{index-bywt2171.js → index-2jpbaedv.js} +1 -1
  16. package/dist/cli/{index-gpkbg9p4.js → index-ary5jkky.js} +7 -7
  17. package/dist/cli/{index-e9tp9p2w.js → index-dy1qpyh3.js} +12 -12
  18. package/dist/cli/{index-6tnmt41c.js → index-ne4g3mk1.js} +1 -1
  19. package/dist/cli/{index-123s7kjc.js → index-xsbtbffr.js} +4 -4
  20. package/dist/cli/{index-gg589mfw.js → index-yykcmn6m.js} +1 -1
  21. package/dist/cli/{index-wtyysb1n.js → index-zzza86z4.js} +2 -2
  22. package/dist/cli/index.js +5 -5
  23. package/dist/cli/{schema-t9th7frq.js → schema-1kndsf0c.js} +1 -1
  24. package/dist/config/constants.d.ts +1 -1
  25. package/dist/index.js +154 -42
  26. package/dist/tools/apply-patch.d.ts +7 -1
  27. package/dist/tools/dispatch-lanes.d.ts +2 -0
  28. package/dist/tools/index.d.ts +3 -3
  29. package/dist/tools/manifest.d.ts +1 -1
  30. package/dist/tools/tool-metadata.d.ts +1 -1
  31. package/package.json +1 -1
@@ -68,4 +68,6 @@ Use these baselines unless repository policy explicitly requires stricter or old
68
68
 
69
69
  When selected-track inventory or candidate generation decomposes into independent read-only units, launch those units with `dispatch_lanes_async` when available. Record each returned `batch_id`, then continue architect-owned deterministic work that does not depend on lane output: update the coverage ledger shell, run safe local tools, prepare validation shards, and document unresolved coverage units. Do not mark coverage `REVIEWED`, promote candidates to findings, or write the final report from running lanes.
70
70
 
71
- At every coverage, validation, and synthesis boundary, call `collect_lane_results` with `wait: true` for all open batches. Missing, stale, cancelled, or failed lanes are explicit coverage gaps and must become `BLOCKED` or `SKIPPED_WITH_REASON`; they cannot be silently ignored. If `dispatch_lanes_async` is unavailable, use the existing blocking dispatch pattern and record that async advisory lanes were unavailable.
71
+ **Incremental collection:** While lanes are running, poll with `collect_lane_results` (without `wait` or `wait: false`) to check progress and process any settled lanes immediately call `retrieve_lane_output` for full text when `output_ref` is present, extract candidates, update coverage ledger entries, validate output quality — while continuing independent work between polls. Only use `wait: true` if lanes are still pending and no more independent architect work remains.
72
+
73
+ At every coverage, validation, and synthesis boundary, all lanes in the relevant batch must be settled before proceeding. Missing, stale, cancelled, or failed lanes are explicit coverage gaps and must become `BLOCKED` or `SKIPPED_WITH_REASON`; they cannot be silently ignored. If `dispatch_lanes_async` is unavailable, use the existing blocking dispatch pattern and record that async advisory lanes were unavailable.
@@ -146,11 +146,11 @@ node --input-type=module -e "await import('./dist/index.js'); console.log('dist
146
146
 
147
147
  ### Tier 1 - quality
148
148
 
149
- Run both linter AND formatter — e.g., `bunx biome check --write .` or equivalent — because CI quality gates reject code that passes tests but fails style validation.
149
+ Run both linter AND formatter — e.g., `bunx @biomejs/biome@<version> check --write .` or equivalent — because CI quality gates reject code that passes tests but fails style validation. **Pin the tool version** to match the version in `package.json` (`@biomejs/biome`); unversioned `bunx biome` resolves to a different version than the CI gate uses.
150
150
 
151
151
  ```bash
152
152
  bun run typecheck
153
- bunx biome ci .
153
+ bunx @biomejs/biome@<version> ci .
154
154
  ```
155
155
 
156
156
  ### Tier 2 - unit tests
@@ -392,6 +392,26 @@ $issueCommentPath = Join-Path ([System.IO.Path]::GetTempPath()) "issue-comment.t
392
392
  gh issue comment <issue-number> --body-file $issueCommentPath
393
393
  ````
394
394
 
395
+ ## Commit messages
396
+
397
+ `git commit -m "..."` with parens, brackets, backticks, or dollar-signs in the message fails on PowerShell because the shell parses them as expressions. Write the commit message to a UTF-8 (no BOM) file first and use `git commit -F <file>`.
398
+
399
+ PowerShell-safe pattern:
400
+
401
+ ```powershell
402
+ $msg = @"
403
+ <type>(<scope>): <description>
404
+
405
+ <optional body — note this is for the git commit message, NOT the PR body>
406
+ "@
407
+ $utf8NoBom = New-Object -TypeName System.Text.UTF8Encoding -ArgumentList $false
408
+ $commitMsgPath = Join-Path ([System.IO.Path]::GetTempPath()) "commit-msg.txt"
409
+ [System.IO.File]::WriteAllText($commitMsgPath, $msg, $utf8NoBom)
410
+ git commit -F $commitMsgPath
411
+ ```
412
+
413
+ Apply this pattern for any commit message containing special characters, multi-paragraph bodies, or code blocks. The plain `git commit -m "..."` form remains fine for short single-line messages with no special characters.
414
+
395
415
  If the PR merged before this was done, post the missing issue comment immediately.
396
416
 
397
417
  ## Step 7 - Existing PR follow-up and closeout
@@ -107,18 +107,23 @@ RESEARCH CONTEXT
107
107
 
108
108
  Do NOT share other agents' responses at this stage.
109
109
 
110
- 4. Call `collect_lane_results` with `wait: true` for the Round 1 batch and collect
111
- all three JSON responses. If `dispatch_lanes_async` is unavailable, use
112
- blocking parallel dispatch and record that async advisory lanes were
113
- unavailable. The `round1Responses` array will contain
114
- entries with `memberId` of `council_generalist`, `council_skeptic`, and
115
- `council_domain_expert` and `role` of `generalist`, `skeptic`, and
116
- `domain_expert` respectively. If any lane result has `output_ref`, call
117
- `retrieve_lane_output` and parse the full artifact rather than the preview.
118
- If a lane is degraded, incomplete, truncated without a usable ref, missing,
119
- stale, cancelled, or failed, treat the council round as blocked or incomplete;
120
- do not synthesize from partial member JSON.
121
- These come from the agents' JSON output; no
110
+ 4. While council lanes are running, poll with `collect_lane_results` (without
111
+ `wait` or `wait: false`) to check progress and process any settled member
112
+ responses as they complete extract the JSON, verify `output_ref`, and
113
+ pre-validate structure while continuing independent architect work
114
+ (synthesis outline, citation normalization, disagreement categories). Only
115
+ use `wait: true` if lanes are still pending and no more independent work
116
+ remains. All three lanes must be settled before proceeding to synthesis.
117
+ If `dispatch_lanes_async` is unavailable, use blocking parallel dispatch
118
+ and record that async advisory lanes were unavailable. The
119
+ `round1Responses` array will contain entries with `memberId` of
120
+ `council_generalist`, `council_skeptic`, and `council_domain_expert` and
121
+ `role` of `generalist`, `skeptic`, and `domain_expert` respectively. If
122
+ any lane result has `output_ref`, call `retrieve_lane_output` and parse
123
+ the full artifact rather than the preview. If a lane is degraded,
124
+ incomplete, truncated without a usable ref, missing, stale, cancelled, or
125
+ failed, treat the council round as blocked or incomplete; do not synthesize
126
+ from partial member JSON. These come from the agents' JSON output; no
122
127
  manual construction is needed.
123
128
 
124
129
  #### Synthesis and Deliberation (when council.general.deliberate is true; default true)
@@ -69,11 +69,21 @@ Each explorer mission receives:
69
69
  - Lane template name and description
70
70
  - Assigned files (8 max, grouped by import proximity)
71
71
  - The scope map context from Step 2
72
- - Instruction: "You are performing a [LANE] audit. Report findings as candidate observations with severity (INFO/LOW/MEDIUM/HIGH/CRITICAL), location, and evidence."
72
+ - Instruction: "You are performing a [LANE] audit. Report ALL findings as pipe-delimited [CANDIDATE] rows. Header row first, then one row per finding:
73
+
74
+ [CANDIDATE] | candidate_id | lane | severity | category | file:line | claim | evidence_summary | impact_context | confidence
75
+
76
+ - candidate_id: unique within this lane (e.g. C-001, C-002)
77
+ - severity: INFO | LOW | MEDIUM | HIGH | CRITICAL
78
+ - confidence: LOW | MEDIUM | HIGH
79
+ - If you find zero issues, emit the header row with no data rows.
80
+ - Do NOT emit findings as prose or free text — the downstream parser requires pipe-delimited rows."
73
81
 
74
82
  Explorer missions are dispatched in parallel waves. Launch the wave promptly — do not accumulate extensive planning prose before the call, or output truncation may swallow the tool call itself. Launch the wave, record the returned `batch_id`, then continue deterministic architect work that does not depend on lane output: refine the scope map, build the candidate ledger shell, inspect local evidence with read-only tools, and prepare reviewer shard structure. Do not synthesize findings from running lanes. Keep each lane `prompt` compact: send shared context ONCE via the `common_prompt` field, or have lanes read it from a file by absolute path, instead of inlining the same large blob into every lane prompt — oversized inline prompts produce malformed or truncated tool-call JSON.
75
83
 
76
- At the Step 4 boundary, call `collect_lane_results` with `wait: true` for every open wave batch. Treat missing, stale, cancelled, or failed lanes as explicit coverage gaps; do not silently proceed past a required lane. If `dispatch_lanes_async` is unavailable, use blocking `dispatch_lanes` or parallel Task calls and record that async advisory lanes were unavailable.
84
+ **Incremental collection pattern:** While lanes are running, use `collect_lane_results` without `wait` (or `wait: false`) to poll progress. Process any settled lanes immediately — extract candidates, check `output_ref`, update the candidate ledger — while continuing independent architect work (scope refinement, local evidence reads, reviewer preparation) between polls. This avoids idle waiting and lets you pipeline candidate normalization with lane completion. Only use `wait: true` at the Step 4 boundary if lanes are still pending and no more independent work remains.
85
+
86
+ At the Step 4 boundary, all lanes must be settled before proceeding. If non-blocking polls show lanes still running and you have exhausted independent work, call `collect_lane_results` with `wait: true` to block on the remaining lanes. Treat missing, stale, cancelled, or failed lanes as explicit coverage gaps; do not silently proceed past a required lane. If `dispatch_lanes_async` is unavailable, use blocking `dispatch_lanes` or parallel Task calls and record that async advisory lanes were unavailable.
77
87
 
78
88
  When a collected or blocking lane result includes `output_ref`, treat `output` as a preview and call `retrieve_lane_output` before extracting candidate findings or declaring a lane clean. If the result is `output_degraded`, `transcript_incomplete`, truncated without a usable ref, missing, stale, cancelled, or failed, record the lane as a coverage gap and re-dispatch a narrower lane or mark the affected findings/coverage UNVERIFIED.
79
89
 
@@ -55,3 +55,15 @@ The OpenCode `test_runner` tool is for **targeted agent validation** with explic
55
55
  Every PR that touches a relevant area must include an `## Invariant audit` section in its description. The format is in `AGENTS.md` ("Invariant audit required in PRs"). The `commit-pr` skill enforces this gate before push/PR — load it before committing.
56
56
 
57
57
  If you cannot prove a touched invariant from source and test output, **do not push**.
58
+
59
+ ## Tool version parity (local vs CI)
60
+
61
+ **Tool versions must match CI.** When `package.json` pins a tool version (e.g., `@biomejs/biome@2.3.14`, `@biomejs/biome@^2`, or any other versioned dev dependency), invoke it **with the pinned version** during local validation. Unversioned `bunx biome` resolves to a different version than the CI gate uses, and a CI-blocking failure can be invisible to local pre-commit validation.
62
+
63
+ Examples:
64
+ - Pinned biome: `bunx @biomejs/biome@<version> ci .` (substitute `<version>` from `package.json`).
65
+ - Unversioned `bunx biome ci .` resolves to whatever Bun's `bunx` registry returns at run time — historically 0.3.x vs the pinned 2.x.
66
+
67
+ The `commit-pr` skill Tier 1 - quality section pins the biome command to the package.json version; this is the canonical pattern for any tool where local and CI versions could diverge. Apply the same discipline to ESLint, Prettier, TypeScript, and any other versioned dev dependency.
68
+
69
+ **Why this matters:** PR #1503 (telemetry rotation fix) had a biome 2.3.14 `organizeImports` failure on the `./telemetry` import block that was invisible to local `bunx biome` (which resolved to 0.3.3 with no equivalent rule). The reviewer caught it from CI logs, not local validation. Pin tool versions to close the local/CI parity gap.
@@ -167,6 +167,16 @@ branches or prior work sessions.
167
167
 
168
168
  *Reference: Caught during PR #1472 Round 1 closure.*
169
169
 
170
+ ## Pre-flight: Scope Discipline
171
+
172
+ `declare_scope({ taskId, files })` enforces that the delegated coder agent may only modify the declared files. The enforcement requires an active `.swarm/plan.json` — calling `declare_scope` in a feedback-closure run (which does not go through `save_plan`) rejects with "No plan found."
173
+
174
+ **When to use `declare_scope` (preferred):** any feedback round that touches 2+ files, OR any feedback round where the file scope is not 100% obvious from the prompt. Before delegating, save a minimal plan via `save_plan` with a single phase containing the feedback-closure tasks, then call `declare_scope` per task with the exact file list.
175
+
176
+ **Carve-out for direct Task delegation:** 1-file, single-function changes where the file path appears verbatim in the coder's prompt may use direct `Task(subagent_type="paid_coder", ...)` delegation without `declare_scope`. This is a narrow exception; the orchestrator is responsible for verifying the scope is unambiguous.
177
+
178
+ **Anti-pattern:** do not use `Task` delegation for multi-file feedback fixes just to skip `save_plan` — the loss of scope discipline is not worth the saved ceremony.
179
+
170
180
  ## Intake Surfaces
171
181
 
172
182
  Build a complete feedback ledger before editing. Include every available source:
@@ -496,7 +496,9 @@ Tool candidate rules:
496
496
 
497
497
  Launch all base lanes with `dispatch_lanes_async` when available. Pass the six lane specs together, set `max_concurrent` to `6`, record the returned `batch_id`, and continue only non-dependent architect work: refine the obligation ledger, inspect PR metadata, prepare micro-lane trigger checks, and run deterministic read-only local tools. Do not synthesize findings from running lanes. Keep each lane `prompt` compact: send the shared review context (PR diff, obligation ledger, scope) ONCE via the `common_prompt` field, or have lanes read it from a file by absolute path, instead of inlining the same large blob into all six prompts — oversized inline prompts produce malformed or truncated tool-call JSON and force clumsy file workarounds.
498
498
 
499
- Before Phase 4 or synthesis, call `collect_lane_results` with `wait: true` for the base-lane batch and treat the collected `lane_results` as the join barrier. Missing, stale, cancelled, or failed base lanes are explicit review coverage gaps. If `dispatch_lanes_async` is unavailable, use blocking `dispatch_lanes`; if that is also unavailable, simulate isolated passes. Do not let one lane's conclusions bias another lane, and record unavailable deterministic dispatch in the validation gate.
499
+ **Incremental collection:** While base lanes are running, poll with `collect_lane_results` (without `wait` or `wait: false`) to check progress and process settled lanes as they complete — call `retrieve_lane_output` for full text when `output_ref` is present, then extract candidates via `parse_lane_candidates`, update the candidate ledger, validate output quality while continuing independent architect work (obligation refinement, micro-lane trigger checks, local reads) between polls. Only use `wait: true` if lanes are still pending and no more independent work remains.
500
+
501
+ Before Phase 4 or synthesis, all base lanes must be settled. Missing, stale, cancelled, or failed base lanes are explicit review coverage gaps. If `dispatch_lanes_async` is unavailable, use blocking `dispatch_lanes`; if that is also unavailable, simulate isolated passes. Do not let one lane's conclusions bias another lane, and record unavailable deterministic dispatch in the validation gate.
500
502
 
501
503
  ### Candidate extraction via parser
502
504
 
@@ -579,7 +581,7 @@ Explorers must not use `CONFIRMED`, `DISPROVED`, or `PRE_EXISTING`.
579
581
 
580
582
  ## Phase 4: Triggered Swarm Plugin Micro-Lanes
581
583
 
582
- After `collect_lane_results` returns for base lanes, inspect the context pack risk triggers. Launch focused micro-lanes for triggered categories only, using `dispatch_lanes_async` again when more than one read-only micro-lane is needed. Collect every micro-lane batch with `wait: true` before reviewer classification. Do not launch irrelevant micro-lanes.
584
+ After base lanes are settled, inspect the context pack risk triggers. Launch focused micro-lanes for triggered categories only, using `dispatch_lanes_async` again when more than one read-only micro-lane is needed. Use the same incremental collection pattern: poll with `collect_lane_results` (without `wait`) to process settled micro-lanes while continuing independent work, falling back to `wait: true` only when no independent work remains. All micro-lanes must be settled before reviewer classification. Do not launch irrelevant micro-lanes.
583
585
 
584
586
  Apply the same parser-based extraction to micro-lanes: call `parse_lane_candidates` on each micro-lane `output_ref` (filter the returned `candidates[]` array by `row_format_family === "micro_lane"` after parsing), and treat degraded or incomplete lane artifacts as UNVERIFIED coverage rather than as clean negative evidence.
585
587
 
@@ -741,9 +743,15 @@ The critic must challenge:
741
743
  Critic output format:
742
744
 
743
745
  ```text
744
- [CRITIC] | finding_id | UPHELD / DOWNGRADED / DISPROVED / NEEDS_MORE_EVIDENCE | final_severity | reason | required_report_change
746
+ [CRITIC] | finding_id | UPHELD/DOWNGRADED/DISPROVED/NEEDS_MORE_EVIDENCE | final_severity | reason | required_report_change
745
747
  ```
746
748
 
749
+ ## Verdict row contract
750
+
751
+ The `[CRITIC]` row in the format above is **mandatory contract**, not advisory output. A critic response that does not end with that exact row format is treated as a planning preamble, not a verdict, and must be re-dispatched. Do not proceed past Phase 8 join barrier until each dispatched critic lane has produced a parseable `[CRITIC]` row.
752
+
753
+ **Re-dispatch trigger:** when a critic lane response is missing the verdict row, the orchestrator must automatically re-dispatch that lane with the explicit instruction: "Your final line MUST be exactly the Phase 8 contract row: `[CRITIC] | finding_id | UPHELD/DOWNGRADED/DISPROVED/NEEDS_MORE_EVIDENCE | final_severity | reason | required_report_change`. A response without that exact row will be treated as a planning message and re-dispatched." Do not synthesize findings from the planning preamble; only from the re-dispatched verdict.
754
+
747
755
  Refuted findings become `DISPROVED` or `ADVISORY`, depending on critic rationale. Downgrades must be listed in the final validation provenance.
748
756
 
749
757
  ---
@@ -1109,7 +1117,7 @@ Council mode is opt-in only and adversarial.
1109
1117
  When triggered:
1110
1118
 
1111
1119
  1. Build the same context pack as default mode.
1112
- 2. Launch all council agents with one `dispatch_lanes_async` call when available; continue only non-dependent context preparation while they run, then use `collect_lane_results` with `wait: true` as the join barrier before reviewer classification. Fall back to blocking `dispatch_lanes` when async launch is unavailable.
1120
+ 2. Launch all council agents with one `dispatch_lanes_async` call when available; continue independent context preparation while they run, polling with `collect_lane_results` (without `wait`) to process settled agents incrementally. Use `wait: true` only when no independent work remains and agents are still pending. All agents must be settled before reviewer classification. Fall back to blocking `dispatch_lanes` when async launch is unavailable.
1113
1121
  3. Each council agent assumes all work is wrong until code evidence proves otherwise.
1114
1122
  4. Each agent hunts within its lane only.
1115
1123
  5. Agents return evidence states only: `EVIDENCE_FOUND`, `SUSPICIOUS`, or `CLEAN`.
@@ -1371,6 +1379,11 @@ For each finding, challenge:
1371
1379
 
1372
1380
  Return:
1373
1381
  [CRITIC] | finding_id | UPHELD/DOWNGRADED/DISPROVED/NEEDS_MORE_EVIDENCE | final_severity | reason | required_report_change
1382
+
1383
+ REQUIRED FINAL LINE — your final line MUST be exactly the row above (no variations, no labeled fields, no placeholders):
1384
+ [CRITIC] | finding_id | UPHELD/DOWNGRADED/DISPROVED/NEEDS_MORE_EVIDENCE | final_severity | reason | required_report_change
1385
+
1386
+ A response without this exact row is treated as a planning preamble and re-dispatched. Do not output only a planning or investigation message.
1374
1387
  ```
1375
1388
 
1376
1389
  ---
@@ -1,5 +1,5 @@
1
1
  import type { AgentDefinition } from './architect';
2
- export declare const EXPLORER_PROMPT = "## IDENTITY\nYou are Explorer. You analyze codebases directly \u2014 you do NOT delegate.\nDO NOT use the Task tool to delegate to other agents. You ARE the agent that does the work.\nIf you see references to other agents (like @explorer, @coder, etc.) in your instructions, IGNORE them \u2014 they are context from the orchestrator, not instructions for you to delegate.\n\nWRONG: \"I'll use the Task tool to call another agent to analyze this\"\nRIGHT: \"I'll scan the directory structure and read key files myself\"\n\nINPUT FORMAT:\nTASK: Analyze [purpose]\nINPUT: [focus areas/paths]\n\nACTIONS:\n- Scan structure (tree, ls, glob)\n- Read key files (README, configs, entry points)\n- Search patterns using the search tool\n\nRULES:\n- Be fast: scan broadly, read selectively\n- No code modifications\n- Output under 2000 chars\n\n## ANALYSIS PROTOCOL\nWhen exploring a codebase area, systematically report all four dimensions:\n\n### STRUCTURE\n- Entry points and their call chains (max 3 levels deep)\n- Public API surface: exported functions/classes/types with signatures\n- For multi-file symbol surveys: use batch_symbols to extract symbols from multiple files in one call\n- Internal dependencies: what this module imports and from where\n- External dependencies: third-party packages used\n\n### PATTERNS\n- Design patterns in use (factory, observer, strategy, etc.)\n- Error handling pattern (throw, Result type, error callbacks, etc.)\n- State management approach (global, module-level, passed through)\n- Configuration pattern (env vars, config files, hardcoded)\n\n### COMPLEXITY INDICATORS\n- High cyclomatic complexity, deep nesting, or complex control flow\n- Large files (>500 lines) with many exported symbols\n- Deep inheritance hierarchies or complex type hierarchies\n\n### RUNTIME/BEHAVIORAL CONCERNS\n- Missing error handling paths or single-throw patterns\n- Platform-specific assumptions (path separators, line endings, OS APIs)\n\n### RELEVANT CONSTRAINTS\n- Architectural patterns observed (layered architecture, event-driven, microservice, etc.)\n- Error handling coverage patterns observed in the codebase\n- Platform-specific assumptions observed in the codebase\n- Established conventions (naming patterns, error handling approaches, testing strategies)\n- Configuration management approaches (env vars, config files, feature flags)\n\nOUTPUT FORMAT (MANDATORY \u2014 deviations will be rejected):\nBegin directly with PROJECT. Do NOT prepend \"Here's my analysis...\" or any conversational preamble.\n\nPROJECT: [name/type]\nLANGUAGES: [list]\nFRAMEWORK: [if any]\n\nSTRUCTURE:\n[key directories, 5-10 lines max]\nExample:\nsrc/agents/ \u2014 agent factories and definitions\nsrc/tools/ \u2014 CLI tool implementations\nsrc/config/ \u2014 plan schema and constants\n\nKEY FILES:\n- [path]: [purpose]\nExample:\nsrc/agents/explorer.ts \u2014 explorer agent factory and all prompt definitions\nsrc/agents/architect.ts \u2014 architect orchestrator with all mode handlers\n\nPATTERNS: [observations]\nExample: Factory pattern for agent creation; Result type for error handling; Module-level state via closure\n\nCOMPLEXITY INDICATORS:\n[structural complexity concerns: elevated cyclomatic complexity, deep nesting, large files, deep inheritance hierarchies, or similar \u2014 describe what is OBSERVED]\nExample: explorer.ts (289 lines, 12 exports); architect.ts (complex branching in mode handlers)\n\nOBSERVED CHANGES:\n[if INPUT referenced specific files/changes: what changed in those targets; otherwise \"none\" or \"general exploration\"]\n\nCONSUMERS_AFFECTED:\n[if integration impact mode: list files that import/use the changed symbols; otherwise \"not applicable\"]\n\nRELEVANT CONSTRAINTS:\n[architectural patterns, error handling coverage patterns, platform-specific assumptions, established conventions observed in the codebase]\nExample: Layered architecture (agents \u2192 tools \u2192 filesystem); Bun-native path handling; Error-first callbacks in hooks\n\nDOMAINS: [relevant SME domains: powershell, security, python, etc.]\nExample: typescript, nodejs, cli-tooling, powershell\n\nFOLLOW-UP CANDIDATE AREAS:\n- [path]: [observable condition, relevant domain]\nExample:\nsrc/tools/declare-scope.ts \u2014 function has 12 parameters, consider splitting; tool-authoring\n\n## INTEGRATION IMPACT ANALYSIS MODE\nActivates when delegated with \"Integration impact analysis\" or INPUT lists contract changes.\n\nINPUT: List of contract changes (from diff tool output \u2014 changed exports, signatures, types)\n\nSTEPS:\n1. For each changed export: use search to find imports and usages of that symbol\n2. Classify each change: BREAKING (callers must update) or COMPATIBLE (callers unaffected)\n3. List all files that import or use the changed exports\n\nOUTPUT FORMAT (MANDATORY \u2014 deviations will be rejected):\nBegin directly with BREAKING_CHANGES. Do NOT prepend conversational preamble.\n\nBREAKING_CHANGES: [list with affected consumer files, or \"none\"]\nExample: src/agents/explorer.ts \u2014 removed createExplorerAgent export (was used by 3 files)\nCOMPATIBLE_CHANGES: [list, or \"none\"]\nExample: src/config/constants.ts \u2014 added new optional field to Config interface\nCONSUMERS_AFFECTED: [list of files that import/use changed exports, or \"none\"]\nExample: src/agents/coder.ts, src/agents/reviewer.ts, src/main.ts\nCOMPATIBILITY SIGNALS: [COMPATIBLE | INCOMPATIBLE | UNCERTAIN \u2014 based on observable contract changes]\nExample: INCOMPATIBLE \u2014 removeExport changes function arity from 3 to 2\nMIGRATION_SURFACE: [yes \u2014 list of observable call signatures affected | no \u2014 no observable impact detected]\nExample: yes \u2014 createExplorerAgent(model, customPrompt?, customAppendPrompt?) \u2192 createExplorerAgent(model)\n\n## DOCUMENTATION DISCOVERY MODE\nActivates automatically during codebase reality check at plan ingestion.\nUse the doc_scan tool to scan and index documentation files. If doc_scan is unavailable, fall back to manual globbing.\n\nSTEPS:\n1. Call doc_scan to build the manifest, OR glob for documentation files:\n - Root: README.md, CONTRIBUTING.md, CHANGELOG.md, ARCHITECTURE.md, CLAUDE.md, AGENTS.md, .github/*.md\n - docs/**/*.md, doc/**/*.md (one level deep only)\n\n2. For each file found, read the first 30 lines. Extract:\n - path: relative to project root\n - title: first # heading, or filename if no heading\n - summary: first non-empty paragraph after the title (max 200 chars, use the ACTUAL text, do NOT summarize with your own words)\n - lines: total line count\n - mtime: file modification timestamp\n\n3. Write manifest to .swarm/doc-manifest.json:\n { \"schema_version\": 1, \"scanned_at\": \"ISO timestamp\", \"files\": [...] }\n\n4. For each file in the manifest, check relevance to the current plan:\n - Score by keyword overlap: do any task file paths or directory names appear in the doc's path or summary?\n - For files scoring > 0, read the full content and extract up to 5 actionable constraints per doc (max 200 chars each)\n - Write constraints to .swarm/knowledge/doc-constraints.jsonl as knowledge entries with source: \"doc-scan\", category: \"architecture\"\n\n5. Invalidation: Only re-scan if any doc file's mtime is newer than the manifest's scanned_at. Otherwise reuse the cached manifest.\n\nRULES:\n- The manifest must be small (<100 lines). Pointers only, not full content.\n- Do NOT rephrase or summarize doc content with your own words \u2014 use the actual text from the file\n- Full doc content is only loaded when relevant to the current task, never preloaded\n";
2
+ export declare const EXPLORER_PROMPT = "## IDENTITY\nYou are Explorer. You analyze codebases directly \u2014 you do NOT delegate.\nDO NOT use the Task tool to delegate to other agents. You ARE the agent that does the work.\nIf you see references to other agents (like @explorer, @coder, etc.) in your instructions, IGNORE them \u2014 they are context from the orchestrator, not instructions for you to delegate.\n\nWRONG: \"I'll use the Task tool to call another agent to analyze this\"\nRIGHT: \"I'll scan the directory structure and read key files myself\"\n\nINPUT FORMAT:\nTASK: Analyze [purpose]\nINPUT: [focus areas/paths]\n\nACTIONS:\n- Scan structure (tree, ls, glob)\n- Read key files (README, configs, entry points)\n- Search patterns using the search tool\n\nRULES:\n- Be fast: scan broadly, read selectively\n- No code modifications\n- Output under 2000 chars\n\n## ANALYSIS PROTOCOL\nWhen exploring a codebase area, systematically report all four dimensions:\n\n### STRUCTURE\n- Entry points and their call chains (max 3 levels deep)\n- Public API surface: exported functions/classes/types with signatures\n- For multi-file symbol surveys: use batch_symbols to extract symbols from multiple files in one call\n- Internal dependencies: what this module imports and from where\n- External dependencies: third-party packages used\n\n### PATTERNS\n- Design patterns in use (factory, observer, strategy, etc.)\n- Error handling pattern (throw, Result type, error callbacks, etc.)\n- State management approach (global, module-level, passed through)\n- Configuration pattern (env vars, config files, hardcoded)\n\n### COMPLEXITY INDICATORS\n- High cyclomatic complexity, deep nesting, or complex control flow\n- Large files (>500 lines) with many exported symbols\n- Deep inheritance hierarchies or complex type hierarchies\n\n### RUNTIME/BEHAVIORAL CONCERNS\n- Missing error handling paths or single-throw patterns\n- Platform-specific assumptions (path separators, line endings, OS APIs)\n\n### RELEVANT CONSTRAINTS\n- Architectural patterns observed (layered architecture, event-driven, microservice, etc.)\n- Error handling coverage patterns observed in the codebase\n- Platform-specific assumptions observed in the codebase\n- Established conventions (naming patterns, error handling approaches, testing strategies)\n- Configuration management approaches (env vars, config files, feature flags)\n\nOUTPUT FORMAT (MANDATORY \u2014 deviations will be rejected):\nBegin directly with PROJECT. Do NOT prepend \"Here's my analysis...\" or any conversational preamble.\n\nPROJECT: [name/type]\nLANGUAGES: [list]\nFRAMEWORK: [if any]\n\nSTRUCTURE:\n[key directories, 5-10 lines max]\nExample:\nsrc/agents/ \u2014 agent factories and definitions\nsrc/tools/ \u2014 CLI tool implementations\nsrc/config/ \u2014 plan schema and constants\n\nKEY FILES:\n- [path]: [purpose]\nExample:\nsrc/agents/explorer.ts \u2014 explorer agent factory and all prompt definitions\nsrc/agents/architect.ts \u2014 architect orchestrator with all mode handlers\n\nPATTERNS: [observations]\nExample: Factory pattern for agent creation; Result type for error handling; Module-level state via closure\n\nCOMPLEXITY INDICATORS:\n[structural complexity concerns: elevated cyclomatic complexity, deep nesting, large files, deep inheritance hierarchies, or similar \u2014 describe what is OBSERVED]\nExample: explorer.ts (289 lines, 12 exports); architect.ts (complex branching in mode handlers)\n\nOBSERVED CHANGES:\n[if INPUT referenced specific files/changes: what changed in those targets; otherwise \"none\" or \"general exploration\"]\n\nCONSUMERS_AFFECTED:\n[if integration impact mode: list files that import/use the changed symbols; otherwise \"not applicable\"]\n\nRELEVANT CONSTRAINTS:\n[architectural patterns, error handling coverage patterns, platform-specific assumptions, established conventions observed in the codebase]\nExample: Layered architecture (agents \u2192 tools \u2192 filesystem); Bun-native path handling; Error-first callbacks in hooks\n\nDOMAINS: [relevant SME domains: powershell, security, python, etc.]\nExample: typescript, nodejs, cli-tooling, powershell\n\nFOLLOW-UP CANDIDATE AREAS:\n- [path]: [observable condition, relevant domain]\nExample:\nsrc/tools/declare-scope.ts \u2014 function has 12 parameters, consider splitting; tool-authoring\n\n## CANDIDATE REPORTING MODE\nActivates when your prompt contains \"[CANDIDATE]\" anywhere in its text.\n\nWhen active, replace the default OUTPUT FORMAT above with structured pipe-delimited\ncandidate rows. Emit exactly one row per finding:\n\n[CANDIDATE] | candidate_id | lane | severity | category | file:line | claim | evidence_summary | impact_context | confidence\n\nField rules:\n- candidate_id: unique within this lane (e.g. C-001, C-002)\n- lane: your lane name or focus area\n- severity: INFO | LOW | MEDIUM | HIGH | CRITICAL\n- category: short category tag (e.g. null-safety, async-ordering, injection)\n- file:line: exact file path and line number (e.g. src/utils/cache.ts:142)\n- claim: one-sentence description of the issue\n- evidence_summary: what you observed in the code that supports the claim\n- impact_context: who or what is affected downstream\n- confidence: LOW | MEDIUM | HIGH\n\nEmit a header row first, then one [CANDIDATE] row per finding. Use pipe (|) to\nseparate fields; escape literal pipe characters inside field values as \\|.\n\nIf you find zero issues, emit the header row with no data rows. Do NOT fall back\nto the default PROJECT/STRUCTURE format when in candidate reporting mode.\n\nFor micro-lane dispatches, use the micro-lane variant:\n[CANDIDATE] | candidate_id | micro_lane | severity | category | file:line | claim | invariant_violated | evidence_summary | confidence\n\nDo NOT use CONFIRMED, DISPROVED, or PRE_EXISTING \u2014 those are reviewer verdicts.\n\n## INTEGRATION IMPACT ANALYSIS MODE\nActivates when delegated with \"Integration impact analysis\" or INPUT lists contract changes.\n\nINPUT: List of contract changes (from diff tool output \u2014 changed exports, signatures, types)\n\nSTEPS:\n1. For each changed export: use search to find imports and usages of that symbol\n2. Classify each change: BREAKING (callers must update) or COMPATIBLE (callers unaffected)\n3. List all files that import or use the changed exports\n\nOUTPUT FORMAT (MANDATORY \u2014 deviations will be rejected):\nBegin directly with BREAKING_CHANGES. Do NOT prepend conversational preamble.\n\nBREAKING_CHANGES: [list with affected consumer files, or \"none\"]\nExample: src/agents/explorer.ts \u2014 removed createExplorerAgent export (was used by 3 files)\nCOMPATIBLE_CHANGES: [list, or \"none\"]\nExample: src/config/constants.ts \u2014 added new optional field to Config interface\nCONSUMERS_AFFECTED: [list of files that import/use changed exports, or \"none\"]\nExample: src/agents/coder.ts, src/agents/reviewer.ts, src/main.ts\nCOMPATIBILITY SIGNALS: [COMPATIBLE | INCOMPATIBLE | UNCERTAIN \u2014 based on observable contract changes]\nExample: INCOMPATIBLE \u2014 removeExport changes function arity from 3 to 2\nMIGRATION_SURFACE: [yes \u2014 list of observable call signatures affected | no \u2014 no observable impact detected]\nExample: yes \u2014 createExplorerAgent(model, customPrompt?, customAppendPrompt?) \u2192 createExplorerAgent(model)\n\n## DOCUMENTATION DISCOVERY MODE\nActivates automatically during codebase reality check at plan ingestion.\nUse the doc_scan tool to scan and index documentation files. If doc_scan is unavailable, fall back to manual globbing.\n\nSTEPS:\n1. Call doc_scan to build the manifest, OR glob for documentation files:\n - Root: README.md, CONTRIBUTING.md, CHANGELOG.md, ARCHITECTURE.md, CLAUDE.md, AGENTS.md, .github/*.md\n - docs/**/*.md, doc/**/*.md (one level deep only)\n\n2. For each file found, read the first 30 lines. Extract:\n - path: relative to project root\n - title: first # heading, or filename if no heading\n - summary: first non-empty paragraph after the title (max 200 chars, use the ACTUAL text, do NOT summarize with your own words)\n - lines: total line count\n - mtime: file modification timestamp\n\n3. Write manifest to .swarm/doc-manifest.json:\n { \"schema_version\": 1, \"scanned_at\": \"ISO timestamp\", \"files\": [...] }\n\n4. For each file in the manifest, check relevance to the current plan:\n - Score by keyword overlap: do any task file paths or directory names appear in the doc's path or summary?\n - For files scoring > 0, read the full content and extract up to 5 actionable constraints per doc (max 200 chars each)\n - Write constraints to .swarm/knowledge/doc-constraints.jsonl as knowledge entries with source: \"doc-scan\", category: \"architecture\"\n\n5. Invalidation: Only re-scan if any doc file's mtime is newer than the manifest's scanned_at. Otherwise reuse the cached manifest.\n\nRULES:\n- The manifest must be small (<100 lines). Pointers only, not full content.\n- Do NOT rephrase or summarize doc content with your own words \u2014 use the actual text from the file\n- Full doc content is only loaded when relevant to the current task, never preloaded\n";
3
3
  export declare const CURATOR_INIT_PROMPT = "## IDENTITY\nYou are Explorer in CURATOR_INIT mode. You consolidate prior session knowledge into an architect briefing.\nDO NOT use the Task tool to delegate. You ARE the agent that does the work.\n\nINPUT FORMAT:\nTASK: CURATOR_INIT\nPRIOR_SUMMARY: [JSON or \"none\"]\nKNOWLEDGE_ENTRIES: [JSON array of existing entries with UUIDs]\nPROJECT_CONTEXT: [context.md excerpt]\n\nACTIONS:\n- Read the prior summary to understand session history\n- Cross-reference knowledge entries against project context\n- Note contradictions (knowledge says X, project state shows Y)\n- Observe where lessons could be tighter or stale\n- Produce a concise briefing for the architect\n\nRULES:\n- Output under 2000 chars\n- No code modifications\n- Flag contradictions explicitly with CONTRADICTION: prefix\n- Memory proposals are for concise durable facts only. Do not propose raw API docs, web search snippets, crawl output, or transcripts as memory; cite their evidence-cache refs and propose only the stable fact they support.\n- If no prior summary exists, state \"First session \u2014 no prior context\"\n\nOUTPUT FORMAT:\nBRIEFING:\n[concise summary of prior session state, key decisions, active blockers]\n\nCONTRADICTIONS:\n- [entry_id]: [description] (or \"None detected\")\n\nOBSERVATIONS:\n- entry <uuid> appears high-confidence: [observable evidence] (suggests boost confidence, mark hive_eligible)\n- entry <uuid> appears stale: [observable evidence] (suggests archive \u2014 no longer injected)\n- entry <uuid> could be tighter: [what's verbose or duplicate] (suggests rewrite with tighter version, max 280 chars)\n- entry <uuid> contradicts project state: [observable conflict] (suggests tag as contradicted)\n- new candidate: [concise lesson text from observed patterns] (suggests new entry)\nUse the UUID from KNOWLEDGE_ENTRIES when observing about existing entries. Use \"new candidate\" only when observing a potential new entry.\n\nKNOWLEDGE_STATS:\n- Entries reviewed: [N]\n- Prior phases covered: [N]\n";
4
4
  export declare const CURATOR_PHASE_PROMPT = "## IDENTITY\nYou are Explorer in CURATOR_PHASE mode. You consolidate a completed phase into a digest.\nDO NOT use the Task tool to delegate. You ARE the agent that does the work.\n\nINPUT FORMAT:\nTASK: CURATOR_PHASE [phase_number]\nPRIOR_DIGEST: [running summary or \"none\"]\nPHASE_EVENTS: [JSON array from events.jsonl for this phase]\nPHASE_EVIDENCE: [summary of evidence bundles]\nPHASE_DECISIONS: [decisions from context.md]\nAGENTS_DISPATCHED: [list]\nAGENTS_EXPECTED: [list from config]\nKNOWLEDGE_ENTRIES: [JSON array of existing entries with UUIDs]\n\nACTIONS:\n- Extend the prior digest with this phase's outcomes (do NOT regenerate from scratch)\n- Observe workflow deviations: missing reviewer, missing retro, skipped test_engineer\n- Report knowledge update candidates with observable evidence: entries that appear promoted, archived, rewritten, or contradicted\n- Summarize key decisions and blockers resolved\n\nRULES:\n- Output under 2000 chars\n- No code modifications\n- Compliance observations are READ-ONLY \u2014 report, do not enforce\n- OBSERVATIONS should not contain directives \u2014 report what is observed, do not instruct the architect what to do\n- Extend the digest, never replace it\n- Memory proposals are for concise durable facts only. Do not promote raw API docs, web search snippets, crawl output, or transcripts into memory; cite evidence-cache refs and propose only the stable fact they support.\n\nOUTPUT FORMAT:\nPHASE_DIGEST:\nphase: [N]\nsummary: [what was accomplished]\nagents_used: [list]\ntasks_completed: [N]/[total]\nkey_decisions: [list]\nblockers_resolved: [list]\n\nCOMPLIANCE:\n- [type] observed: [description] (or \"No deviations observed\")\n\nOBSERVATIONS:\n- entry <uuid> appears high-confidence: [observable evidence] (suggests boost confidence, mark hive_eligible)\n- entry <uuid> appears stale: [observable evidence] (suggests archive \u2014 no longer injected)\n- entry <uuid> could be tighter: [what's verbose or duplicate] (suggests rewrite with tighter version, max 280 chars)\n- entry <uuid> contradicts project state: [observable conflict] (suggests tag as contradicted)\n- new candidate: [concise lesson text from observed patterns] (suggests new entry)\nUse the UUID from KNOWLEDGE_ENTRIES when observing about existing entries. Use \"new candidate\" only when observing a potential new entry.\n\nEXTENDED_DIGEST:\n[the full running digest with this phase appended]\n\n## V3 ACTIONABILITY ENRICHMENT (overrides the format above when triggered)\nWhen the input asks you to \"Convert this prose lesson into an actionable knowledge directive\", ignore the PHASE_DIGEST output format entirely and output ONLY a single JSON object \u2014 no fences, no commentary, no digest.\nMANDATORY fields (the directive is rejected without them):\n- at least one non-empty scope field: \"applies_to_agents\" (roles: architect, coder, reviewer, test_engineer, sme, docs, designer, critic, curator) or \"applies_to_tools\" (edit, write, patch, bash, read, grep, glob)\n- at least one non-empty predicate field: \"forbidden_actions\", \"required_actions\", or \"verification_checks\"\nOptional: \"triggers\" (short surfacing phrases), \"directive_priority\" (low|medium|high|critical).\nExample output:\n{\"applies_to_agents\":[\"coder\"],\"forbidden_actions\":[\"use async iterators in hot paths\"],\"required_actions\":[\"use a plain for loop in hot paths\"],\"triggers\":[\"hot path\",\"async iterator\"],\"directive_priority\":\"high\"}\n";
5
5
  export declare const CURATOR_POSTMORTEM_PROMPT = "## IDENTITY\nYou are Explorer in CURATOR_POSTMORTEM mode. You synthesize a project-end post-mortem from structured .swarm/ evidence.\nDO NOT use the Task tool to delegate. You ARE the agent that does the work.\nDO NOT scan raw source code \u2014 work only from the recorded evidence provided below.\n\nINPUT FORMAT:\nTASK: CURATOR_POSTMORTEM [plan_id]\nPLAN_SUMMARY: [plan phases, task counts, completion status]\nCURATOR_DIGESTS: [running digest from curator_phase across all phases]\nKNOWLEDGE_ENTRIES: [JSON array of existing entries with UUIDs]\nKNOWLEDGE_EVENTS_SUMMARY: [aggregated violation/applied/ignored counts per entry]\nPENDING_PROPOSALS: [skill/motif proposals awaiting triage]\nUNACTIONABLE_QUARANTINE: [entries flagged unactionable with retry status]\nDRIFT_REPORTS: [per-phase alignment/drift scores if available]\nRETROSPECTIVES: [any session retrospectives found]\n\nACTIONS:\n1. IMPROVEMENT AGENDA: Rank process + code improvement opportunities, each citing recorded evidence (task IDs, event records, evidence bundles). Focus on what would most reduce mistakes or increase reuse in the next project.\n2. FINAL CURATION PASS: Consolidate knowledge across phases \u2014 identify near-duplicate lessons that accumulated under different IDs, recommend hive promotion for project-proven entries (high confidence, multiple phases confirmed), flag never-applied entries past 3+ phases for review.\n3. QUEUE TRIAGE: For each pending proposal, recommend apply/reject with one-line reasoning. Surface unactionable-quarantine counts and retry candidates.\n4. LEARNING METRICS SUMMARY: Embed violation-rate trend, application rates, escalation frequency if metrics data is provided.\n\nRULES:\n- Output under 4000 chars\n- No code modifications \u2014 read-only synthesis\n- Every improvement item must cite a specific evidence artifact or event record\n- Do not invent evidence \u2014 if an artifact is missing, note the gap\n- Proposals route through existing gated paths (knowledge_add, skill proposals, hive promotion) \u2014 recommend the path, do not bypass it\n- HIGH-severity items that should become critical directives must be flagged for critic gate validation\n\nOUTPUT FORMAT:\nPOST_MORTEM_REPORT:\nplan_id: [plan identifier]\ngenerated_at: [ISO timestamp]\n\nIMPROVEMENT_AGENDA:\n1. [priority] [description] \u2014 evidence: [artifact/event ref]\n2. ...\n\nCURATION_RECOMMENDATIONS:\n- merge: [entry_a UUID] + [entry_b UUID] \u2014 [reason]\n- promote_to_hive: [entry UUID] \u2014 [evidence of cross-phase confirmation]\n- flag_stale: [entry UUID] \u2014 [never applied in N phases]\n- rewrite: [entry UUID] \u2014 [what's verbose/outdated]\n\nQUEUE_TRIAGE:\n- [proposal_id]: APPLY|REJECT \u2014 [one-line reasoning]\n\nLEARNING_METRICS:\n[3-line summary of trends if data available, or \"metrics data not provided\"]\n\nSUMMARY:\n[3-line executive summary for architect briefing]\n";
@@ -119,6 +119,7 @@ export interface DiagnosticsSummary {
119
119
  degraded_source_count: number;
120
120
  incomplete_source_count: number;
121
121
  format_families_detected: string[];
122
+ format_mismatch_hint?: string;
122
123
  }
123
124
  /**
124
125
  * Top-level return value from parseCandidates.
@@ -12,8 +12,8 @@ import {
12
12
  shouldRunOnStartup,
13
13
  writeBackupArtifact,
14
14
  writeDoctorArtifact
15
- } from "./index-bywt2171.js";
16
- import"./index-123s7kjc.js";
15
+ } from "./index-2jpbaedv.js";
16
+ import"./index-xsbtbffr.js";
17
17
  import"./index-5e4e2hvv.js";
18
18
  import"./index-p0arc26j.js";
19
19
  import"./index-zgwm4ryv.js";
@@ -6,7 +6,7 @@ import {
6
6
  CURATOR_POSTMORTEM_PROMPT,
7
7
  EXPLORER_PROMPT,
8
8
  createExplorerAgent
9
- } from "./index-bm4f0nme.js";
9
+ } from "./index-1x2608ga.js";
10
10
  import"./index-a76rekgs.js";
11
11
  export {
12
12
  createExplorerAgent,
@@ -1,14 +1,14 @@
1
1
  // @bun
2
2
  import {
3
3
  handleGuardrailExplain
4
- } from "./index-wtyysb1n.js";
5
- import"./index-e9tp9p2w.js";
6
- import"./index-6tnmt41c.js";
7
- import"./index-bm4f0nme.js";
4
+ } from "./index-zzza86z4.js";
5
+ import"./index-dy1qpyh3.js";
6
+ import"./index-ne4g3mk1.js";
7
+ import"./index-1x2608ga.js";
8
8
  import"./index-5hrexm02.js";
9
9
  import"./index-w7gkpmq8.js";
10
- import"./index-bywt2171.js";
11
- import"./index-123s7kjc.js";
10
+ import"./index-2jpbaedv.js";
11
+ import"./index-xsbtbffr.js";
12
12
  import"./index-y1z6yaq4.js";
13
13
  import"./index-adz3nk9b.js";
14
14
  import"./index-v4fcn4tr.js";
@@ -1,9 +1,9 @@
1
1
  // @bun
2
2
  import {
3
3
  handleGuardrailLog
4
- } from "./index-gg589mfw.js";
5
- import"./index-6tnmt41c.js";
6
- import"./index-123s7kjc.js";
4
+ } from "./index-yykcmn6m.js";
5
+ import"./index-ne4g3mk1.js";
6
+ import"./index-xsbtbffr.js";
7
7
  import"./index-5e4e2hvv.js";
8
8
  import"./index-p0arc26j.js";
9
9
  import"./index-zgwm4ryv.js";
@@ -99,6 +99,36 @@ FOLLOW-UP CANDIDATE AREAS:
99
99
  Example:
100
100
  src/tools/declare-scope.ts \u2014 function has 12 parameters, consider splitting; tool-authoring
101
101
 
102
+ ## CANDIDATE REPORTING MODE
103
+ Activates when your prompt contains "[CANDIDATE]" anywhere in its text.
104
+
105
+ When active, replace the default OUTPUT FORMAT above with structured pipe-delimited
106
+ candidate rows. Emit exactly one row per finding:
107
+
108
+ [CANDIDATE] | candidate_id | lane | severity | category | file:line | claim | evidence_summary | impact_context | confidence
109
+
110
+ Field rules:
111
+ - candidate_id: unique within this lane (e.g. C-001, C-002)
112
+ - lane: your lane name or focus area
113
+ - severity: INFO | LOW | MEDIUM | HIGH | CRITICAL
114
+ - category: short category tag (e.g. null-safety, async-ordering, injection)
115
+ - file:line: exact file path and line number (e.g. src/utils/cache.ts:142)
116
+ - claim: one-sentence description of the issue
117
+ - evidence_summary: what you observed in the code that supports the claim
118
+ - impact_context: who or what is affected downstream
119
+ - confidence: LOW | MEDIUM | HIGH
120
+
121
+ Emit a header row first, then one [CANDIDATE] row per finding. Use pipe (|) to
122
+ separate fields; escape literal pipe characters inside field values as \\|.
123
+
124
+ If you find zero issues, emit the header row with no data rows. Do NOT fall back
125
+ to the default PROJECT/STRUCTURE format when in candidate reporting mode.
126
+
127
+ For micro-lane dispatches, use the micro-lane variant:
128
+ [CANDIDATE] | candidate_id | micro_lane | severity | category | file:line | claim | invariant_violated | evidence_summary | confidence
129
+
130
+ Do NOT use CONFIRMED, DISPROVED, or PRE_EXISTING \u2014 those are reviewer verdicts.
131
+
102
132
  ## INTEGRATION IMPACT ANALYSIS MODE
103
133
  Activates when delegated with "Integration impact analysis" or INPUT lists contract changes.
104
134
 
@@ -3,7 +3,7 @@ import {
3
3
  ALL_AGENT_NAMES,
4
4
  PluginConfigSchema,
5
5
  stripKnownSwarmPrefix
6
- } from "./index-123s7kjc.js";
6
+ } from "./index-xsbtbffr.js";
7
7
  import {
8
8
  log
9
9
  } from "./index-zgwm4ryv.js";
@@ -1,10 +1,10 @@
1
1
  // @bun
2
2
  import {
3
3
  handleGuardrailExplain
4
- } from "./index-wtyysb1n.js";
4
+ } from "./index-zzza86z4.js";
5
5
  import {
6
6
  handleGuardrailLog
7
- } from "./index-gg589mfw.js";
7
+ } from "./index-yykcmn6m.js";
8
8
  import {
9
9
  COMMAND_REGISTRY,
10
10
  SWARM_COMMAND_TOOL_ALLOWLIST,
@@ -78,17 +78,17 @@ import {
78
78
  handleWriteRetroCommand,
79
79
  normalizeSwarmCommandInput,
80
80
  resolveCommand
81
- } from "./index-e9tp9p2w.js";
82
- import"./index-6tnmt41c.js";
83
- import"./index-bm4f0nme.js";
81
+ } from "./index-dy1qpyh3.js";
82
+ import"./index-ne4g3mk1.js";
83
+ import"./index-1x2608ga.js";
84
84
  import"./index-5hrexm02.js";
85
85
  import"./index-w7gkpmq8.js";
86
- import"./index-bywt2171.js";
86
+ import"./index-2jpbaedv.js";
87
87
  import {
88
88
  AGENT_TOOL_MAP,
89
89
  ORCHESTRATOR_NAME,
90
90
  stripKnownSwarmPrefix
91
- } from "./index-123s7kjc.js";
91
+ } from "./index-xsbtbffr.js";
92
92
  import"./index-y1z6yaq4.js";
93
93
  import"./index-adz3nk9b.js";
94
94
  import"./index-v4fcn4tr.js";
@@ -54,7 +54,7 @@ import {
54
54
  readDoctorArtifact,
55
55
  removeStraySwarmDir,
56
56
  runConfigDoctor
57
- } from "./index-bywt2171.js";
57
+ } from "./index-2jpbaedv.js";
58
58
  import {
59
59
  AGENT_TOOL_MAP,
60
60
  ALL_SUBAGENT_NAMES,
@@ -67,7 +67,7 @@ import {
67
67
  TOOL_NAME_SET,
68
68
  resolveExternalSkillsConfig,
69
69
  stripKnownSwarmPrefix
70
- } from "./index-123s7kjc.js";
70
+ } from "./index-xsbtbffr.js";
71
71
  import {
72
72
  MAX_TRANSIENT_RETRIES,
73
73
  PlanSchema,
@@ -906,7 +906,7 @@ var init_executor = __esm(() => {
906
906
  // package.json
907
907
  var package_default = {
908
908
  name: "opencode-swarm",
909
- version: "7.91.0",
909
+ version: "7.92.0",
910
910
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
911
911
  main: "dist/index.js",
912
912
  types: "dist/index.d.ts",
@@ -6273,7 +6273,7 @@ async function runCuratorPostMortem(directory, options = {}) {
6273
6273
  let reportContent;
6274
6274
  if (options.llmDelegate) {
6275
6275
  try {
6276
- const { CURATOR_POSTMORTEM_PROMPT: CURATOR_POSTMORTEM_PROMPT2 } = await import("./explorer-h2fnj343.js");
6276
+ const { CURATOR_POSTMORTEM_PROMPT: CURATOR_POSTMORTEM_PROMPT2 } = await import("./explorer-4ttwy7jd.js");
6277
6277
  const userInput = assembleLLMInput(effectivePlanId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports);
6278
6278
  const ac = new AbortController;
6279
6279
  const timer = setTimeout(() => ac.abort(), 300000);
@@ -9074,7 +9074,7 @@ function isWriteToSwarmPlan(input) {
9074
9074
  const toolName = record.toolName;
9075
9075
  if (typeof toolName !== "string")
9076
9076
  return false;
9077
- if (!["write", "edit", "apply_patch"].includes(toolName))
9077
+ if (!["write", "edit", "apply_patch", "swarm_apply_patch"].includes(toolName))
9078
9078
  return false;
9079
9079
  const rawPath = record.path;
9080
9080
  const rawFile = record.file;
@@ -9095,7 +9095,7 @@ function isWriteToEvidenceFile(input) {
9095
9095
  const toolName = record.toolName;
9096
9096
  if (typeof toolName !== "string")
9097
9097
  return false;
9098
- if (!["write", "edit", "apply_patch"].includes(toolName))
9098
+ if (!["write", "edit", "apply_patch", "swarm_apply_patch"].includes(toolName))
9099
9099
  return false;
9100
9100
  const rawPath = record.path;
9101
9101
  const rawFile = record.file;
@@ -11626,7 +11626,7 @@ async function runFinalizeStage(ctx) {
11626
11626
  }
11627
11627
  }
11628
11628
  try {
11629
- const { CuratorConfigSchema: CCS } = await import("./schema-t9th7frq.js");
11629
+ const { CuratorConfigSchema: CCS } = await import("./schema-1kndsf0c.js");
11630
11630
  const { config: pmLoadedConfig } = _internals20.loadPluginConfigWithMeta(ctx.directory);
11631
11631
  const curatorCfg = CCS.parse(pmLoadedConfig.curator ?? {});
11632
11632
  if (curatorCfg.enabled && curatorCfg.postmortem_enabled) {
@@ -15325,7 +15325,7 @@ async function handleDoctorCommand(directory, args) {
15325
15325
  const result = runConfigDoctor(config, directory);
15326
15326
  let output;
15327
15327
  if (enableAutoFix && result.hasAutoFixableIssues) {
15328
- const { runConfigDoctorWithFixes } = await import("./config-doctor-g04wdz19.js");
15328
+ const { runConfigDoctorWithFixes } = await import("./config-doctor-fkwyrtpq.js");
15329
15329
  const fixResult = await runConfigDoctorWithFixes(directory, config, true);
15330
15330
  output = formatDoctorMarkdown(fixResult.result);
15331
15331
  } else {
@@ -30387,7 +30387,7 @@ function buildDetailedHelp(commandName, entry) {
30387
30387
  async function handleHelpCommand(ctx) {
30388
30388
  const targetCommand = ctx.args.join(" ");
30389
30389
  if (!targetCommand) {
30390
- const { buildHelpText } = await import("./index-gpkbg9p4.js");
30390
+ const { buildHelpText } = await import("./index-ary5jkky.js");
30391
30391
  return buildHelpText();
30392
30392
  }
30393
30393
  const tokens = targetCommand.split(/\s+/);
@@ -30396,7 +30396,7 @@ async function handleHelpCommand(ctx) {
30396
30396
  return _internals45.buildDetailedHelp(resolved.key, resolved.entry);
30397
30397
  }
30398
30398
  const similar = _internals45.findSimilarCommands(targetCommand);
30399
- const { buildHelpText: fullHelp } = await import("./index-gpkbg9p4.js");
30399
+ const { buildHelpText: fullHelp } = await import("./index-ary5jkky.js");
30400
30400
  if (similar.length > 0) {
30401
30401
  return `Command '/swarm ${targetCommand}' not found.
30402
30402
 
@@ -30529,7 +30529,7 @@ var COMMAND_REGISTRY = {
30529
30529
  },
30530
30530
  "guardrail explain": {
30531
30531
  handler: async (ctx) => {
30532
- const { handleGuardrailExplain } = await import("./guardrail-explain-0ephhnjq.js");
30532
+ const { handleGuardrailExplain } = await import("./guardrail-explain-ygfy1qg9.js");
30533
30533
  return handleGuardrailExplain(ctx.directory, ctx.args);
30534
30534
  },
30535
30535
  description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
@@ -30539,7 +30539,7 @@ var COMMAND_REGISTRY = {
30539
30539
  },
30540
30540
  "guardrail-log": {
30541
30541
  handler: async (ctx) => {
30542
- const { handleGuardrailLog } = await import("./guardrail-log-m3285thy.js");
30542
+ const { handleGuardrailLog } = await import("./guardrail-log-x3w800x5.js");
30543
30543
  return handleGuardrailLog(ctx.directory, ctx.args);
30544
30544
  },
30545
30545
  description: "Read the guardrail decision log (use --blocks-only for blocks)",
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  stripKnownSwarmPrefix
4
- } from "./index-123s7kjc.js";
4
+ } from "./index-xsbtbffr.js";
5
5
  import {
6
6
  init_logger,
7
7
  warn
@@ -521,11 +521,11 @@ var TOOL_METADATA = {
521
521
  agents: ["architect"]
522
522
  },
523
523
  dispatch_lanes_async: {
524
- description: "launch read-only advisory lanes non-blockingly and return a batch id immediately so you can keep working; join later with collect_lane_results",
524
+ description: "launch read-only advisory lanes non-blockingly and return a batch id immediately so you can keep working; poll incrementally with collect_lane_results (wait omitted or false) while doing independent investigation, or join with wait: true when you need all results",
525
525
  agents: ["architect"]
526
526
  },
527
527
  collect_lane_results: {
528
- description: "collect or poll results for a dispatch_lanes_async batch; this is the required join barrier for advisory lane workflows and does not advance workflow gates",
528
+ description: "collect or poll results for a dispatch_lanes_async batch; supports both non-blocking polling (wait omitted or false) and blocking join (wait: true). Use non-blocking polls to check progress and process settled lanes incrementally while continuing independent work; use blocking join only when you need all lanes settled before proceeding. Does not advance workflow gates.",
529
529
  agents: ["architect"]
530
530
  },
531
531
  summarize_work: {
@@ -570,8 +570,8 @@ var TOOL_METADATA = {
570
570
  description: "returns Lean Turbo configuration and active status for the current session",
571
571
  agents: []
572
572
  },
573
- apply_patch: {
574
- description: "Apply a unified diff patch to workspace files with exact context matching, atomic writes, and path validation",
573
+ swarm_apply_patch: {
574
+ description: "Apply a unified diff patch to workspace files with exact context matching, atomic writes, and path validation. Use standard unified diff format only \u2014 does NOT support *** Begin Patch / *** Update File payloads (use native apply_patch for those).",
575
575
  agents: ["coder", "test_engineer"]
576
576
  },
577
577
  external_skill_discover: {
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  redactPath,
4
4
  redactShellCommand
5
- } from "./index-6tnmt41c.js";
5
+ } from "./index-ne4g3mk1.js";
6
6
 
7
7
  // src/services/guardrail-log-service.ts
8
8
  import * as fs from "fs/promises";
@@ -12,14 +12,14 @@ import {
12
12
  detectPosixWrites,
13
13
  detectWindowsWrites,
14
14
  resolveWriteTargets
15
- } from "./index-e9tp9p2w.js";
15
+ } from "./index-dy1qpyh3.js";
16
16
  import {
17
17
  checkFileAuthority,
18
18
  classifyFile,
19
19
  isInDeclaredScope,
20
20
  redactPath,
21
21
  redactShellCommand
22
- } from "./index-6tnmt41c.js";
22
+ } from "./index-ne4g3mk1.js";
23
23
 
24
24
  // src/services/guardrail-explain-service.ts
25
25
  import path from "path";
package/dist/cli/index.js CHANGED
@@ -7,15 +7,15 @@ import {
7
7
  getPluginLockFilePaths,
8
8
  package_default,
9
9
  resolveCommand
10
- } from "./index-e9tp9p2w.js";
11
- import"./index-6tnmt41c.js";
12
- import"./index-bm4f0nme.js";
10
+ } from "./index-dy1qpyh3.js";
11
+ import"./index-ne4g3mk1.js";
12
+ import"./index-1x2608ga.js";
13
13
  import"./index-5hrexm02.js";
14
14
  import"./index-w7gkpmq8.js";
15
- import"./index-bywt2171.js";
15
+ import"./index-2jpbaedv.js";
16
16
  import {
17
17
  DEFAULT_AGENT_CONFIGS
18
- } from "./index-123s7kjc.js";
18
+ } from "./index-xsbtbffr.js";
19
19
  import"./index-y1z6yaq4.js";
20
20
  import"./index-adz3nk9b.js";
21
21
  import"./index-v4fcn4tr.js";
@@ -81,7 +81,7 @@ import {
81
81
  resolveGeneratedAgentRole,
82
82
  resolveGuardrailsConfig,
83
83
  stripKnownSwarmPrefix
84
- } from "./index-123s7kjc.js";
84
+ } from "./index-xsbtbffr.js";
85
85
  import"./index-p0arc26j.js";
86
86
  import"./index-293f68mj.js";
87
87
  import"./index-a76rekgs.js";
@@ -25,7 +25,7 @@ export declare const TURBO_AGENT_TOOL_MAP: Partial<Record<AgentName, ToolName[]>
25
25
  * NOTE: bash/shell tools are intentionally excluded — bash commands are opaque
26
26
  * to static scope analysis. Post-hoc detection via guardrails diff-scope provides secondary coverage.
27
27
  */
28
- export declare const WRITE_TOOL_NAMES: readonly ["write", "edit", "patch", "apply_patch", "create_file", "insert", "replace", "append", "prepend"];
28
+ export declare const WRITE_TOOL_NAMES: readonly ["write", "edit", "patch", "apply_patch", "swarm_apply_patch", "create_file", "insert", "replace", "append", "prepend"];
29
29
  export type WriteToolName = (typeof WRITE_TOOL_NAMES)[number];
30
30
  export declare const DEFAULT_MODELS: Record<string, string>;
31
31
  export declare const DEFAULT_AGENT_CONFIGS: Record<string, {
package/dist/index.js CHANGED
@@ -69,7 +69,7 @@ var package_default;
69
69
  var init_package = __esm(() => {
70
70
  package_default = {
71
71
  name: "opencode-swarm",
72
- version: "7.91.0",
72
+ version: "7.92.0",
73
73
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
74
74
  main: "dist/index.js",
75
75
  types: "dist/index.d.ts",
@@ -698,11 +698,11 @@ var init_tool_metadata = __esm(() => {
698
698
  agents: ["architect"]
699
699
  },
700
700
  dispatch_lanes_async: {
701
- description: "launch read-only advisory lanes non-blockingly and return a batch id immediately so you can keep working; join later with collect_lane_results",
701
+ description: "launch read-only advisory lanes non-blockingly and return a batch id immediately so you can keep working; poll incrementally with collect_lane_results (wait omitted or false) while doing independent investigation, or join with wait: true when you need all results",
702
702
  agents: ["architect"]
703
703
  },
704
704
  collect_lane_results: {
705
- description: "collect or poll results for a dispatch_lanes_async batch; this is the required join barrier for advisory lane workflows and does not advance workflow gates",
705
+ description: "collect or poll results for a dispatch_lanes_async batch; supports both non-blocking polling (wait omitted or false) and blocking join (wait: true). Use non-blocking polls to check progress and process settled lanes incrementally while continuing independent work; use blocking join only when you need all lanes settled before proceeding. Does not advance workflow gates.",
706
706
  agents: ["architect"]
707
707
  },
708
708
  summarize_work: {
@@ -747,8 +747,8 @@ var init_tool_metadata = __esm(() => {
747
747
  description: "returns Lean Turbo configuration and active status for the current session",
748
748
  agents: []
749
749
  },
750
- apply_patch: {
751
- description: "Apply a unified diff patch to workspace files with exact context matching, atomic writes, and path validation",
750
+ swarm_apply_patch: {
751
+ description: "Apply a unified diff patch to workspace files with exact context matching, atomic writes, and path validation. Use standard unified diff format only — does NOT support *** Begin Patch / *** Update File payloads (use native apply_patch for those).",
752
752
  agents: ["coder", "test_engineer"]
753
753
  },
754
754
  external_skill_discover: {
@@ -1185,6 +1185,7 @@ var init_constants = __esm(() => {
1185
1185
  "edit",
1186
1186
  "patch",
1187
1187
  "apply_patch",
1188
+ "swarm_apply_patch",
1188
1189
  "create_file",
1189
1190
  "insert",
1190
1191
  "replace",
@@ -43289,7 +43290,7 @@ function createToolBeforeHandler(ctx) {
43289
43290
  }
43290
43291
  }
43291
43292
  }
43292
- if (tool === "apply_patch" || tool === "patch") {
43293
+ if (tool === "apply_patch" || tool === "swarm_apply_patch" || tool === "patch") {
43293
43294
  const agentName = swarmState.activeAgent.get(sessionID) ?? "unknown";
43294
43295
  const cwd = effectiveDirectory;
43295
43296
  for (const p of extractPatchTargetPaths(tool, args2)) {
@@ -43432,16 +43433,23 @@ function createToolBeforeHandler(ctx) {
43432
43433
  return payloads.some((p) => re.test(p));
43433
43434
  }
43434
43435
  function extractPatchTargetPaths(tool, args2) {
43435
- if (tool !== "apply_patch" && tool !== "patch")
43436
+ if (tool !== "apply_patch" && tool !== "swarm_apply_patch" && tool !== "patch")
43436
43437
  return [];
43437
43438
  const toolArgs = args2;
43439
+ const paths = new Set;
43440
+ if (Array.isArray(toolArgs?.files)) {
43441
+ for (const f of toolArgs.files) {
43442
+ if (typeof f === "string" && f.length > 0 && f !== "/dev/null") {
43443
+ paths.add(f);
43444
+ }
43445
+ }
43446
+ }
43438
43447
  const patchText = toolArgs?.input ?? toolArgs?.patch ?? toolArgs?.diff ?? (Array.isArray(toolArgs?.cmd) ? toolArgs.cmd[1] : undefined);
43439
43448
  if (typeof patchText !== "string")
43440
- return [];
43449
+ return Array.from(paths);
43441
43450
  if (patchText.length > 1e6) {
43442
43451
  throw new Error("WRITE BLOCKED: Patch payload exceeds 1 MB — authority cannot be verified for all modified paths. Split into smaller patches.");
43443
43452
  }
43444
- const paths = new Set;
43445
43453
  const patchPathPattern = /\*\*\*\s+(?:Update|Add|Delete)\s+File:\s*(.+)/gi;
43446
43454
  const diffPathPattern = /\+\+\+\s+b\/(.+)/gm;
43447
43455
  const gitDiffPathPattern = /^diff --git a\/(.+?) b\/(.+?)$/gm;
@@ -43483,9 +43491,9 @@ function createToolBeforeHandler(ctx) {
43483
43491
  function handlePlanAndScopeProtection(sessionID, tool, args2) {
43484
43492
  const toolArgs = args2;
43485
43493
  const targetPath = toolArgs?.filePath ?? toolArgs?.path ?? toolArgs?.file ?? toolArgs?.target;
43486
- if (tool === "apply_patch" || tool === "patch") {
43494
+ if (tool === "apply_patch" || tool === "swarm_apply_patch" || tool === "patch") {
43487
43495
  if (patchPayloadHasHumanOnlyInvocation(args2)) {
43488
- throw new Error("BLOCKED: apply_patch would introduce a script invoking a human-only swarm CLI subcommand. " + "Present the situation to the user and ask them to run the command themselves.");
43496
+ throw new Error("BLOCKED: apply_patch/swarm_apply_patch would introduce a script invoking a human-only swarm CLI subcommand. " + "Present the situation to the user and ask them to run the command themselves.");
43489
43497
  }
43490
43498
  }
43491
43499
  if (typeof targetPath === "string" && targetPath.length > 0) {
@@ -43504,7 +43512,7 @@ function createToolBeforeHandler(ctx) {
43504
43512
  throw new Error("BLOCKED: write/edit tool would create a script invoking a human-only swarm CLI subcommand. " + "Present the situation to the user and ask them to run the command themselves.");
43505
43513
  }
43506
43514
  }
43507
- if (!targetPath && (tool === "apply_patch" || tool === "patch")) {
43515
+ if (!targetPath && (tool === "apply_patch" || tool === "swarm_apply_patch" || tool === "patch")) {
43508
43516
  for (const p of extractPatchTargetPaths(tool, args2)) {
43509
43517
  const resolvedP = path28.resolve(effectiveDirectory, p);
43510
43518
  const planMdPath = path28.resolve(effectiveDirectory, ".swarm", "plan.md").toLowerCase();
@@ -43520,7 +43528,7 @@ function createToolBeforeHandler(ctx) {
43520
43528
  const session = swarmState.agentSessions.get(sessionID);
43521
43529
  if (session) {
43522
43530
  session.architectWriteCount++;
43523
- warn("Architect direct code edit detected via apply_patch", {
43531
+ warn("Architect direct code edit detected via patch tool", {
43524
43532
  tool,
43525
43533
  sessionID,
43526
43534
  targetPath: p,
@@ -43872,7 +43880,7 @@ function createToolBeforeHandler(ctx) {
43872
43880
  }
43873
43881
  }
43874
43882
  }
43875
- if (input.tool === "apply_patch" || input.tool === "patch") {
43883
+ if (input.tool === "apply_patch" || input.tool === "swarm_apply_patch" || input.tool === "patch") {
43876
43884
  const patchAgentName = swarmState.activeAgent.get(input.sessionID) ?? "unknown";
43877
43885
  if (!swarmState.activeAgent.has(input.sessionID)) {
43878
43886
  throw new Error(`WRITE BLOCKED: No active agent registered for session "${input.sessionID}". Call startAgentSession before issuing write tool calls.`);
@@ -62812,6 +62820,36 @@ FOLLOW-UP CANDIDATE AREAS:
62812
62820
  Example:
62813
62821
  src/tools/declare-scope.ts — function has 12 parameters, consider splitting; tool-authoring
62814
62822
 
62823
+ ## CANDIDATE REPORTING MODE
62824
+ Activates when your prompt contains "[CANDIDATE]" anywhere in its text.
62825
+
62826
+ When active, replace the default OUTPUT FORMAT above with structured pipe-delimited
62827
+ candidate rows. Emit exactly one row per finding:
62828
+
62829
+ [CANDIDATE] | candidate_id | lane | severity | category | file:line | claim | evidence_summary | impact_context | confidence
62830
+
62831
+ Field rules:
62832
+ - candidate_id: unique within this lane (e.g. C-001, C-002)
62833
+ - lane: your lane name or focus area
62834
+ - severity: INFO | LOW | MEDIUM | HIGH | CRITICAL
62835
+ - category: short category tag (e.g. null-safety, async-ordering, injection)
62836
+ - file:line: exact file path and line number (e.g. src/utils/cache.ts:142)
62837
+ - claim: one-sentence description of the issue
62838
+ - evidence_summary: what you observed in the code that supports the claim
62839
+ - impact_context: who or what is affected downstream
62840
+ - confidence: LOW | MEDIUM | HIGH
62841
+
62842
+ Emit a header row first, then one [CANDIDATE] row per finding. Use pipe (|) to
62843
+ separate fields; escape literal pipe characters inside field values as \\|.
62844
+
62845
+ If you find zero issues, emit the header row with no data rows. Do NOT fall back
62846
+ to the default PROJECT/STRUCTURE format when in candidate reporting mode.
62847
+
62848
+ For micro-lane dispatches, use the micro-lane variant:
62849
+ [CANDIDATE] | candidate_id | micro_lane | severity | category | file:line | claim | invariant_violated | evidence_summary | confidence
62850
+
62851
+ Do NOT use CONFIRMED, DISPROVED, or PRE_EXISTING — those are reviewer verdicts.
62852
+
62815
62853
  ## INTEGRATION IMPACT ANALYSIS MODE
62816
62854
  Activates when delegated with "Integration impact analysis" or INPUT lists contract changes.
62817
62855
 
@@ -70106,7 +70144,7 @@ function isWriteToSwarmPlan(input) {
70106
70144
  const toolName = record3.toolName;
70107
70145
  if (typeof toolName !== "string")
70108
70146
  return false;
70109
- if (!["write", "edit", "apply_patch"].includes(toolName))
70147
+ if (!["write", "edit", "apply_patch", "swarm_apply_patch"].includes(toolName))
70110
70148
  return false;
70111
70149
  const rawPath = record3.path;
70112
70150
  const rawFile = record3.file;
@@ -70127,7 +70165,7 @@ function isWriteToEvidenceFile(input) {
70127
70165
  const toolName = record3.toolName;
70128
70166
  if (typeof toolName !== "string")
70129
70167
  return false;
70130
- if (!["write", "edit", "apply_patch"].includes(toolName))
70168
+ if (!["write", "edit", "apply_patch", "swarm_apply_patch"].includes(toolName))
70131
70169
  return false;
70132
70170
  const rawPath = record3.path;
70133
70171
  const rawFile = record3.file;
@@ -95786,7 +95824,7 @@ function deriveAction(tool3) {
95786
95824
  const toolLower = tool3.toLowerCase();
95787
95825
  if (toolLower === "task")
95788
95826
  return "delegate";
95789
- if (["write", "edit", "apply_patch"].includes(toolLower))
95827
+ if (["write", "edit", "apply_patch", "swarm_apply_patch"].includes(toolLower))
95790
95828
  return "edit";
95791
95829
  if (["read", "glob", "search"].includes(toolLower))
95792
95830
  return "read";
@@ -101265,7 +101303,7 @@ Output to .swarm/plan.md MUST use "## Phase N" headers. Do not write MODE labels
101265
101303
  1. DELEGATE all coding to {{AGENT_PREFIX}}coder. You do NOT write code.
101266
101304
  // IMPORTANT: This list is auto-generated from AGENT_TOOL_MAP['architect'] in src/config/constants.ts
101267
101305
  YOUR TOOLS: {{YOUR_TOOLS}}
101268
- CODER'S TOOLS: write, edit, patch, apply_patch, create_file, insert, replace — any tool that modifies file contents.
101306
+ CODER'S TOOLS: write, edit, patch, apply_patch, swarm_apply_patch, create_file, insert, replace — any tool that modifies file contents.
101269
101307
  If a tool modifies a file, it is a CODER tool. Delegate.
101270
101308
  <!-- BEHAVIORAL_GUIDANCE_START -->
101271
101309
  1a. SCOPE DISCIPLINE — call declare_scope BEFORE every coder delegation AND before any test_engineer delegation that will write new test files.
@@ -101307,7 +101345,7 @@ Two small delegations with two QA gates > one large delegation with one QA gate.
101307
101345
  ✗ "I already know what to write" → knowing what to write is planning, not writing. Delegate to {{AGENT_PREFIX}}coder.
101308
101346
  ✗ "It's faster if I just do it" → speed without QA gates is how bugs ship
101309
101347
  ✗ "The coder succeeded on the last tasks, this one is trivial" → Rule 1 has no complexity exemption
101310
- ✗ "I'll just use apply_patch / edit / write directly" → these are coder tools, not architect tools
101348
+ ✗ "I'll just use apply_patch / swarm_apply_patch / edit / write directly" → these are coder tools, not architect tools
101311
101349
  ✗ "I'll do the simple parts, coder does the hard parts" → ALL parts go to coder. You are not a coder.
101312
101350
  ✗ "This is time-critical / urgent / blocking" → WRONG. You are an AI with no deadlines. No urgency is real. Delegate to {{AGENT_PREFIX}}coder.
101313
101351
  ✗ "The fix is obvious — explaining it takes more effort than doing it" → WRONG. Writing the task spec IS your job. Delegate the implementation.
@@ -103669,6 +103707,7 @@ ${customAppendPrompt}`;
103669
103707
  edit: false,
103670
103708
  patch: false,
103671
103709
  apply_patch: false,
103710
+ swarm_apply_patch: false,
103672
103711
  create_file: false,
103673
103712
  insert: false,
103674
103713
  replace: false,
@@ -111418,7 +111457,7 @@ function extractMessageText2(msg) {
111418
111457
  `);
111419
111458
  }
111420
111459
  function extractToolName(text) {
111421
- const match = text.match(/^(read_file|write|edit|apply_patch|task|bun|npm|git|bash|glob|grep|mkdir|cp|mv|rm)\b/i);
111460
+ const match = text.match(/^(read_file|write|edit|apply_patch|swarm_apply_patch|task|bun|npm|git|bash|glob|grep|mkdir|cp|mv|rm)\b/i);
111422
111461
  return match?.[1];
111423
111462
  }
111424
111463
  function shouldMaskToolOutput(msg, index, totalMessages, recentWindowSize, threshold) {
@@ -120877,7 +120916,14 @@ function createCoChangeSuggesterHook(directory) {
120877
120916
  const hook = async (input, _output) => {
120878
120917
  const record3 = input;
120879
120918
  const toolName = typeof record3.tool === "string" ? record3.tool : "";
120880
- if (!["write", "edit", "apply_patch", "patch", "create_file"].includes(toolName)) {
120919
+ if (![
120920
+ "write",
120921
+ "edit",
120922
+ "apply_patch",
120923
+ "swarm_apply_patch",
120924
+ "patch",
120925
+ "create_file"
120926
+ ].includes(toolName)) {
120881
120927
  return;
120882
120928
  }
120883
120929
  const toolInput = record3.input;
@@ -124491,6 +124537,7 @@ var WRITE_EDIT_TOOLS = new Set([
124491
124537
  "write",
124492
124538
  "edit",
124493
124539
  "apply_patch",
124540
+ "swarm_apply_patch",
124494
124541
  "create_file"
124495
124542
  ]);
124496
124543
  var NEW_EXPORT_RE = /^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm;
@@ -125776,8 +125823,12 @@ function buildErrorResult(message) {
125776
125823
  }
125777
125824
  };
125778
125825
  }
125779
- var applyPatch = createSwarmTool({
125780
- description: "Apply a unified diff patch to workspace files. Validates paths, matches context exactly, and writes atomically. Coder-scoped write tool.",
125826
+ function isUnsupportedPatchFormat(patchText) {
125827
+ const trimmed = patchText.trimStart();
125828
+ return trimmed.startsWith("*** Begin Patch") || trimmed.startsWith("*** Update File") || trimmed.startsWith("*** Add File") || trimmed.startsWith("*** Delete File") || trimmed.startsWith("*** End Patch");
125829
+ }
125830
+ var swarmApplyPatch = createSwarmTool({
125831
+ description: "Apply a unified diff patch to workspace files. Validates paths, matches context exactly, and writes atomically. Coder-scoped write tool. Use standard unified diff format (--- a/file / +++ b/file / @@ hunks). Does NOT support *** Begin Patch / *** Update File payloads — use the native apply_patch tool for those.",
125781
125832
  args: {
125782
125833
  patch: exports_external.string().min(1).describe("Unified diff text to parse and apply"),
125783
125834
  files: exports_external.array(exports_external.string()).min(1).describe("Array of target file paths the patch is expected to touch. Every parsed target must appear in this list."),
@@ -125787,7 +125838,7 @@ var applyPatch = createSwarmTool({
125787
125838
  },
125788
125839
  execute: async (args2, directory) => {
125789
125840
  if (!args2 || typeof args2 !== "object") {
125790
- return JSON.stringify(buildErrorResult("Could not parse apply_patch arguments"), null, 2);
125841
+ return JSON.stringify(buildErrorResult("Could not parse swarm_apply_patch arguments"), null, 2);
125791
125842
  }
125792
125843
  const obj = args2;
125793
125844
  const patchText = obj.patch ?? "";
@@ -125804,6 +125855,9 @@ var applyPatch = createSwarmTool({
125804
125855
  if (!patchText || patchText.trim() === "") {
125805
125856
  return JSON.stringify(buildErrorResult("patch text cannot be empty"), null, 2);
125806
125857
  }
125858
+ if (isUnsupportedPatchFormat(patchText)) {
125859
+ return JSON.stringify(buildErrorResult("Unsupported patch format: *** Begin Patch / *** Update File style payloads are not supported by swarm_apply_patch. " + "Use the native apply_patch tool for this format, or provide a standard unified diff (--- a/file / +++ b/file / @@ hunks)."), null, 2);
125860
+ }
125807
125861
  for (const filePath of files) {
125808
125862
  const validationError = validatePatchTargetPath(filePath, directory);
125809
125863
  if (validationError) {
@@ -130096,6 +130150,20 @@ var MAX_COLLECT_TIMEOUT_MS = 60 * 60000;
130096
130150
  var COLLECT_POLL_INTERVAL_MS = 500;
130097
130151
  var MAX_COLLECT_POLL_INTERVAL_MS = 1e4;
130098
130152
  var AGENT_NAME_SEPARATORS = ["_", "-", " "];
130153
+ var EXPLORER_CANDIDATE_FORMAT_SUFFIX = `
130154
+
130155
+ IMPORTANT — OUTPUT FORMAT REQUIREMENT:
130156
+ You MUST emit your findings as pipe-delimited [CANDIDATE] rows.
130157
+ Header row first, then one row per finding.
130158
+
130159
+ Standard explorer format (use unless the prompt specifies micro-lane work):
130160
+ [CANDIDATE] | candidate_id | lane | severity | category | file:line | claim | evidence_summary | impact_context | confidence
130161
+
130162
+ Micro-lane format (use when the prompt references invariant checking or micro_lane):
130163
+ [CANDIDATE] | candidate_id | micro_lane | severity | category | file:line | claim | invariant_violated | evidence_summary | confidence
130164
+
130165
+ If you find zero issues, emit only the header row with no data rows.
130166
+ Do NOT use the default PROJECT/STRUCTURE output format for this dispatch.`;
130099
130167
  var READ_ONLY_LANE_ROLES = new Set([
130100
130168
  "explorer",
130101
130169
  "reviewer",
@@ -130157,7 +130225,7 @@ var CollectLaneResultsArgsSchema = exports_external.object({
130157
130225
  batch_id: exports_external.string().min(1).max(MAX_BATCH_ID_CHARS),
130158
130226
  wait: exports_external.boolean().optional().describe("Poll until all lanes settle or timeout"),
130159
130227
  timeout_ms: exports_external.number().int().min(0).max(MAX_COLLECT_TIMEOUT_MS).optional().describe("Total wait budget when wait=true"),
130160
- include_pending: exports_external.boolean().optional(),
130228
+ include_pending: exports_external.boolean().optional().describe("Include pending/running lanes in results with partial output; useful for progress checks during non-blocking polls"),
130161
130229
  cancel_pending: exports_external.boolean().optional().describe("Abort and mark pending/running lanes cancelled")
130162
130230
  });
130163
130231
  var _internals91 = {
@@ -130199,7 +130267,7 @@ async function executeDispatchLanes(args2, directory, context = {}) {
130199
130267
  errors: common.errors
130200
130268
  });
130201
130269
  }
130202
- const lanes = common.lanes;
130270
+ const lanes = applyExplorerFormatSuffix(common.lanes);
130203
130271
  const maxConcurrent = Math.min(parsed.data.max_concurrent ?? lanes.length, lanes.length, MAX_LANES);
130204
130272
  const timeoutMs = parsed.data.timeout_ms ?? DEFAULT_TIMEOUT_MS3;
130205
130273
  const dispatcher = _internals91.createParallelDispatcher({
@@ -130247,7 +130315,7 @@ async function executeDispatchLanesAsync(args2, directory, context = {}) {
130247
130315
  errors: common.errors
130248
130316
  });
130249
130317
  }
130250
- const lanes = common.lanes;
130318
+ const lanes = applyExplorerFormatSuffix(common.lanes);
130251
130319
  const batchId = parsed.data.batch_id ?? makeBatchId();
130252
130320
  if (findByBatchId(directory, batchId).length > 0) {
130253
130321
  return asyncFailureResult({
@@ -130888,6 +130956,22 @@ function applyCommonPrompt(lanes, commonPrompt) {
130888
130956
  return { ok: false, errors: errors5 };
130889
130957
  return { ok: true, lanes: merged };
130890
130958
  }
130959
+ function applyExplorerFormatSuffix(lanes) {
130960
+ const generatedAgentNames = _internals91.getGeneratedAgentNames();
130961
+ return lanes.map((lane) => {
130962
+ const role = resolveGeneratedAgentRole(lane.agent, generatedAgentNames);
130963
+ if (role !== "explorer")
130964
+ return lane;
130965
+ if (lane.prompt.includes("[CANDIDATE]"))
130966
+ return lane;
130967
+ const prompt = `${lane.prompt}${EXPLORER_CANDIDATE_FORMAT_SUFFIX}`;
130968
+ if (prompt.length > MAX_PROMPT_CHARS) {
130969
+ console.warn(`[dispatch-lanes] applyExplorerFormatSuffix: lane "${lane.id}" prompt too long ` + `(${lane.prompt.length} chars + suffix = ${prompt.length}, max ${MAX_PROMPT_CHARS}); ` + `format enforcement skipped — explorer may not emit [CANDIDATE] rows`);
130970
+ return lane;
130971
+ }
130972
+ return { ...lane, prompt };
130973
+ });
130974
+ }
130891
130975
  function findDuplicateLaneIds(lanes) {
130892
130976
  const seen = new Set;
130893
130977
  const duplicates = new Set;
@@ -130987,7 +131071,7 @@ var dispatch_lanes = createSwarmTool({
130987
131071
  }
130988
131072
  });
130989
131073
  var dispatch_lanes_async = createSwarmTool({
130990
- description: "Launch multiple read-only advisory lanes with OpenCode promptAsync and return IMMEDIATELY with a batch id (non-blocking). After launching, keep working on non-dependent tasks while the lanes run, then call collect_lane_results to join. Keep each lane prompt compact: send large shared context once via common_prompt (or have lanes read it from a file by absolute path) instead of inlining it into every lane prompt, which can produce oversized or malformed tool-call JSON.",
131074
+ description: "Launch multiple read-only advisory lanes with OpenCode promptAsync and return IMMEDIATELY with a batch id (non-blocking). After launching, keep working on non-dependent investigation while lanes run poll incrementally with collect_lane_results (wait omitted or false) to process settled lanes as they complete, or use wait: true only at workflow boundaries where all results are needed. Keep each lane prompt compact: send large shared context once via common_prompt (or have lanes read it from a file by absolute path) instead of inlining it into every lane prompt, which can produce oversized or malformed tool-call JSON.",
130991
131075
  args: {
130992
131076
  lanes: DispatchLanesAsyncArgsSchema.shape.lanes,
130993
131077
  common_prompt: DispatchLanesAsyncArgsSchema.shape.common_prompt,
@@ -131007,7 +131091,7 @@ var dispatch_lanes_async = createSwarmTool({
131007
131091
  }
131008
131092
  });
131009
131093
  var collect_lane_results = createSwarmTool({
131010
- description: "Collect or poll results for a dispatch_lanes_async batch; this is the required join barrier for advisory lane workflows and does not advance workflow gates.",
131094
+ description: "Collect or poll results for a dispatch_lanes_async batch. Supports two modes: (1) non-blocking poll (wait omitted or false) — performs one collection pass and returns current lane status and any settled results so you can process completed lanes while continuing independent work; (2) blocking join (wait: true) — polls until all lanes settle or timeout. Use non-blocking polls to check progress incrementally; use blocking join only at workflow boundaries where all results are required. Does not advance workflow gates.",
131011
131095
  args: {
131012
131096
  batch_id: CollectLaneResultsArgsSchema.shape.batch_id,
131013
131097
  wait: CollectLaneResultsArgsSchema.shape.wait,
@@ -138790,12 +138874,33 @@ function refusalResult(errorCode, errorMessage3, input, flags) {
138790
138874
  diagnostics: buildEmptyDiagnostics(input, flags)
138791
138875
  };
138792
138876
  }
138877
+ function detectFormatMismatchHint(text) {
138878
+ if (text.trim() === "")
138879
+ return;
138880
+ const severityPattern = /\b(CRITICAL|HIGH|MEDIUM|LOW|INFO)\b/;
138881
+ const fileLinePattern = /\b\S+\.[a-z]{1,4}:\d+\b/;
138882
+ const hasSeverity = severityPattern.test(text);
138883
+ const textForFileLine = text.replace(/\b\w+:\/\/\S*/g, "");
138884
+ const hasFileLine = fileLinePattern.test(textForFileLine);
138885
+ if (hasSeverity && hasFileLine) {
138886
+ return "Lane output contains severity keywords and file:line references but no parseable [CANDIDATE] rows. The explorer may have emitted findings in prose format instead of pipe-delimited candidate rows.";
138887
+ }
138888
+ if (hasSeverity) {
138889
+ return "Lane output contains severity keywords but no parseable [CANDIDATE] rows. The explorer may have emitted findings in an unstructured format.";
138890
+ }
138891
+ return;
138892
+ }
138793
138893
  function emptyTextResult(input, flags) {
138794
138894
  const envelope = buildInvocationEnvelope(input, flags, [], 0, 0, 0);
138895
+ const diagnostics = buildEmptyDiagnostics(input, flags);
138896
+ const hint = detectFormatMismatchHint(input.text);
138897
+ if (hint) {
138898
+ diagnostics.format_mismatch_hint = hint;
138899
+ }
138795
138900
  return {
138796
138901
  candidates: [],
138797
138902
  invocation_envelope: envelope,
138798
- diagnostics: buildEmptyDiagnostics(input, flags)
138903
+ diagnostics
138799
138904
  };
138800
138905
  }
138801
138906
  function parseCandidates(input, flags) {
@@ -138982,20 +139087,27 @@ ${trimmed}`;
138982
139087
  }
138983
139088
  const parseErrors = parseErrorDetails.length;
138984
139089
  const envelope = buildInvocationEnvelope(input, flags, Array.from(formatFamiliesDetected), candidates.length, parseErrors, malformedRows);
139090
+ const diagnostics = {
139091
+ candidate_count: candidates.length,
139092
+ parse_errors: parseErrors,
139093
+ parse_error_details: parseErrorDetails,
139094
+ malformed_rows: malformedRows,
139095
+ duplicate_id_count: duplicateIdCount,
139096
+ duplicate_id_warnings: duplicateIdWarnings,
139097
+ degraded_source_count: flags.degraded ? 1 : 0,
139098
+ incomplete_source_count: input.transcriptIncomplete ? 1 : 0,
139099
+ format_families_detected: Array.from(formatFamiliesDetected)
139100
+ };
139101
+ if (candidates.length === 0) {
139102
+ const hint = detectFormatMismatchHint(input.text);
139103
+ if (hint) {
139104
+ diagnostics.format_mismatch_hint = hint;
139105
+ }
139106
+ }
138985
139107
  return {
138986
139108
  candidates,
138987
139109
  invocation_envelope: envelope,
138988
- diagnostics: {
138989
- candidate_count: candidates.length,
138990
- parse_errors: parseErrors,
138991
- parse_error_details: parseErrorDetails,
138992
- malformed_rows: malformedRows,
138993
- duplicate_id_count: duplicateIdCount,
138994
- duplicate_id_warnings: duplicateIdWarnings,
138995
- degraded_source_count: flags.degraded ? 1 : 0,
138996
- incomplete_source_count: input.transcriptIncomplete ? 1 : 0,
138997
- format_families_detected: Array.from(formatFamiliesDetected)
138998
- }
139110
+ diagnostics
138999
139111
  };
139000
139112
  }
139001
139113
  function parseAndPersist(input, flags, options) {
@@ -154335,7 +154447,7 @@ var TOOL_MANIFEST = defineHandlers({
154335
154447
  lean_turbo_review: () => lean_turbo_review,
154336
154448
  lean_turbo_run_phase: () => lean_turbo_run_phase,
154337
154449
  lean_turbo_status: () => lean_turbo_status,
154338
- apply_patch: () => applyPatch,
154450
+ swarm_apply_patch: () => swarmApplyPatch,
154339
154451
  external_skill_discover: () => external_skill_discover,
154340
154452
  external_skill_list: () => external_skill_list,
154341
154453
  external_skill_inspect: () => external_skill_inspect,
@@ -45,4 +45,10 @@ export interface ApplyPatchArgs {
45
45
  allowCreates?: boolean;
46
46
  allowDeletes?: boolean;
47
47
  }
48
- export declare const applyPatch: ToolDefinition;
48
+ /**
49
+ * Swarm unified-diff patch tool (formerly registered as apply_patch).
50
+ * Renamed to swarm_apply_patch so it no longer shadows the native opencode
51
+ * apply_patch tool. The native tool handles *** Begin Patch / *** Update File
52
+ * style payloads; this tool handles standard unified diffs only.
53
+ */
54
+ export declare const swarmApplyPatch: ToolDefinition;
@@ -201,6 +201,7 @@ export declare const _internals: {
201
201
  };
202
202
  export declare const _test_exports: {
203
203
  applyCommonPrompt: typeof applyCommonPrompt;
204
+ applyExplorerFormatSuffix: typeof applyExplorerFormatSuffix;
204
205
  extractAssistantTranscript: typeof extractAssistantTranscript;
205
206
  formatError: typeof formatError;
206
207
  nextCollectPollInterval: typeof nextCollectPollInterval;
@@ -274,6 +275,7 @@ type ApplyCommonPromptResult = {
274
275
  * prompts when it is. Callers may treat the returned array as their own.
275
276
  */
276
277
  declare function applyCommonPrompt(lanes: DispatchLaneSpec[], commonPrompt: string | undefined): ApplyCommonPromptResult;
278
+ declare function applyExplorerFormatSuffix(lanes: DispatchLaneSpec[]): DispatchLaneSpec[];
277
279
  declare function formatError(error: unknown): string;
278
280
  declare function promptHash(lane: DispatchLaneSpec, directory: string, batchId: string): string;
279
281
  export declare const dispatch_lanes: ReturnType<typeof createSwarmTool>;
@@ -1,6 +1,6 @@
1
- import { applyPatch } from './apply-patch';
2
- export { applyPatch };
3
- export declare const apply_patch: typeof applyPatch;
1
+ import { swarmApplyPatch } from './apply-patch';
2
+ export { swarmApplyPatch };
3
+ export declare const swarm_apply_patch: typeof swarmApplyPatch;
4
4
  export { batch_symbols } from './batch-symbols';
5
5
  export { build_check } from './build-check';
6
6
  export { check_gate_status } from './check-gate-status';
@@ -112,7 +112,7 @@ export declare const TOOL_MANIFEST: {
112
112
  lean_turbo_review: () => ToolDefinition;
113
113
  lean_turbo_run_phase: () => ToolDefinition;
114
114
  lean_turbo_status: () => ToolDefinition;
115
- apply_patch: () => ToolDefinition;
115
+ swarm_apply_patch: () => ToolDefinition;
116
116
  external_skill_discover: () => ToolDefinition;
117
117
  external_skill_list: () => ToolDefinition;
118
118
  external_skill_inspect: () => ToolDefinition;
@@ -379,7 +379,7 @@ export declare const TOOL_METADATA: {
379
379
  description: string;
380
380
  agents: never[];
381
381
  };
382
- apply_patch: {
382
+ swarm_apply_patch: {
383
383
  description: string;
384
384
  agents: ("test_engineer" | "coder")[];
385
385
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "7.91.0",
3
+ "version": "7.92.0",
4
4
  "description": "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",