opencode-swarm 7.114.2 → 7.114.3

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.
@@ -14,7 +14,7 @@ import {
14
14
  runCuratorInit,
15
15
  runCuratorPhase,
16
16
  writeCuratorSummary
17
- } from "./index-64168f15.js";
17
+ } from "./index-e8zaze89.js";
18
18
  import"./index-g6va6n3t.js";
19
19
  import"./index-c8s9a3zh.js";
20
20
  import"./index-2148358e.js";
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  createCuratorLLMDelegate
4
- } from "./index-64168f15.js";
4
+ } from "./index-e8zaze89.js";
5
5
  import"./index-g6va6n3t.js";
6
6
  import"./index-c8s9a3zh.js";
7
7
  import"./index-2148358e.js";
@@ -1,8 +1,8 @@
1
1
  // @bun
2
2
  import {
3
3
  handleGuardrailExplain
4
- } from "./index-tnm0e2vb.js";
5
- import"./index-64168f15.js";
4
+ } from "./index-hnv7rrf9.js";
5
+ import"./index-e8zaze89.js";
6
6
  import"./index-g6va6n3t.js";
7
7
  import"./index-c8s9a3zh.js";
8
8
  import"./index-2148358e.js";
@@ -6,7 +6,7 @@ import {
6
6
  isHiveEligible,
7
7
  promoteFromSwarm,
8
8
  promoteToHive
9
- } from "./index-64168f15.js";
9
+ } from "./index-e8zaze89.js";
10
10
  import"./index-g6va6n3t.js";
11
11
  import"./index-c8s9a3zh.js";
12
12
  import"./index-2148358e.js";
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  handleGuardrailExplain
4
- } from "./index-tnm0e2vb.js";
4
+ } from "./index-hnv7rrf9.js";
5
5
  import {
6
6
  handleGuardrailLog
7
7
  } from "./index-xbe1wtme.js";
@@ -81,7 +81,7 @@ import {
81
81
  handleWriteRetroCommand,
82
82
  normalizeSwarmCommandInput,
83
83
  resolveCommand
84
- } from "./index-64168f15.js";
84
+ } from "./index-e8zaze89.js";
85
85
  import"./index-g6va6n3t.js";
86
86
  import"./index-c8s9a3zh.js";
87
87
  import"./index-2148358e.js";
@@ -10432,11 +10432,11 @@ var _internals12 = {
10432
10432
  return KnowledgeConfigSchema2.parse({});
10433
10433
  },
10434
10434
  applyCuratorKnowledgeUpdates: async (directory, recommendations, knowledgeConfig) => {
10435
- const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-2g6v327b.js");
10435
+ const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-68rn0ss8.js");
10436
10436
  return applyCuratorKnowledgeUpdates2(directory, recommendations, knowledgeConfig);
10437
10437
  },
10438
10438
  checkHivePromotions: async (entries, knowledgeConfig) => {
10439
- const { checkHivePromotions } = await import("./hive-promoter-bxngckjh.js");
10439
+ const { checkHivePromotions } = await import("./hive-promoter-h3jcrdh0.js");
10440
10440
  return checkHivePromotions(entries, knowledgeConfig);
10441
10441
  },
10442
10442
  applyProposalTriage: async (directory, triage) => {
@@ -15177,7 +15177,9 @@ var ARCHIVE_ARTIFACTS = [
15177
15177
  "swarm.db-wal",
15178
15178
  "close-summary.md",
15179
15179
  "session-reflection.md",
15180
- "spec.md"
15180
+ "spec.md",
15181
+ "spec-staleness.json",
15182
+ "spec-snapshot.md"
15181
15183
  ];
15182
15184
  var ACTIVE_STATE_TO_CLEAN = [
15183
15185
  "plan.json",
@@ -15194,11 +15196,19 @@ var ACTIVE_STATE_TO_CLEAN = [
15194
15196
  "dark-matter.md",
15195
15197
  "telemetry.jsonl",
15196
15198
  "session-reflection.md",
15199
+ "spec.md",
15200
+ "spec-staleness.json",
15201
+ "spec-snapshot.md",
15197
15202
  "swarm.db",
15198
15203
  "swarm.db-shm",
15199
15204
  "swarm.db-wal"
15200
15205
  ];
15201
- var TERMINAL_STATE_FILES = ["plan.json", "plan-ledger.jsonl"];
15206
+ var TERMINAL_STATE_FILES = [
15207
+ "plan.json",
15208
+ "plan-ledger.jsonl",
15209
+ "spec-staleness.json",
15210
+ "spec-snapshot.md"
15211
+ ];
15202
15212
  var KNOWLEDGE_FAMILY_ARTIFACTS = new Set([
15203
15213
  "knowledge.jsonl",
15204
15214
  "knowledge-rejected.jsonl"
@@ -15713,7 +15723,9 @@ async function runCleanStage(ctx) {
15713
15723
  ctx.warnings.push(reason ? `${artifact} was not archived (${reason}); removing it anyway to prevent CLOSED-plan resurrection next session \u2014 no archive copy retained.` : `${artifact} was not archived; removing it anyway to prevent CLOSED-plan resurrection next session \u2014 no archive copy retained.`);
15714
15724
  continue;
15715
15725
  }
15716
- ctx.warnings.push(reason ? `Preserved ${artifact} because it was not successfully archived: ${reason}.` : `Preserved ${artifact} because it was not successfully archived.`);
15726
+ if (reason) {
15727
+ ctx.warnings.push(`Preserved ${artifact} because it was not successfully archived: ${reason}.`);
15728
+ }
15717
15729
  continue;
15718
15730
  }
15719
15731
  const filePath = path29.join(ctx.swarmDir, artifact);
@@ -17585,8 +17597,8 @@ var _internals24 = {
17585
17597
  loadCuratorDeps: async () => {
17586
17598
  const [{ CuratorConfigSchema }, curator, { createCuratorLLMDelegate: createCuratorLLMDelegate2 }] = await Promise.all([
17587
17599
  import("./schema-e5kd993s.js"),
17588
- import("./curator-2g6v327b.js"),
17589
- import("./curator-llm-factory-31e6dsqe.js")
17600
+ import("./curator-68rn0ss8.js"),
17601
+ import("./curator-llm-factory-fpzm8j0g.js")
17590
17602
  ]);
17591
17603
  return { CuratorConfigSchema, curator, createCuratorLLMDelegate: createCuratorLLMDelegate2 };
17592
17604
  }
@@ -18082,7 +18094,7 @@ import { fileURLToPath } from "url";
18082
18094
  // package.json
18083
18095
  var package_default = {
18084
18096
  name: "opencode-swarm",
18085
- version: "7.114.2",
18097
+ version: "7.114.3",
18086
18098
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
18087
18099
  main: "dist/index.js",
18088
18100
  types: "dist/index.d.ts",
@@ -30322,7 +30334,11 @@ async function handleResetCommand(directory, args) {
30322
30334
  const filesToReset = [
30323
30335
  "plan.md",
30324
30336
  "plan.json",
30337
+ "plan-ledger.jsonl",
30325
30338
  "context.md",
30339
+ "spec.md",
30340
+ "spec-staleness.json",
30341
+ "spec-snapshot.md",
30326
30342
  "SWARM_PLAN.md",
30327
30343
  "SWARM_PLAN.json",
30328
30344
  "plan-export/SWARM_PLAN.md",
@@ -32968,7 +32984,7 @@ function buildDetailedHelp(commandName, entry) {
32968
32984
  async function handleHelpCommand(ctx) {
32969
32985
  const targetCommand = ctx.args.join(" ");
32970
32986
  if (!targetCommand) {
32971
- const { buildHelpText } = await import("./index-fdwtf08h.js");
32987
+ const { buildHelpText } = await import("./index-by2gt09c.js");
32972
32988
  return buildHelpText();
32973
32989
  }
32974
32990
  const tokens = targetCommand.split(/\s+/);
@@ -32977,7 +32993,7 @@ async function handleHelpCommand(ctx) {
32977
32993
  return _internals49.buildDetailedHelp(resolved.key, resolved.entry);
32978
32994
  }
32979
32995
  const similar = _internals49.findSimilarCommands(targetCommand);
32980
- const { buildHelpText: fullHelp } = await import("./index-fdwtf08h.js");
32996
+ const { buildHelpText: fullHelp } = await import("./index-by2gt09c.js");
32981
32997
  if (similar.length > 0) {
32982
32998
  return `Command '/swarm ${targetCommand}' not found.
32983
32999
 
@@ -33110,7 +33126,7 @@ var COMMAND_REGISTRY = {
33110
33126
  },
33111
33127
  "guardrail explain": {
33112
33128
  handler: async (ctx) => {
33113
- const { handleGuardrailExplain } = await import("./guardrail-explain-ygvp1aj9.js");
33129
+ const { handleGuardrailExplain } = await import("./guardrail-explain-k3bb68q5.js");
33114
33130
  return handleGuardrailExplain(ctx.directory, ctx.args);
33115
33131
  },
33116
33132
  description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
@@ -33120,7 +33136,7 @@ var COMMAND_REGISTRY = {
33120
33136
  },
33121
33137
  "guardrail-explain": {
33122
33138
  handler: async (ctx) => {
33123
- const { handleGuardrailExplain } = await import("./guardrail-explain-ygvp1aj9.js");
33139
+ const { handleGuardrailExplain } = await import("./guardrail-explain-k3bb68q5.js");
33124
33140
  return handleGuardrailExplain(ctx.directory, ctx.args);
33125
33141
  },
33126
33142
  description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
@@ -12,7 +12,7 @@ import {
12
12
  detectPosixWrites,
13
13
  detectWindowsWrites,
14
14
  resolveWriteTargets
15
- } from "./index-64168f15.js";
15
+ } from "./index-e8zaze89.js";
16
16
  import {
17
17
  checkFileAuthority,
18
18
  classifyFile,
package/dist/cli/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  getPluginLockFilePaths,
8
8
  package_default,
9
9
  resolveCommand
10
- } from "./index-64168f15.js";
10
+ } from "./index-e8zaze89.js";
11
11
  import"./index-g6va6n3t.js";
12
12
  import"./index-c8s9a3zh.js";
13
13
  import"./index-2148358e.js";
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import{createRequire}from"node:module";var __create=Object.create;var{getPrototypeOf:__getProtoOf,defineProperty:__defProp,getOwnPropertyNames:__getOwnPropNames,getOwnPropertyDescriptor:__getOwnPropDesc}=Object,__hasOwnProp=Object.prototype.hasOwnProperty;function __accessProp(key){return this[key]}var __toESMCache_node,__toESMCache_esm,__toESM=(mod,isNodeMode,target)=>{var canCache=mod!=null&&typeof mod==="object";if(canCache){var cache=isNodeMode?__toESMCache_node??=new WeakMap:__toESMCache_esm??=new WeakMap,cached=cache.get(mod);if(cached)return cached}target=mod!=null?__create(__getProtoOf(mod)):{};let to=isNodeMode||!mod||!mod.__esModule?__defProp(target,"default",{value:mod,enumerable:!0}):target;for(let key of __getOwnPropNames(mod))if(!__hasOwnProp.call(to,key))__defProp(to,key,{get:__accessProp.bind(mod,key),enumerable:!0});if(canCache)cache.set(mod,to);return to},__toCommonJS=(from)=>{var entry=(__moduleCache??=new WeakMap).get(from),desc;if(entry)return entry;if(entry=__defProp({},"__esModule",{value:!0}),from&&typeof from==="object"||typeof from==="function"){for(var key of __getOwnPropNames(from))if(!__hasOwnProp.call(entry,key))__defProp(entry,key,{get:__accessProp.bind(from,key),enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return __moduleCache.set(from,entry),entry},__moduleCache,__commonJS=(cb,mod)=>()=>(mod||cb((mod={exports:{}}).exports,mod),mod.exports);var __returnValue=(v)=>v;function __exportSetter(name,newValue){this[name]=__returnValue.bind(null,newValue)}var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0,configurable:!0,set:__exportSetter.bind(all,name)})};var __esm=(fn2,res)=>()=>(fn2&&(res=fn2(fn2=0)),res);var __require=createRequire(import.meta.url);var package_default;var init_package=__esm(()=>{package_default={name:"opencode-swarm",version:"7.114.2",description:"Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",main:"dist/index.js",types:"dist/index.d.ts",exports:{".":{types:"./dist/index.d.ts",default:"./dist/index.js"},"./package.json":"./package.json"},bin:{"opencode-swarm":"./dist/cli/index.js"},type:"module",engines:{bun:">=1.3.13"},license:"MIT",repository:{type:"git",url:"https://github.com/ZaxbyHub/opencode-swarm.git"},publishConfig:{access:"public",registry:"https://registry.npmjs.org/"},keywords:["opencode","opencode-plugin","ai","agents","orchestration","swarm","multi-agent","llm"],files:["dist","dist/lang/grammars","binaries",".opencode/skills/brainstorm",".opencode/skills/specify",".opencode/skills/clarify-spec",".opencode/skills/resume",".opencode/skills/clarify",".opencode/skills/discover",".opencode/skills/consult",".opencode/skills/pre-phase-briefing",".opencode/skills/council",".opencode/skills/deep-dive",".opencode/skills/deep-research",".opencode/skills/codebase-review-swarm",".opencode/skills/swarm-implement",".opencode/skills/design-docs",".opencode/skills/swarm-pr-review",".opencode/skills/swarm",".opencode/skills/swarm-pr-feedback",".opencode/skills/swarm-pr-subscribe",".opencode/skills/swarm-ci-monitor",".opencode/skills/issue-ingest",".opencode/skills/plan",".opencode/skills/critic-gate",".opencode/skills/execute",".opencode/skills/phase-wrap",".opencode/skills/loop",".opencode/skills/writing-tests",".opencode/skills/running-tests",".opencode/skills/engineering-conventions",".opencode/skills/commit-pr",".opencode/skills/ci-failure-batching",".opencode/skills/gate-attribution",".opencode/skills/merge-queue-readiness",".opencode/skills/skill-edit-validation",".opencode/skills/worktree-retry-cleanup",".opencode/skills/test-file-split",".opencode/skills/fork-pr-operations",".opencode/skills/parallel-work-check",".opencode/skills/ci-fix-monitor","tests/fixtures/memory-recall","README.md","LICENSE"],scripts:{clean:`bun -e "require('fs').rmSync('dist',{recursive:true,force:true})"`,build:"bun run clean && bun run scripts/copy-grammars.ts && bun build src/index.ts --outdir dist --target node --format esm --external web-tree-sitter --minify-whitespace --minify-syntax && bun build src/cli/index.ts --outdir dist/cli --target bun --format esm --external bash-parser --splitting && bun run scripts/copy-grammars.ts --to-dist && tsc --emitDeclarationOnly",typecheck:"tsc --noEmit",test:"bun test",lint:"biome lint .","lint:ci":"biome ci .","test:unit:ci":"bun scripts/ci/run-unit-tests-local.ts","drift:check":"bun run scripts/drift-check.ts","drift:fix":"bun run scripts/drift-check.ts --fix --confirm",format:"biome format . --write",check:"biome check --write .",dev:"bun run build && opencode","package:smoke":"node scripts/package-smoke.mjs",prepare:"bun run build","repro:704":"node scripts/repro-704.mjs","repro:1144":"bun scripts/repro-1144.mjs"},dependencies:{"@opencode-ai/plugin":"^1.1.53","@opencode-ai/sdk":"^1.1.53","@vscode/tree-sitter-wasm":"^0.3.0","bash-parser":"^0.5.0","p-limit":"^7.3.0",picomatch:"^4.0.4","proper-lockfile":"^4.1.2","quick-lru":"^7.3.0","web-tree-sitter":"^0.25.0",zod:"^4.1.8"},devDependencies:{"@biomejs/biome":"2.3.14","@types/picomatch":"^4.0.3","bun-types":"1.3.8","js-yaml":"^4.1.1",typescript:"^5.7.3"}}});var QA_AGENTS,PIPELINE_AGENTS,ORCHESTRATOR_NAME="architect",ALL_SUBAGENT_NAMES,ALL_AGENT_NAMES;var init_agent_names=__esm(()=>{QA_AGENTS=["reviewer","critic","critic_oversight"],PIPELINE_AGENTS=["explorer","coder","test_engineer"],ALL_SUBAGENT_NAMES=["sme","researcher","docs","docs_design","designer","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","critic_architecture_supervisor","curator_init","curator_phase","curator_postmortem","curator_consolidation","council_generalist","council_skeptic","council_domain_expert","skill_improver","spec_writer",...QA_AGENTS,...PIPELINE_AGENTS],ALL_AGENT_NAMES=["architect",...ALL_SUBAGENT_NAMES]});var TOOL_METADATA,TOOL_NAMES,TOOL_NAME_SET,TOOL_DESCRIPTIONS,AGENT_TOOL_MAP;var init_tool_metadata=__esm(()=>{init_agent_names();TOOL_METADATA={diff:{description:"structured git diff with contract change detection",agents:["architect","reviewer","critic_oversight","coder","test_engineer"]},diff_summary:{description:"filter classified AST changes by category, risk level, or file for reviewer drill-down",agents:["architect","reviewer","critic_oversight"]},syntax_check:{description:"check syntax of source files using tree-sitter parsers across multiple languages, returning per-file errors",agents:["architect","coder","test_engineer"]},placeholder_scan:{description:"todo and FIXME comment detection",agents:["architect","reviewer"]},imports:{description:"find all consumers that import from a given file — use before refactoring shared modules to avoid breaking unseen dependents",agents:["architect","sme","researcher","docs","docs_design","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","reviewer","critic","coder","test_engineer"]},lint:{description:"run project linter in check or fix mode; supports biome, eslint, ruff, clippy, and more, returns structured results",agents:["architect","reviewer","coder"]},secretscan:{description:"scan for secrets (API keys, tokens, passwords) via regex and entropy; returns redacted previews, excludes common dirs",agents:["architect","reviewer","critic_oversight"]},sast_scan:{description:"static analysis security scan",agents:["architect","reviewer","critic_oversight"]},build_check:{description:"discover and run build, typecheck, and test commands for various project ecosystems in the working directory",agents:["architect","coder","test_engineer"]},pre_check_batch:{description:"parallel verification: lint:check + secretscan + sast_scan + quality_budget",agents:["architect","reviewer"]},quality_budget:{description:"code quality budget check",agents:["architect"]},symbols:{description:"extract exported symbols (functions, classes, interfaces, types) from source files; supports TypeScript, JavaScript, and Python",agents:["architect","sme","researcher","docs","docs_design","designer","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","spec_writer","reviewer","critic","coder","test_engineer"]},complexity_hotspots:{description:"git churn × complexity risk map",agents:["architect","sme","researcher","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","reviewer","critic","critic_oversight","explorer","test_engineer"]},schema_drift:{description:"OpenAPI spec vs route drift",agents:["architect","sme","researcher","docs","explorer"]},todo_extract:{description:"structured TODO/FIXME extraction",agents:["architect","researcher","docs","explorer"]},evidence_check:{description:"verify task evidence completeness",agents:["architect","critic_oversight"]},check_gate_status:{description:"check the gate status of a specific task",agents:["architect","critic_oversight"]},completion_verify:{description:"verify completed tasks have required evidence",agents:["architect","critic_oversight"]},submit_council_verdicts:{description:"submit pre-collected council member verdicts for synthesis (architect MUST dispatch critic/reviewer/sme/test_engineer/explorer as Agent tasks first; this tool synthesizes only, it does not contact members)",agents:[]},submit_phase_council_verdicts:{description:"submit pre-collected phase-level council member verdicts for holistic phase synthesis (architect MUST dispatch all 5 council members with phase-scoped context first; this tool synthesizes only, it does not contact members)",agents:[]},declare_council_criteria:{description:"pre-declare acceptance criteria for a task before the coder starts work; criteria are read back during council evaluation",agents:[]},sbom_generate:{description:"SBOM generation for dependency inventory",agents:["architect"]},checkpoint:{description:"create named git checkpoints for save, restore, and delete — use before risky operations to enable rollback",agents:["architect"]},pkg_audit:{description:"dependency vulnerability scan — npm/pip/cargo",agents:["architect","critic_hallucination_verifier","reviewer","critic_oversight","test_engineer"]},parse_lane_candidates:{description:"Parse [CANDIDATE] rows from a dispatch_lanes or collect_lane_results artifact (by output_ref), produce structured records with provenance, optionally persist to a per-batch sidecar JSONL. Pure-parser variant exists as internal module.",agents:["architect"]},test_runner:{description:"auto-detect and run tests",agents:["architect","reviewer","test_engineer"]},test_impact:{description:"identify test files impacted by changed source files via import analysis",agents:["architect","reviewer","critic_oversight","test_engineer"]},mutation_test:{description:"executes pre-generated mutation patches against tests, evaluates kill rate against quality gate thresholds",agents:["architect","test_engineer"]},generate_mutants:{description:"generate LLM-based mutation testing patches for source files; returns MutationPatch[] for direct consumption by the mutation_test tool",agents:["architect"]},detect_domains:{description:"detect which SME domains are relevant for a given text",agents:["architect","sme","docs","docs_design","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","critic","critic_oversight","explorer"]},git_blame:{description:"per-line git blame metadata: sha, author, date, summary for each line in a file",agents:["reviewer","explorer","architect"]},gitingest:{description:"fetch a GitHub repository full content via gitingest.com",agents:["architect","docs","explorer"]},retrieve_summary:{description:"retrieve the full content of a stored tool output summary",agents:["architect","sme","docs","docs_design","designer","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","critic_architecture_supervisor","spec_writer","reviewer","critic","coder","test_engineer"]},retrieve_lane_output:{description:"retrieve paged full dispatch lane output by output_ref; use before consuming truncated lane previews or routing candidates from lane results",agents:["architect"]},extract_code_blocks:{description:"extract code blocks from text content and save them to files",agents:["docs","docs_design","designer","spec_writer","coder","test_engineer"]},phase_complete:{description:"mark a phase as complete and track dispatched agents",agents:["architect"]},save_plan:{description:"save a structured implementation plan",agents:["architect"]},update_task_status:{description:"mark tasks complete, track phase progress",agents:["architect"]},lint_spec:{description:"validate .swarm/spec.md format and required fields",agents:["architect","spec_writer"]},write_retro:{description:"document phase retrospectives via phase_complete workflow, capture lessons learned",agents:["architect"]},write_drift_evidence:{description:"write drift verification evidence for a completed phase",agents:["architect"]},write_hallucination_evidence:{description:"write hallucination verification evidence for a completed phase",agents:["architect"]},write_mutation_evidence:{description:"write mutation gate evidence for a completed phase; normalizes PASS/WARN/FAIL/SKIP verdicts and writes .swarm/evidence/{phase}/mutation-gate.json",agents:["architect"]},declare_scope:{description:"declare file scope for next coder delegation",agents:["architect"]},knowledge_query:{description:"query swarm or hive knowledge with optional filters",agents:["architect","skill_improver","spec_writer"]},doc_scan:{description:"scan project documentation files and build an index manifest",agents:["architect","docs_design","skill_improver","spec_writer","explorer"]},doc_extract:{description:"extract actionable constraints from project documentation",agents:["architect","docs_design","skill_improver","spec_writer"]},curator_analyze:{description:"run curator phase analysis and optionally apply knowledge recommendations",agents:["architect"]},knowledge_add:{description:"store a new lesson in the knowledge base",agents:["architect","coder"]},knowledge_recall:{description:"search the knowledge base for relevant past decisions",agents:["architect","sme","docs","docs_design","designer","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","critic_architecture_supervisor","curator_init","curator_phase","skill_improver","spec_writer","reviewer","critic","critic_oversight","explorer","coder","test_engineer"]},knowledge_remove:{description:"delete an outdated swarm knowledge entry by ID (swarm tier only)",agents:["architect"]},co_change_analyzer:{description:"detect hidden couplings by analyzing git history",agents:["architect"]},context_status:{description:"report current context-window headroom for the active session — returns tokens-used, model-limit, usage-percent, threshold-state (none/warn/critical), model name, and provider. Pure read-only: no state mutation, no warning injection. Works whether context_budget.enabled is true or false.",agents:["architect"]},search:{description:"Workspace-scoped ripgrep-style text search with structured JSON output. Supports literal and regex modes, glob filtering, and result limits. NOTE: This is text search, not structural AST search — use symbols and imports tools for structural queries.",agents:["architect","sme","docs","docs_design","designer","critic_hallucination_verifier","skill_improver","spec_writer","reviewer","critic_oversight","explorer","coder","test_engineer","researcher"]},ast_grep:{description:"Read-only structural AST search using ast-grep patterns with optional language and glob filters. Use for syntax-aware code pattern searches; does not rewrite files.",agents:["architect","sme","docs","docs_design","critic_hallucination_verifier","spec_writer","explorer","coder","test_engineer","researcher"]},actionlint_scan:{description:"Run actionlint against GitHub Actions workflow YAML files with structured findings. Resolves actionlint lazily and does not modify files.",agents:["architect","test_engineer"]},osv_scan:{description:"Run OSV-Scanner against a workspace path and return structured dependency vulnerability findings. Resolves osv-scanner lazily and does not modify files.",agents:["architect","test_engineer"]},gh_evidence:{description:"Fetch bounded GitHub pull request or issue metadata through gh for review and CI evidence. Resolves gh lazily and is read-only.",agents:["architect","researcher"]},batch_symbols:{description:"Batched symbol extraction across multiple files. Returns per-file symbol summaries with isolated error handling.",agents:["architect","critic_hallucination_verifier","reviewer","critic_oversight","explorer"]},suggest_patch:{description:"Reviewer-safe structured patch suggestion tool. Produces context-anchored patch artifacts without file modification. Returns structured diagnostics on context mismatch.",agents:["architect","reviewer"]},req_coverage:{description:"query requirement coverage status for tracked functional requirements",agents:["critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","spec_writer","critic","critic_oversight"]},get_approved_plan:{description:"retrieve the last critic-approved immutable plan snapshot for baseline drift comparison",agents:["critic_drift_verifier","critic","critic_oversight"]},repo_map:{description:"query the repo code graph: importers, dependencies, blast radius, localization, ontology facts, package boundaries, and heuristic preflight packets before refactoring; ontology findings are advisory, not formal proofs",agents:["architect","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","critic_architecture_supervisor","reviewer","critic","critic_oversight","explorer","coder"]},get_qa_gate_profile:{description:"retrieve the QA gate profile for the current plan: gates (reviewer, test_engineer, sme_enabled, critic_pre_plan, sast_enabled, council_mode, hallucination_guard, mutation_test, phase_council, drift_check, final_council), lock state, and profile hash. Read-only.",agents:["architect"]},set_qa_gates:{description:"configure the QA gate profile for the current plan. Architect-only. Ratchet-tighter only — rejected once the profile is locked after critic approval. Supports: reviewer, test_engineer, sme_enabled, critic_pre_plan, sast_enabled, council_mode, hallucination_guard, mutation_test, phase_council, drift_check, final_council.",agents:["architect"]},web_search:{description:"External web search (Tavily or Brave) for architect-driven council research, SME domain research, researcher auto-research, and skill-improver research. Returns titled results with snippets, URLs, normalized query metadata, temporal intent, freshness, and removed stale years. Config-gated on council.general.enabled in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides. Requires a search API key. Used by the architect in MODE: COUNCIL to gather a RESEARCH CONTEXT before dispatching council agents, by SME for opt-in external skill/source evaluation, and by the researcher agent for multi-source auto-research.",agents:["sme","researcher","skill_improver"]},web_fetch:{description:"Fetch the readable text of a single http(s) URL (architect-only). Returns decoded page text, document title, final URL after redirects, and an evidence reference. Reads primary sources that web_search only surfaces as snippets. Config-gated on council.general.enabled. Blocks private/loopback/link-local/metadata addresses (re-validated and re-pinned across redirects); enforces timeout and body size cap.",agents:[]},convene_general_council:{description:"Synthesize responses from a multi-model General Council. Accepts parallel member responses (Round 1, optionally Round 2), detects disagreements, and returns consensus points, persisting disagreements, and a structured synthesis. Architect-only. Config-gated on council.general.enabled in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides.",agents:[]},write_final_council_evidence:{description:"Persist project-scoped final council evidence to .swarm/evidence/final-council.json. PREREQUISITE: dispatch critic, reviewer, sme, test_engineer, and explorer as project-scoped Agent tasks and collect their CouncilMemberVerdict JSON — this tool synthesizes only. Rejects on insufficient quorum or CONCERNS with unresolved requiredFixes; normalizes verdicts to approved/concerns/rejected. Architect-only.",agents:[]},skill_generate:{description:"compile knowledge entries into a structured SKILL.md draft",agents:["skill_improver"]},skill_list:{description:"list generated skill files and their status",agents:["skill_improver"]},skill_apply:{description:"activate a draft skill proposal",agents:[]},skill_inspect:{description:"inspect the content and source entries of a skill file",agents:["skill_improver"]},run_stale_reconciliation:{description:"reconcile skills against the knowledge store: mark skills stale when source knowledge is archived or deleted, or clear stale markers",agents:["architect"]},skill_regenerate:{description:"regenerate an active skill by re-clustering its source knowledge entries and updating the SKILL.md in place",agents:[]},skill_retire:{description:"retire a generated skill by adding a retired.marker file; retired skills are excluded from scoring and injection",agents:[]},skill_improve:{description:"run the skill_improver agent to review and refine skills",agents:["skill_improver"]},spec_write:{description:"author or update .swarm/spec.md for the current project",agents:["spec_writer"]},knowledge_receipt:{description:"file a receipt for retrieved knowledge (applied/ignored/contradicted + new lessons), recorded as immutable knowledge events",agents:["architect","sme","docs","docs_design","designer","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","critic_architecture_supervisor","curator_init","curator_phase","skill_improver","spec_writer","reviewer","critic","coder","test_engineer"]},knowledge_archive:{description:"archive (default), quarantine, or purge a swarm or hive knowledge entry by ID with an immutable audit tombstone; purge requires an admin flag",agents:["architect"]},swarm_memory_recall:{description:"recall scoped Swarm memory for the current repository as untrusted background",agents:[]},swarm_memory_propose:{description:"create a pending Swarm memory proposal; does not write durable memory directly",agents:[]},swarm_command:{description:"run supported /swarm commands through the canonical command registry",agents:["architect","sme","researcher","docs","docs_design","designer","reviewer","critic","explorer","coder","test_engineer"]},dispatch_lanes:{description:"dispatch read-only exploration/review lanes concurrently and BLOCK until all finish; prefer dispatch_lanes_async for non-blocking dispatch, use this only when promptAsync is unavailable",agents:["architect"]},dispatch_lanes_async:{description:"launch read-only advisory lanes non-blockingly and return a batch id plus lane session handles immediately so you can keep working; launch_timeout_ms is only a promptAsync acceptance budget, not a lane runtime timeout; poll incrementally with collect_lane_results (wait omitted or false) while doing independent investigation, or join with wait: true when you need all results",agents:["architect"]},collect_lane_results:{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). Non-blocking polls include pending lane identities by default and process settled lanes incrementally while continuing independent work; busy/retry lanes are not timed out just because they run for a long time. Does not advance workflow gates.",agents:["architect"]},summarize_work:{description:"emit a short structured summary of completed work (key decisions, assumptions, risks, constraints) at task completion; rolls up per phase for architecture-supervisor review. Advisory, never blocks.",agents:["architect","sme","researcher","docs","docs_design","designer","explorer","coder","test_engineer"]},write_architecture_supervisor_evidence:{description:"persist the architecture supervisor verdict for a phase (architect MUST dispatch critic_architecture_supervisor first and collect its JSON verdict; this tool persists only, it does not contact the supervisor)",agents:["architect"]},lean_turbo_plan_lanes:{description:"partition phase tasks into parallel lanes based on file-scope conflicts for Lean Turbo execution",agents:[]},lean_turbo_acquire_locks:{description:"acquire file locks for all files in a lane (all-or-nothing) before lane execution",agents:[]},lean_turbo_runner_status:{description:"read Lean Turbo run state from .swarm/turbo-state.json",agents:[]},lean_turbo_review:{description:"dispatch a read-only reviewer agent to evaluate a completed Lean Turbo phase",agents:[]},lean_turbo_run_phase:{description:"Execute a phase using Lean Turbo parallel lane execution. Plans lanes, acquires file locks, and dispatches coder agents concurrently. Use when Lean Turbo is active and you want to execute all tasks in a phase in parallel lanes.",agents:[]},lean_turbo_status:{description:"returns Lean Turbo configuration and active status for the current session",agents:[]},swarm_apply_patch:{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).",agents:["coder","test_engineer"]},external_skill_discover:{description:"Discover external skill candidates from configured sources. Returns a disabled message when external_skills.curation_enabled is false.",agents:[]},external_skill_list:{description:"List external skill candidates in the quarantine store. Returns a disabled message when external_skills.curation_enabled is false.",agents:[]},external_skill_inspect:{description:"Inspect a specific external skill candidate by ID. Returns a disabled message when external_skills.curation_enabled is false.",agents:[]},external_skill_promote:{description:"Promote a validated external skill candidate to an active generated skill. Returns a disabled message when external_skills.curation_enabled is false.",agents:[]},external_skill_reject:{description:"Reject an external skill candidate after evaluation. Returns a disabled message when external_skills.curation_enabled is false.",agents:[]},external_skill_delete:{description:"Delete an external skill candidate from the quarantine store. Returns a disabled message when external_skills.curation_enabled is false.",agents:[]},external_skill_revoke:{description:"Revoke a previously promoted external skill. Returns a disabled message when external_skills.curation_enabled is false.",agents:[]},epic_decide_phase:{description:"Compute the Epic Mode verdict for a phase WITHOUT dispatching coders. Runs preflight + calibration + the three gates (p-threshold, hot-module, greenfield), persists the decision, and returns the verdict so the architect can dispatch waves via the visible Task tool (promote) or fall back to per-task serial (demote). Pair with `epic_plan_waves` to get the wave plan when promoted. Use when /swarm epic is on for the session.",agents:["architect"]},epic_plan_waves:{description:"Partition a phase's pending tasks into ordered concurrent waves for Epic Mode dispatch. A wave is a set of tasks with mutually disjoint declared scopes and all dependencies satisfied by prior waves. Returns `{ waves: [{ waveId, taskIds, files }, ...], serializedTasks, degradedTasks }`. "+'For each wave in order, the architect dispatches one `Task(subagent_type="coder", ...)` per `taskId` — all in one assistant message — so the wave runs concurrently and each coder appears as a visible subagent. '+"Wait for the wave to finish before dispatching the next. Pair with `epic_decide_phase` (called first; this tool is only relevant on a `promote` verdict). "+"Preflight reject reasons: `no-plan`, `no-phase`, `phase-empty`, `phase-already-complete`, `scopes-missing` (call `declare_scope` for `missingScopes`), `git-failed` (transient — retry), `planner-error`.",agents:["architect"]},epic_record_divergence:{description:"After every `update_task_status(completed)`, record the task's declared-vs-actual divergence to .swarm/epic/divergence.jsonl. Feeds Epic Mode's self-calibration loop (Capability D). Best-effort: never blocks.",agents:["architect"]}},TOOL_NAMES=Object.keys(TOOL_METADATA),TOOL_NAME_SET=new Set(TOOL_NAMES),TOOL_DESCRIPTIONS=Object.fromEntries(Object.entries(TOOL_METADATA).map(([name,meta])=>[name,meta.description])),AGENT_TOOL_MAP=(()=>{let map=Object.fromEntries(ALL_AGENT_NAMES.map((agent)=>[agent,[]]));for(let[name,meta]of Object.entries(TOOL_METADATA))for(let agent of meta.agents)map[agent].push(name);return map})()});function deepMergeInternal(base,override,depth){if(depth>=10)throw Error("deepMerge exceeded maximum depth of 10");let result={...base};for(let key of Object.keys(override)){let baseVal=base[key],overrideVal=override[key];if(typeof baseVal==="object"&&baseVal!==null&&typeof overrideVal==="object"&&overrideVal!==null&&!Array.isArray(baseVal)&&!Array.isArray(overrideVal))result[key]=deepMergeInternal(baseVal,overrideVal,depth+1);else result[key]=overrideVal}return result}function deepMerge(base,override){if(!base)return override;if(!override)return base;return deepMergeInternal(base,override,0)}function freezeSet(items){let set=new Set(items),proxy=new Proxy(set,{get(target,prop){if(prop==="add"||prop==="delete"||prop==="clear")return()=>{throw TypeError("CLAUDE_CODE_NATIVE_COMMANDS is readonly")};if(prop==="forEach")return(callback,thisArg)=>{let wrapped=(v,k)=>callback.call(thisArg??void 0,v,k,proxy);return set.forEach(wrapped)};let value=Reflect.get(target,prop);return typeof value==="function"?value.bind(target):value},set(){throw TypeError("CLAUDE_CODE_NATIVE_COMMANDS is readonly")},deleteProperty(){throw TypeError("CLAUDE_CODE_NATIVE_COMMANDS is readonly")},defineProperty(){throw TypeError("CLAUDE_CODE_NATIVE_COMMANDS is readonly")},setPrototypeOf(){throw TypeError("CLAUDE_CODE_NATIVE_COMMANDS is readonly")}});return proxy}function isQAAgent(name){return QA_AGENTS.includes(name)}function isSubagent(name){return ALL_SUBAGENT_NAMES.includes(name)}function isLowCapabilityModel(modelId){let lower=(modelId||"").toLowerCase();return LOW_CAPABILITY_MODELS.some((substr)=>lower.includes(substr))}var OPENCODE_NATIVE_AGENTS,CLAUDE_CODE_NATIVE_COMMANDS,MEMORY_AGENT_TOOL_MAP,EXTERNAL_SKILL_TOOL_NAMES,EXTERNAL_SKILL_AGENT_TOOL_MAP,COUNCIL_TOOL_NAMES,COUNCIL_AGENT_TOOL_MAP,GENERAL_COUNCIL_TOOL_NAMES,GENERAL_COUNCIL_AGENT_TOOL_MAP,TURBO_TOOL_NAMES,TURBO_AGENT_TOOL_MAP,SKILL_TOOL_NAMES,SKILL_AGENT_TOOL_MAP,WRITE_TOOL_NAMES,DEFAULT_MODELS,DEFAULT_SCORING_CONFIG,LOW_CAPABILITY_MODELS,TURBO_MODE_BANNER=`## \uD83D\uDE80 TURBO MODE ACTIVE
1
+ import{createRequire}from"node:module";var __create=Object.create;var{getPrototypeOf:__getProtoOf,defineProperty:__defProp,getOwnPropertyNames:__getOwnPropNames,getOwnPropertyDescriptor:__getOwnPropDesc}=Object,__hasOwnProp=Object.prototype.hasOwnProperty;function __accessProp(key){return this[key]}var __toESMCache_node,__toESMCache_esm,__toESM=(mod,isNodeMode,target)=>{var canCache=mod!=null&&typeof mod==="object";if(canCache){var cache=isNodeMode?__toESMCache_node??=new WeakMap:__toESMCache_esm??=new WeakMap,cached=cache.get(mod);if(cached)return cached}target=mod!=null?__create(__getProtoOf(mod)):{};let to=isNodeMode||!mod||!mod.__esModule?__defProp(target,"default",{value:mod,enumerable:!0}):target;for(let key of __getOwnPropNames(mod))if(!__hasOwnProp.call(to,key))__defProp(to,key,{get:__accessProp.bind(mod,key),enumerable:!0});if(canCache)cache.set(mod,to);return to},__toCommonJS=(from)=>{var entry=(__moduleCache??=new WeakMap).get(from),desc;if(entry)return entry;if(entry=__defProp({},"__esModule",{value:!0}),from&&typeof from==="object"||typeof from==="function"){for(var key of __getOwnPropNames(from))if(!__hasOwnProp.call(entry,key))__defProp(entry,key,{get:__accessProp.bind(from,key),enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable})}return __moduleCache.set(from,entry),entry},__moduleCache,__commonJS=(cb,mod)=>()=>(mod||cb((mod={exports:{}}).exports,mod),mod.exports);var __returnValue=(v)=>v;function __exportSetter(name,newValue){this[name]=__returnValue.bind(null,newValue)}var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0,configurable:!0,set:__exportSetter.bind(all,name)})};var __esm=(fn2,res)=>()=>(fn2&&(res=fn2(fn2=0)),res);var __require=createRequire(import.meta.url);var package_default;var init_package=__esm(()=>{package_default={name:"opencode-swarm",version:"7.114.3",description:"Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",main:"dist/index.js",types:"dist/index.d.ts",exports:{".":{types:"./dist/index.d.ts",default:"./dist/index.js"},"./package.json":"./package.json"},bin:{"opencode-swarm":"./dist/cli/index.js"},type:"module",engines:{bun:">=1.3.13"},license:"MIT",repository:{type:"git",url:"https://github.com/ZaxbyHub/opencode-swarm.git"},publishConfig:{access:"public",registry:"https://registry.npmjs.org/"},keywords:["opencode","opencode-plugin","ai","agents","orchestration","swarm","multi-agent","llm"],files:["dist","dist/lang/grammars","binaries",".opencode/skills/brainstorm",".opencode/skills/specify",".opencode/skills/clarify-spec",".opencode/skills/resume",".opencode/skills/clarify",".opencode/skills/discover",".opencode/skills/consult",".opencode/skills/pre-phase-briefing",".opencode/skills/council",".opencode/skills/deep-dive",".opencode/skills/deep-research",".opencode/skills/codebase-review-swarm",".opencode/skills/swarm-implement",".opencode/skills/design-docs",".opencode/skills/swarm-pr-review",".opencode/skills/swarm",".opencode/skills/swarm-pr-feedback",".opencode/skills/swarm-pr-subscribe",".opencode/skills/swarm-ci-monitor",".opencode/skills/issue-ingest",".opencode/skills/plan",".opencode/skills/critic-gate",".opencode/skills/execute",".opencode/skills/phase-wrap",".opencode/skills/loop",".opencode/skills/writing-tests",".opencode/skills/running-tests",".opencode/skills/engineering-conventions",".opencode/skills/commit-pr",".opencode/skills/ci-failure-batching",".opencode/skills/gate-attribution",".opencode/skills/merge-queue-readiness",".opencode/skills/skill-edit-validation",".opencode/skills/worktree-retry-cleanup",".opencode/skills/test-file-split",".opencode/skills/fork-pr-operations",".opencode/skills/parallel-work-check",".opencode/skills/ci-fix-monitor","tests/fixtures/memory-recall","README.md","LICENSE"],scripts:{clean:`bun -e "require('fs').rmSync('dist',{recursive:true,force:true})"`,build:"bun run clean && bun run scripts/copy-grammars.ts && bun build src/index.ts --outdir dist --target node --format esm --external web-tree-sitter --minify-whitespace --minify-syntax && bun build src/cli/index.ts --outdir dist/cli --target bun --format esm --external bash-parser --splitting && bun run scripts/copy-grammars.ts --to-dist && tsc --emitDeclarationOnly",typecheck:"tsc --noEmit",test:"bun test",lint:"biome lint .","lint:ci":"biome ci .","test:unit:ci":"bun scripts/ci/run-unit-tests-local.ts","drift:check":"bun run scripts/drift-check.ts","drift:fix":"bun run scripts/drift-check.ts --fix --confirm",format:"biome format . --write",check:"biome check --write .",dev:"bun run build && opencode","package:smoke":"node scripts/package-smoke.mjs",prepare:"bun run build","repro:704":"node scripts/repro-704.mjs","repro:1144":"bun scripts/repro-1144.mjs"},dependencies:{"@opencode-ai/plugin":"^1.1.53","@opencode-ai/sdk":"^1.1.53","@vscode/tree-sitter-wasm":"^0.3.0","bash-parser":"^0.5.0","p-limit":"^7.3.0",picomatch:"^4.0.4","proper-lockfile":"^4.1.2","quick-lru":"^7.3.0","web-tree-sitter":"^0.25.0",zod:"^4.1.8"},devDependencies:{"@biomejs/biome":"2.3.14","@types/picomatch":"^4.0.3","bun-types":"1.3.8","js-yaml":"^4.1.1",typescript:"^5.7.3"}}});var QA_AGENTS,PIPELINE_AGENTS,ORCHESTRATOR_NAME="architect",ALL_SUBAGENT_NAMES,ALL_AGENT_NAMES;var init_agent_names=__esm(()=>{QA_AGENTS=["reviewer","critic","critic_oversight"],PIPELINE_AGENTS=["explorer","coder","test_engineer"],ALL_SUBAGENT_NAMES=["sme","researcher","docs","docs_design","designer","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","critic_architecture_supervisor","curator_init","curator_phase","curator_postmortem","curator_consolidation","council_generalist","council_skeptic","council_domain_expert","skill_improver","spec_writer",...QA_AGENTS,...PIPELINE_AGENTS],ALL_AGENT_NAMES=["architect",...ALL_SUBAGENT_NAMES]});var TOOL_METADATA,TOOL_NAMES,TOOL_NAME_SET,TOOL_DESCRIPTIONS,AGENT_TOOL_MAP;var init_tool_metadata=__esm(()=>{init_agent_names();TOOL_METADATA={diff:{description:"structured git diff with contract change detection",agents:["architect","reviewer","critic_oversight","coder","test_engineer"]},diff_summary:{description:"filter classified AST changes by category, risk level, or file for reviewer drill-down",agents:["architect","reviewer","critic_oversight"]},syntax_check:{description:"check syntax of source files using tree-sitter parsers across multiple languages, returning per-file errors",agents:["architect","coder","test_engineer"]},placeholder_scan:{description:"todo and FIXME comment detection",agents:["architect","reviewer"]},imports:{description:"find all consumers that import from a given file — use before refactoring shared modules to avoid breaking unseen dependents",agents:["architect","sme","researcher","docs","docs_design","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","reviewer","critic","coder","test_engineer"]},lint:{description:"run project linter in check or fix mode; supports biome, eslint, ruff, clippy, and more, returns structured results",agents:["architect","reviewer","coder"]},secretscan:{description:"scan for secrets (API keys, tokens, passwords) via regex and entropy; returns redacted previews, excludes common dirs",agents:["architect","reviewer","critic_oversight"]},sast_scan:{description:"static analysis security scan",agents:["architect","reviewer","critic_oversight"]},build_check:{description:"discover and run build, typecheck, and test commands for various project ecosystems in the working directory",agents:["architect","coder","test_engineer"]},pre_check_batch:{description:"parallel verification: lint:check + secretscan + sast_scan + quality_budget",agents:["architect","reviewer"]},quality_budget:{description:"code quality budget check",agents:["architect"]},symbols:{description:"extract exported symbols (functions, classes, interfaces, types) from source files; supports TypeScript, JavaScript, and Python",agents:["architect","sme","researcher","docs","docs_design","designer","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","spec_writer","reviewer","critic","coder","test_engineer"]},complexity_hotspots:{description:"git churn × complexity risk map",agents:["architect","sme","researcher","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","reviewer","critic","critic_oversight","explorer","test_engineer"]},schema_drift:{description:"OpenAPI spec vs route drift",agents:["architect","sme","researcher","docs","explorer"]},todo_extract:{description:"structured TODO/FIXME extraction",agents:["architect","researcher","docs","explorer"]},evidence_check:{description:"verify task evidence completeness",agents:["architect","critic_oversight"]},check_gate_status:{description:"check the gate status of a specific task",agents:["architect","critic_oversight"]},completion_verify:{description:"verify completed tasks have required evidence",agents:["architect","critic_oversight"]},submit_council_verdicts:{description:"submit pre-collected council member verdicts for synthesis (architect MUST dispatch critic/reviewer/sme/test_engineer/explorer as Agent tasks first; this tool synthesizes only, it does not contact members)",agents:[]},submit_phase_council_verdicts:{description:"submit pre-collected phase-level council member verdicts for holistic phase synthesis (architect MUST dispatch all 5 council members with phase-scoped context first; this tool synthesizes only, it does not contact members)",agents:[]},declare_council_criteria:{description:"pre-declare acceptance criteria for a task before the coder starts work; criteria are read back during council evaluation",agents:[]},sbom_generate:{description:"SBOM generation for dependency inventory",agents:["architect"]},checkpoint:{description:"create named git checkpoints for save, restore, and delete — use before risky operations to enable rollback",agents:["architect"]},pkg_audit:{description:"dependency vulnerability scan — npm/pip/cargo",agents:["architect","critic_hallucination_verifier","reviewer","critic_oversight","test_engineer"]},parse_lane_candidates:{description:"Parse [CANDIDATE] rows from a dispatch_lanes or collect_lane_results artifact (by output_ref), produce structured records with provenance, optionally persist to a per-batch sidecar JSONL. Pure-parser variant exists as internal module.",agents:["architect"]},test_runner:{description:"auto-detect and run tests",agents:["architect","reviewer","test_engineer"]},test_impact:{description:"identify test files impacted by changed source files via import analysis",agents:["architect","reviewer","critic_oversight","test_engineer"]},mutation_test:{description:"executes pre-generated mutation patches against tests, evaluates kill rate against quality gate thresholds",agents:["architect","test_engineer"]},generate_mutants:{description:"generate LLM-based mutation testing patches for source files; returns MutationPatch[] for direct consumption by the mutation_test tool",agents:["architect"]},detect_domains:{description:"detect which SME domains are relevant for a given text",agents:["architect","sme","docs","docs_design","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","critic","critic_oversight","explorer"]},git_blame:{description:"per-line git blame metadata: sha, author, date, summary for each line in a file",agents:["reviewer","explorer","architect"]},gitingest:{description:"fetch a GitHub repository full content via gitingest.com",agents:["architect","docs","explorer"]},retrieve_summary:{description:"retrieve the full content of a stored tool output summary",agents:["architect","sme","docs","docs_design","designer","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","critic_architecture_supervisor","spec_writer","reviewer","critic","coder","test_engineer"]},retrieve_lane_output:{description:"retrieve paged full dispatch lane output by output_ref; use before consuming truncated lane previews or routing candidates from lane results",agents:["architect"]},extract_code_blocks:{description:"extract code blocks from text content and save them to files",agents:["docs","docs_design","designer","spec_writer","coder","test_engineer"]},phase_complete:{description:"mark a phase as complete and track dispatched agents",agents:["architect"]},save_plan:{description:"save a structured implementation plan",agents:["architect"]},update_task_status:{description:"mark tasks complete, track phase progress",agents:["architect"]},lint_spec:{description:"validate .swarm/spec.md format and required fields",agents:["architect","spec_writer"]},write_retro:{description:"document phase retrospectives via phase_complete workflow, capture lessons learned",agents:["architect"]},write_drift_evidence:{description:"write drift verification evidence for a completed phase",agents:["architect"]},write_hallucination_evidence:{description:"write hallucination verification evidence for a completed phase",agents:["architect"]},write_mutation_evidence:{description:"write mutation gate evidence for a completed phase; normalizes PASS/WARN/FAIL/SKIP verdicts and writes .swarm/evidence/{phase}/mutation-gate.json",agents:["architect"]},declare_scope:{description:"declare file scope for next coder delegation",agents:["architect"]},knowledge_query:{description:"query swarm or hive knowledge with optional filters",agents:["architect","skill_improver","spec_writer"]},doc_scan:{description:"scan project documentation files and build an index manifest",agents:["architect","docs_design","skill_improver","spec_writer","explorer"]},doc_extract:{description:"extract actionable constraints from project documentation",agents:["architect","docs_design","skill_improver","spec_writer"]},curator_analyze:{description:"run curator phase analysis and optionally apply knowledge recommendations",agents:["architect"]},knowledge_add:{description:"store a new lesson in the knowledge base",agents:["architect","coder"]},knowledge_recall:{description:"search the knowledge base for relevant past decisions",agents:["architect","sme","docs","docs_design","designer","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","critic_architecture_supervisor","curator_init","curator_phase","skill_improver","spec_writer","reviewer","critic","critic_oversight","explorer","coder","test_engineer"]},knowledge_remove:{description:"delete an outdated swarm knowledge entry by ID (swarm tier only)",agents:["architect"]},co_change_analyzer:{description:"detect hidden couplings by analyzing git history",agents:["architect"]},context_status:{description:"report current context-window headroom for the active session — returns tokens-used, model-limit, usage-percent, threshold-state (none/warn/critical), model name, and provider. Pure read-only: no state mutation, no warning injection. Works whether context_budget.enabled is true or false.",agents:["architect"]},search:{description:"Workspace-scoped ripgrep-style text search with structured JSON output. Supports literal and regex modes, glob filtering, and result limits. NOTE: This is text search, not structural AST search — use symbols and imports tools for structural queries.",agents:["architect","sme","docs","docs_design","designer","critic_hallucination_verifier","skill_improver","spec_writer","reviewer","critic_oversight","explorer","coder","test_engineer","researcher"]},ast_grep:{description:"Read-only structural AST search using ast-grep patterns with optional language and glob filters. Use for syntax-aware code pattern searches; does not rewrite files.",agents:["architect","sme","docs","docs_design","critic_hallucination_verifier","spec_writer","explorer","coder","test_engineer","researcher"]},actionlint_scan:{description:"Run actionlint against GitHub Actions workflow YAML files with structured findings. Resolves actionlint lazily and does not modify files.",agents:["architect","test_engineer"]},osv_scan:{description:"Run OSV-Scanner against a workspace path and return structured dependency vulnerability findings. Resolves osv-scanner lazily and does not modify files.",agents:["architect","test_engineer"]},gh_evidence:{description:"Fetch bounded GitHub pull request or issue metadata through gh for review and CI evidence. Resolves gh lazily and is read-only.",agents:["architect","researcher"]},batch_symbols:{description:"Batched symbol extraction across multiple files. Returns per-file symbol summaries with isolated error handling.",agents:["architect","critic_hallucination_verifier","reviewer","critic_oversight","explorer"]},suggest_patch:{description:"Reviewer-safe structured patch suggestion tool. Produces context-anchored patch artifacts without file modification. Returns structured diagnostics on context mismatch.",agents:["architect","reviewer"]},req_coverage:{description:"query requirement coverage status for tracked functional requirements",agents:["critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","spec_writer","critic","critic_oversight"]},get_approved_plan:{description:"retrieve the last critic-approved immutable plan snapshot for baseline drift comparison",agents:["critic_drift_verifier","critic","critic_oversight"]},repo_map:{description:"query the repo code graph: importers, dependencies, blast radius, localization, ontology facts, package boundaries, and heuristic preflight packets before refactoring; ontology findings are advisory, not formal proofs",agents:["architect","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","critic_architecture_supervisor","reviewer","critic","critic_oversight","explorer","coder"]},get_qa_gate_profile:{description:"retrieve the QA gate profile for the current plan: gates (reviewer, test_engineer, sme_enabled, critic_pre_plan, sast_enabled, council_mode, hallucination_guard, mutation_test, phase_council, drift_check, final_council), lock state, and profile hash. Read-only.",agents:["architect"]},set_qa_gates:{description:"configure the QA gate profile for the current plan. Architect-only. Ratchet-tighter only — rejected once the profile is locked after critic approval. Supports: reviewer, test_engineer, sme_enabled, critic_pre_plan, sast_enabled, council_mode, hallucination_guard, mutation_test, phase_council, drift_check, final_council.",agents:["architect"]},web_search:{description:"External web search (Tavily or Brave) for architect-driven council research, SME domain research, researcher auto-research, and skill-improver research. Returns titled results with snippets, URLs, normalized query metadata, temporal intent, freshness, and removed stale years. Config-gated on council.general.enabled in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides. Requires a search API key. Used by the architect in MODE: COUNCIL to gather a RESEARCH CONTEXT before dispatching council agents, by SME for opt-in external skill/source evaluation, and by the researcher agent for multi-source auto-research.",agents:["sme","researcher","skill_improver"]},web_fetch:{description:"Fetch the readable text of a single http(s) URL (architect-only). Returns decoded page text, document title, final URL after redirects, and an evidence reference. Reads primary sources that web_search only surfaces as snippets. Config-gated on council.general.enabled. Blocks private/loopback/link-local/metadata addresses (re-validated and re-pinned across redirects); enforces timeout and body size cap.",agents:[]},convene_general_council:{description:"Synthesize responses from a multi-model General Council. Accepts parallel member responses (Round 1, optionally Round 2), detects disagreements, and returns consensus points, persisting disagreements, and a structured synthesis. Architect-only. Config-gated on council.general.enabled in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides.",agents:[]},write_final_council_evidence:{description:"Persist project-scoped final council evidence to .swarm/evidence/final-council.json. PREREQUISITE: dispatch critic, reviewer, sme, test_engineer, and explorer as project-scoped Agent tasks and collect their CouncilMemberVerdict JSON — this tool synthesizes only. Rejects on insufficient quorum or CONCERNS with unresolved requiredFixes; normalizes verdicts to approved/concerns/rejected. Architect-only.",agents:[]},skill_generate:{description:"compile knowledge entries into a structured SKILL.md draft",agents:["skill_improver"]},skill_list:{description:"list generated skill files and their status",agents:["skill_improver"]},skill_apply:{description:"activate a draft skill proposal",agents:[]},skill_inspect:{description:"inspect the content and source entries of a skill file",agents:["skill_improver"]},run_stale_reconciliation:{description:"reconcile skills against the knowledge store: mark skills stale when source knowledge is archived or deleted, or clear stale markers",agents:["architect"]},skill_regenerate:{description:"regenerate an active skill by re-clustering its source knowledge entries and updating the SKILL.md in place",agents:[]},skill_retire:{description:"retire a generated skill by adding a retired.marker file; retired skills are excluded from scoring and injection",agents:[]},skill_improve:{description:"run the skill_improver agent to review and refine skills",agents:["skill_improver"]},spec_write:{description:"author or update .swarm/spec.md for the current project",agents:["spec_writer"]},knowledge_receipt:{description:"file a receipt for retrieved knowledge (applied/ignored/contradicted + new lessons), recorded as immutable knowledge events",agents:["architect","sme","docs","docs_design","designer","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","critic_architecture_supervisor","curator_init","curator_phase","skill_improver","spec_writer","reviewer","critic","coder","test_engineer"]},knowledge_archive:{description:"archive (default), quarantine, or purge a swarm or hive knowledge entry by ID with an immutable audit tombstone; purge requires an admin flag",agents:["architect"]},swarm_memory_recall:{description:"recall scoped Swarm memory for the current repository as untrusted background",agents:[]},swarm_memory_propose:{description:"create a pending Swarm memory proposal; does not write durable memory directly",agents:[]},swarm_command:{description:"run supported /swarm commands through the canonical command registry",agents:["architect","sme","researcher","docs","docs_design","designer","reviewer","critic","explorer","coder","test_engineer"]},dispatch_lanes:{description:"dispatch read-only exploration/review lanes concurrently and BLOCK until all finish; prefer dispatch_lanes_async for non-blocking dispatch, use this only when promptAsync is unavailable",agents:["architect"]},dispatch_lanes_async:{description:"launch read-only advisory lanes non-blockingly and return a batch id plus lane session handles immediately so you can keep working; launch_timeout_ms is only a promptAsync acceptance budget, not a lane runtime timeout; poll incrementally with collect_lane_results (wait omitted or false) while doing independent investigation, or join with wait: true when you need all results",agents:["architect"]},collect_lane_results:{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). Non-blocking polls include pending lane identities by default and process settled lanes incrementally while continuing independent work; busy/retry lanes are not timed out just because they run for a long time. Does not advance workflow gates.",agents:["architect"]},summarize_work:{description:"emit a short structured summary of completed work (key decisions, assumptions, risks, constraints) at task completion; rolls up per phase for architecture-supervisor review. Advisory, never blocks.",agents:["architect","sme","researcher","docs","docs_design","designer","explorer","coder","test_engineer"]},write_architecture_supervisor_evidence:{description:"persist the architecture supervisor verdict for a phase (architect MUST dispatch critic_architecture_supervisor first and collect its JSON verdict; this tool persists only, it does not contact the supervisor)",agents:["architect"]},lean_turbo_plan_lanes:{description:"partition phase tasks into parallel lanes based on file-scope conflicts for Lean Turbo execution",agents:[]},lean_turbo_acquire_locks:{description:"acquire file locks for all files in a lane (all-or-nothing) before lane execution",agents:[]},lean_turbo_runner_status:{description:"read Lean Turbo run state from .swarm/turbo-state.json",agents:[]},lean_turbo_review:{description:"dispatch a read-only reviewer agent to evaluate a completed Lean Turbo phase",agents:[]},lean_turbo_run_phase:{description:"Execute a phase using Lean Turbo parallel lane execution. Plans lanes, acquires file locks, and dispatches coder agents concurrently. Use when Lean Turbo is active and you want to execute all tasks in a phase in parallel lanes.",agents:[]},lean_turbo_status:{description:"returns Lean Turbo configuration and active status for the current session",agents:[]},swarm_apply_patch:{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).",agents:["coder","test_engineer"]},external_skill_discover:{description:"Discover external skill candidates from configured sources. Returns a disabled message when external_skills.curation_enabled is false.",agents:[]},external_skill_list:{description:"List external skill candidates in the quarantine store. Returns a disabled message when external_skills.curation_enabled is false.",agents:[]},external_skill_inspect:{description:"Inspect a specific external skill candidate by ID. Returns a disabled message when external_skills.curation_enabled is false.",agents:[]},external_skill_promote:{description:"Promote a validated external skill candidate to an active generated skill. Returns a disabled message when external_skills.curation_enabled is false.",agents:[]},external_skill_reject:{description:"Reject an external skill candidate after evaluation. Returns a disabled message when external_skills.curation_enabled is false.",agents:[]},external_skill_delete:{description:"Delete an external skill candidate from the quarantine store. Returns a disabled message when external_skills.curation_enabled is false.",agents:[]},external_skill_revoke:{description:"Revoke a previously promoted external skill. Returns a disabled message when external_skills.curation_enabled is false.",agents:[]},epic_decide_phase:{description:"Compute the Epic Mode verdict for a phase WITHOUT dispatching coders. Runs preflight + calibration + the three gates (p-threshold, hot-module, greenfield), persists the decision, and returns the verdict so the architect can dispatch waves via the visible Task tool (promote) or fall back to per-task serial (demote). Pair with `epic_plan_waves` to get the wave plan when promoted. Use when /swarm epic is on for the session.",agents:["architect"]},epic_plan_waves:{description:"Partition a phase's pending tasks into ordered concurrent waves for Epic Mode dispatch. A wave is a set of tasks with mutually disjoint declared scopes and all dependencies satisfied by prior waves. Returns `{ waves: [{ waveId, taskIds, files }, ...], serializedTasks, degradedTasks }`. "+'For each wave in order, the architect dispatches one `Task(subagent_type="coder", ...)` per `taskId` — all in one assistant message — so the wave runs concurrently and each coder appears as a visible subagent. '+"Wait for the wave to finish before dispatching the next. Pair with `epic_decide_phase` (called first; this tool is only relevant on a `promote` verdict). "+"Preflight reject reasons: `no-plan`, `no-phase`, `phase-empty`, `phase-already-complete`, `scopes-missing` (call `declare_scope` for `missingScopes`), `git-failed` (transient — retry), `planner-error`.",agents:["architect"]},epic_record_divergence:{description:"After every `update_task_status(completed)`, record the task's declared-vs-actual divergence to .swarm/epic/divergence.jsonl. Feeds Epic Mode's self-calibration loop (Capability D). Best-effort: never blocks.",agents:["architect"]}},TOOL_NAMES=Object.keys(TOOL_METADATA),TOOL_NAME_SET=new Set(TOOL_NAMES),TOOL_DESCRIPTIONS=Object.fromEntries(Object.entries(TOOL_METADATA).map(([name,meta])=>[name,meta.description])),AGENT_TOOL_MAP=(()=>{let map=Object.fromEntries(ALL_AGENT_NAMES.map((agent)=>[agent,[]]));for(let[name,meta]of Object.entries(TOOL_METADATA))for(let agent of meta.agents)map[agent].push(name);return map})()});function deepMergeInternal(base,override,depth){if(depth>=10)throw Error("deepMerge exceeded maximum depth of 10");let result={...base};for(let key of Object.keys(override)){let baseVal=base[key],overrideVal=override[key];if(typeof baseVal==="object"&&baseVal!==null&&typeof overrideVal==="object"&&overrideVal!==null&&!Array.isArray(baseVal)&&!Array.isArray(overrideVal))result[key]=deepMergeInternal(baseVal,overrideVal,depth+1);else result[key]=overrideVal}return result}function deepMerge(base,override){if(!base)return override;if(!override)return base;return deepMergeInternal(base,override,0)}function freezeSet(items){let set=new Set(items),proxy=new Proxy(set,{get(target,prop){if(prop==="add"||prop==="delete"||prop==="clear")return()=>{throw TypeError("CLAUDE_CODE_NATIVE_COMMANDS is readonly")};if(prop==="forEach")return(callback,thisArg)=>{let wrapped=(v,k)=>callback.call(thisArg??void 0,v,k,proxy);return set.forEach(wrapped)};let value=Reflect.get(target,prop);return typeof value==="function"?value.bind(target):value},set(){throw TypeError("CLAUDE_CODE_NATIVE_COMMANDS is readonly")},deleteProperty(){throw TypeError("CLAUDE_CODE_NATIVE_COMMANDS is readonly")},defineProperty(){throw TypeError("CLAUDE_CODE_NATIVE_COMMANDS is readonly")},setPrototypeOf(){throw TypeError("CLAUDE_CODE_NATIVE_COMMANDS is readonly")}});return proxy}function isQAAgent(name){return QA_AGENTS.includes(name)}function isSubagent(name){return ALL_SUBAGENT_NAMES.includes(name)}function isLowCapabilityModel(modelId){let lower=(modelId||"").toLowerCase();return LOW_CAPABILITY_MODELS.some((substr)=>lower.includes(substr))}var OPENCODE_NATIVE_AGENTS,CLAUDE_CODE_NATIVE_COMMANDS,MEMORY_AGENT_TOOL_MAP,EXTERNAL_SKILL_TOOL_NAMES,EXTERNAL_SKILL_AGENT_TOOL_MAP,COUNCIL_TOOL_NAMES,COUNCIL_AGENT_TOOL_MAP,GENERAL_COUNCIL_TOOL_NAMES,GENERAL_COUNCIL_AGENT_TOOL_MAP,TURBO_TOOL_NAMES,TURBO_AGENT_TOOL_MAP,SKILL_TOOL_NAMES,SKILL_AGENT_TOOL_MAP,WRITE_TOOL_NAMES,DEFAULT_MODELS,DEFAULT_SCORING_CONFIG,LOW_CAPABILITY_MODELS,TURBO_MODE_BANNER=`## \uD83D\uDE80 TURBO MODE ACTIVE
2
2
 
3
3
  **Speed optimization enabled for this session.**
4
4
 
@@ -1319,7 +1319,7 @@ ${inv.staleActiveSkills.slice(0,10).map((s)=>`- ${s.slug} | ${s.reasons.join(",
1319
1319
  `)}function buildLLMProposalFrame(args2){let lines=[];if(lines.push("---"),lines.push("source: llm"),lines.push(`generated_at: ${args2.now.toISOString()}`),lines.push(`targets: [${args2.targets.join(", ")}]`),args2.model)lines.push(`model: ${args2.model}`);return lines.push("---"),lines.push(""),lines.push(args2.body.trim()),lines.push(""),lines.join(`
1320
1320
  `)}async function reconcileStaleActiveSkills(directory,options={}){let result={regenerated:[],retired:[],skipped:[],checked:0},skills;try{skills=await listSkills(directory)}catch{return result}for(let skill of skills.active){let content;try{content=await readFile19(skill.path,"utf-8")}catch{continue}let fm=parseDraftFrontmatter(content);if(fm?.skillOrigin==="shim"){result.skipped.push(skill.slug);continue}if(!(!fm||fm.sourceKnowledgeIds.length===0||!fm.generatedAt))continue;if(result.checked+=1,options.dryRun){result.retired.push(skill.slug);continue}try{let regen=await _internals43.regenerateSkill(directory,skill.slug,{evaluate:!1});if(regen.regenerated)result.regenerated.push(skill.slug);else if(regen.retired)result.retired.push(skill.slug);else if((await retireSkill(directory,skill.slug,"stale_no_source_knowledge")).retired)result.retired.push(skill.slug)}catch(err){warn(`[skill-improver] reconcileStaleActiveSkills: failed to reconcile '${skill.slug}': ${err instanceof Error?err.message:String(err)}`),result.skipped.push(skill.slug)}}return result}async function runSkillImprover(req){let cfg=req.config,now=req.now??new Date,targets=req.targets&&req.targets.length>0?req.targets:cfg.targets,writeMode=req.mode??cfg.write_mode,maxCalls=Math.max(1,Math.min(cfg.max_calls_per_day,req.maxCalls??1)),noQuota={date:now.toISOString().slice(0,10),calls_used:0,max_calls:cfg.max_calls_per_day};if(!cfg.enabled)return{ran:!1,reason:"skill_improver.enabled is false",quota:noQuota};if(req.signal?.aborted)return{ran:!1,reason:"skill_improver aborted",quota:noQuota};let delegate=req.delegate??createSkillImproverLLMDelegate(req.directory,req.sessionId);if(!delegate&&!cfg.allow_deterministic_fallback)return{ran:!1,reason:"no_llm_client: skill_improver.allow_deterministic_fallback is false and no OpenCode client is wired. Run from a session where swarmState.opencodeClient is available, or enable allow_deterministic_fallback to use the offline path.",quota:noQuota};let reservation=await reserveQuota(req.directory,{nCalls:maxCalls,maxCalls:cfg.max_calls_per_day,window:cfg.quota_window,now});if(!reservation.allowed)return{ran:!1,reason:reservation.reason??"quota exhausted",quota:{date:reservation.state.date,calls_used:reservation.state.calls_used,max_calls:reservation.state.max_calls}};let networkStarted=!1,sideEffectsStarted=!1,reservationQuota={date:reservation.state.date,calls_used:reservation.state.calls_used,max_calls:reservation.state.max_calls},releaseReservedQuota=async()=>{let released=await releaseQuota(req.directory,{nCalls:maxCalls,maxCalls:cfg.max_calls_per_day,window:cfg.quota_window,now}).catch(()=>({...reservation.state,calls_used:Math.max(0,reservation.state.calls_used-maxCalls)}));return{date:released.date,calls_used:released.calls_used,max_calls:released.max_calls}},abortResult=async()=>({ran:!1,reason:"skill_improver aborted",quota:networkStarted||sideEffectsStarted?reservationQuota:await releaseReservedQuota()}),inventory;try{throwIfAborted2(req.signal),inventory=await gatherInventory(req.directory),throwIfAborted2(req.signal)}catch(err){if(isAbortError2(err))return await abortResult();return await releaseQuota(req.directory,{nCalls:maxCalls,maxCalls:cfg.max_calls_per_day,window:cfg.quota_window,now}).catch(()=>{}),{ran:!1,reason:`inventory_failed: ${err instanceof Error?err.message:String(err)}`,quota:{date:reservation.state.date,calls_used:reservation.state.calls_used-maxCalls,max_calls:reservation.state.max_calls}}}let body,source;if(delegate)try{if(throwIfAborted2(req.signal),networkStarted=!0,body=await delegate(buildSystemPrompt(targets,{...cfg,write_mode:writeMode}),buildUserPrompt(inventory),req.signal),throwIfAborted2(req.signal),!body||body.trim().length===0)throw Error("empty LLM response");source="llm"}catch(err){if(isAbortError2(err))return await abortResult();return{ran:!1,reason:`llm_call_failed: ${err instanceof Error?err.message:String(err)}`,quota:{date:reservation.state.date,calls_used:reservation.state.calls_used,max_calls:reservation.state.max_calls}}}else{try{throwIfAborted2(req.signal)}catch(err){if(isAbortError2(err))return await abortResult();throw err}body="",source="deterministic_fallback"}let draftSkillsWritten;if(writeMode==="draft_skills"&&inventory.matureCandidates.length>0){try{throwIfAborted2(req.signal)}catch(err){if(isAbortError2(err))return await abortResult();throw err}sideEffectsStarted=!0,draftSkillsWritten=(await generateSkills({directory:req.directory,mode:"draft",minConfidence:DEFAULT_SKILL_MIN_CONFIDENCE,minConfirmations:DEFAULT_SKILL_MIN_CONFIRMATIONS,evaluate:req.evaluateDrafts??!1})).written.map((w)=>({slug:w.slug,path:w.path,sourceKnowledgeIds:w.sourceKnowledgeIds}))}try{throwIfAborted2(req.signal)}catch(err){if(isAbortError2(err))return await abortResult();throw err}let proposalDir=path74.join(req.directory,".swarm","skill-improver","proposals"),proposalFile=path74.join(proposalDir,`${timestampSlug(now)}.md`),finalBody=source==="llm"?buildLLMProposalFrame({body,targets,model:cfg.model,now}):buildDeterministicProposal({targets,inventory,model:cfg.model,now});sideEffectsStarted=!0,await atomicWrite4(proposalFile,finalBody);let unactionableHardening;if(delegate)unactionableHardening=await hardenUnactionableEntries({directory:req.directory,llmDelegate:delegate,quota:req.enrichmentQuota});let motifResult=await writeMotifProposals(req.directory),macroMotifs={motifs:motifResult.motifs,proposalsWritten:motifResult.proposalsWritten.length},successMotifResult=await writeSuccessMotifProposals(req.directory),successMotifs={motifs:successMotifResult.motifs,proposalsWritten:successMotifResult.proposalsWritten.length},staleSkillReconciliation=await reconcileStaleActiveSkills(req.directory,{dryRun:writeMode!=="draft_skills"}),autoApply;if(req.allowAutoApply!==!1&&delegate&&req.sessionId&&hasActiveFullAuto(req.sessionId))try{autoApply=await autoApplyProposals(req.directory,delegate)}catch{}return{ran:!0,proposalPath:proposalFile,source,quota:{date:reservation.state.date,calls_used:reservation.state.calls_used,max_calls:reservation.state.max_calls},draftSkillsWritten,model:cfg.model??void 0,unactionableHardening,macroMotifs,successMotifs,staleSkillReconciliation,autoApply}}var _internals43;var init_skill_improver=__esm(()=>{init_knowledge_store();init_skill_improver_llm_factory();init_state2();init_logger();init_skill_generator();init_skill_improver_quota();init_trajectory_cluster();init_unactionable_hardening();_internals43={runSkillImprover,buildDeterministicProposal,buildLLMProposalFrame,buildSystemPrompt,buildUserPrompt,gatherInventory,reconcileStaleActiveSkills,regenerateSkill}});import{existsSync as existsSync39}from"node:fs";import path75 from"node:path";async function executeWriteRetro(args2,directory){if(/^(CON|PRN|AUX|NUL|COM[0-9]|LPT[0-9])(:|$)/i.test(directory))return JSON.stringify({success:!1,message:"Invalid directory: reserved device name"},null,2);if(!existsSync39(path75.join(directory,".swarm")))return JSON.stringify({success:!1,message:`Cannot write evidence in "${directory}" — no .swarm/ folder was found. Run write_retro from an initialized project root.`},null,2);let phase=args2.phase;if(!Number.isInteger(phase)||phase<1)return JSON.stringify({success:!1,phase,message:"Invalid phase: must be a positive integer"},null,2);if(!["trivial","simple","moderate","complex"].includes(args2.task_complexity))return JSON.stringify({success:!1,phase,message:"Invalid task_complexity: must be one of 'trivial'|'simple'|'moderate'|'complex'"},null,2);if(!Number.isInteger(args2.task_count)||args2.task_count<1)return JSON.stringify({success:!1,phase,message:"Invalid task_count: must be a positive integer >= 1"},null,2);if(!Number.isInteger(args2.total_tool_calls)||args2.total_tool_calls<0)return JSON.stringify({success:!1,phase,message:"Invalid total_tool_calls: must be a non-negative integer"},null,2);if(!Number.isInteger(args2.coder_revisions)||args2.coder_revisions<0)return JSON.stringify({success:!1,phase,message:"Invalid coder_revisions: must be a non-negative integer"},null,2);if(!Number.isInteger(args2.reviewer_rejections)||args2.reviewer_rejections<0)return JSON.stringify({success:!1,phase,message:"Invalid reviewer_rejections: must be a non-negative integer"},null,2);if(!Number.isInteger(args2.test_failures)||args2.test_failures<0)return JSON.stringify({success:!1,phase,message:"Invalid test_failures: must be a non-negative integer"},null,2);if(!Number.isInteger(args2.security_findings)||args2.security_findings<0)return JSON.stringify({success:!1,phase,message:"Invalid security_findings: must be a non-negative integer"},null,2);if(!Number.isInteger(args2.integration_issues)||args2.integration_issues<0)return JSON.stringify({success:!1,phase,message:"Invalid integration_issues: must be a non-negative integer"},null,2);if(args2.loop_detections!==void 0&&(!Number.isInteger(args2.loop_detections)||args2.loop_detections<0))return JSON.stringify({success:!1,phase,message:"Invalid loop_detections: must be a non-negative integer"},null,2);if(args2.circuit_breaker_trips!==void 0&&(!Number.isInteger(args2.circuit_breaker_trips)||args2.circuit_breaker_trips<0))return JSON.stringify({success:!1,phase,message:"Invalid circuit_breaker_trips: must be a non-negative integer"},null,2);if(args2.phase>99)return JSON.stringify({success:!1,phase,message:"Invalid phase: must be <= 99"},null,2);if(args2.task_count>9999)return JSON.stringify({success:!1,phase,message:"Invalid task_count: must be <= 9999"},null,2);if(args2.total_tool_calls>9999)return JSON.stringify({success:!1,phase,message:"Invalid total_tool_calls: must be <= 9999"},null,2);if(args2.coder_revisions>999)return JSON.stringify({success:!1,phase,message:"Invalid coder_revisions: must be <= 999"},null,2);if(args2.reviewer_rejections>999)return JSON.stringify({success:!1,phase,message:"Invalid reviewer_rejections: must be <= 999"},null,2);if(args2.loop_detections!==void 0&&args2.loop_detections>9999)return JSON.stringify({success:!1,phase,message:"Invalid loop_detections: must be <= 9999"},null,2);if(args2.circuit_breaker_trips!==void 0&&args2.circuit_breaker_trips>9999)return JSON.stringify({success:!1,phase,message:"Invalid circuit_breaker_trips: must be <= 9999"},null,2);if(args2.test_failures>9999)return JSON.stringify({success:!1,phase,message:"Invalid test_failures: must be <= 9999"},null,2);if(args2.security_findings>999)return JSON.stringify({success:!1,phase,message:"Invalid security_findings: must be <= 999"},null,2);if(args2.integration_issues>999)return JSON.stringify({success:!1,phase,message:"Invalid integration_issues: must be <= 999"},null,2);let summary=args2.summary;if(typeof summary!=="string"||summary.trim().length===0)return JSON.stringify({success:!1,phase,message:"Invalid summary: must be a non-empty string"},null,2);if(args2.task_id!==void 0){let tid=args2.task_id;if(!tid||tid.length===0||tid.length>200)return JSON.stringify({success:!1,phase,message:"Invalid task ID: must match pattern"},null,2);if(/\0/.test(tid))return JSON.stringify({success:!1,phase,message:"Invalid task ID: contains null bytes"},null,2);for(let i=0;i<tid.length;i++)if(tid.charCodeAt(i)<32)return JSON.stringify({success:!1,phase,message:"Invalid task ID: contains control characters"},null,2);if(tid.includes("..")||tid.includes("/")||tid.includes("\\"))return JSON.stringify({success:!1,phase,message:"Invalid task ID: path traversal detected"},null,2);if(!/^(retro-[a-zA-Z0-9][a-zA-Z0-9_-]*|\d+\.\d+(\.\d+)*)$/.test(tid))return JSON.stringify({success:!1,phase,message:"Invalid task ID: must match pattern"},null,2)}let taskId=args2.task_id??`retro-${phase}`,retroEntry={task_id:taskId,type:"retrospective",timestamp:new Date().toISOString(),agent:"architect",verdict:"pass",summary,metadata:args2.metadata,phase_number:phase,total_tool_calls:args2.total_tool_calls,coder_revisions:args2.coder_revisions,reviewer_rejections:args2.reviewer_rejections,loop_detections:args2.loop_detections,circuit_breaker_trips:args2.circuit_breaker_trips,test_failures:args2.test_failures,security_findings:args2.security_findings,integration_issues:args2.integration_issues,task_count:args2.task_count,task_complexity:args2.task_complexity,top_rejection_reasons:args2.top_rejection_reasons??[],lessons_learned:(args2.lessons_learned??[]).slice(0,5),user_directives:[],approaches_tried:[],error_taxonomy:[]},taxonomy=[];try{let phaseTaskIds=(await listEvidenceTaskIds(directory)).filter((id)=>id.startsWith(`${phase}.`)),sessionStart=args2.metadata&&typeof args2.metadata.session_start==="string"?args2.metadata.session_start:void 0;for(let phaseTaskId of phaseTaskIds){let result=await loadEvidence(directory,phaseTaskId);if(result.status!=="found")continue;let bundle=result.bundle;if(sessionStart&&bundle.updated_at<sessionStart)continue;for(let entry of bundle.entries){let e=entry;if(e.type==="review"&&e.verdict==="fail"){let reasonParts=[];if(typeof e.summary==="string")reasonParts.push(e.summary);if(Array.isArray(e.issues)){for(let iss of e.issues)if(typeof iss.message==="string")reasonParts.push(iss.message)}let reason=reasonParts.join(" ");if(/signature|type|contract|interface/i.test(reason))taxonomy.push("interface_mismatch");else taxonomy.push("logic_error")}else if(e.type==="test"&&e.verdict==="fail")taxonomy.push("logic_error");else if(e.agent==="scope_guard"&&e.verdict==="fail")taxonomy.push("scope_creep");else if(e.agent==="loop_detector"&&e.verdict==="fail")taxonomy.push("gate_evasion")}}}catch{}retroEntry.error_taxonomy=[...new Set(taxonomy)];let validationResult=RetrospectiveEvidenceSchema.safeParse(retroEntry);if(!validationResult.success)return JSON.stringify({success:!1,error:`Retrospective entry failed validation: ${validationResult.error.message}`},null,2);try{return await saveEvidence(directory,taskId,retroEntry),JSON.stringify({success:!0,task_id:taskId,phase,message:`Retrospective evidence written to .swarm/evidence/${taskId}/evidence.json`},null,2)}catch(error93){return JSON.stringify({success:!1,phase,message:error93 instanceof Error?error93.message:String(error93)},null,2)}}var write_retro,_internals44;var init_write_retro=__esm(()=>{init_zod();init_evidence_schema();init_manager2();init_create_tool();write_retro=createSwarmTool({description:"Write a retrospective evidence bundle for a completed phase. Accepts flat retro fields and writes a correctly-wrapped EvidenceBundle to .swarm/evidence/retro-{phase}/evidence.json. Use this instead of manually writing retro JSON to avoid schema validation failures in phase_complete.",args:{phase:exports_external.number().int().min(1).max(99).describe("The phase number being completed (e.g., 1, 2, 3)"),summary:exports_external.string().describe("Human-readable summary of the phase"),task_count:exports_external.number().int().min(1).max(9999).describe("Count of tasks completed in this phase"),task_complexity:exports_external.enum(["trivial","simple","moderate","complex"]).describe("Complexity level of the completed tasks"),total_tool_calls:exports_external.number().int().min(0).max(9999).describe("Total number of tool calls in this phase"),coder_revisions:exports_external.number().int().min(0).max(999).describe("Number of coder revisions made"),reviewer_rejections:exports_external.number().int().min(0).max(999).describe("Number of reviewer rejections received"),loop_detections:exports_external.number().int().min(0).max(9999).optional().describe("Number of loop detection events in this phase"),circuit_breaker_trips:exports_external.number().int().min(0).max(9999).optional().describe("Number of circuit breaker trips in this phase"),test_failures:exports_external.number().int().min(0).max(9999).describe("Number of test failures encountered"),security_findings:exports_external.number().int().min(0).max(999).describe("Number of security findings"),integration_issues:exports_external.number().int().min(0).max(999).describe("Number of integration issues"),lessons_learned:exports_external.array(exports_external.string()).max(5).optional().describe("Key lessons learned from this phase (max 5)"),top_rejection_reasons:exports_external.array(exports_external.string()).optional().describe("Top reasons for reviewer rejections"),task_id:exports_external.string().optional().describe("Optional custom task ID (defaults to retro-{phase})"),metadata:exports_external.record(exports_external.string(),exports_external.unknown()).optional().describe("Optional additional metadata")},execute:async(args2,directory)=>{let rawPhase=args2.phase!==void 0?Number(args2.phase):0;try{let writeRetroArgs={phase:Number(args2.phase),summary:String(args2.summary??""),task_count:Number(args2.task_count),task_complexity:args2.task_complexity,total_tool_calls:Number(args2.total_tool_calls),coder_revisions:Number(args2.coder_revisions),reviewer_rejections:Number(args2.reviewer_rejections),loop_detections:args2.loop_detections!=null?Number(args2.loop_detections):void 0,circuit_breaker_trips:args2.circuit_breaker_trips!=null?Number(args2.circuit_breaker_trips):void 0,test_failures:Number(args2.test_failures),security_findings:Number(args2.security_findings),integration_issues:Number(args2.integration_issues),lessons_learned:Array.isArray(args2.lessons_learned)?args2.lessons_learned.map(String):void 0,top_rejection_reasons:Array.isArray(args2.top_rejection_reasons)?args2.top_rejection_reasons.map(String):void 0,task_id:args2.task_id!==void 0?String(args2.task_id):void 0,metadata:args2.metadata};return await _internals44.executeWriteRetro(writeRetroArgs,directory)}catch{return JSON.stringify({success:!1,phase:rawPhase,message:"Invalid arguments"},null,2)}}}),_internals44={executeWriteRetro,write_retro}});import*as child_process4 from"node:child_process";import*as fsSync8 from"node:fs";import{promises as fs34}from"node:fs";import path76 from"node:path";async function runAbortableReflection(input,timeoutMs){let controller=new AbortController,timeout,reflectionPromise=runSessionReflection({...input,signal:controller.signal}),timeoutPromise=new Promise((_,reject)=>{timeout=setTimeout(()=>{reject(Error(`session_reflection exceeded ${timeoutMs}ms budget`)),controller.abort()},timeoutMs)});try{return await Promise.race([reflectionPromise,timeoutPromise])}finally{if(timeout)clearTimeout(timeout)}}async function runAbortableSkillReview(req,timeoutMs){let controller=new AbortController,timeout,skillReviewPromise=runSkillImprover({...req,signal:controller.signal}),timeoutPromise=new Promise((_,reject)=>{timeout=setTimeout(()=>{reject(Error(`skill_review exceeded ${timeoutMs}ms budget`)),controller.abort()},timeoutMs)});try{return await Promise.race([skillReviewPromise,timeoutPromise])}finally{if(timeout)clearTimeout(timeout)}}function normalizeLessonText(text){return(text??"").trim().toLowerCase()}function countSessionKnowledgeEntries(entries,sessionStart,fallbackCount){if(!sessionStart)return fallbackCount;let sessionStartMs=Date.parse(sessionStart);if(!Number.isFinite(sessionStartMs))return fallbackCount;return entries.filter((entry)=>{if(typeof entry.created_at!=="string")return!1;let createdAtMs=Date.parse(entry.created_at);return Number.isFinite(createdAtMs)&&createdAtMs>=sessionStartMs}).length}async function copyDirRecursiveWithFailures(src,dest){let count=0,failures=[],entries=await fs34.readdir(src);await fs34.mkdir(dest,{recursive:!0});for(let entry of entries){let srcEntry=path76.join(src,entry),destEntry=path76.join(dest,entry);try{if((await fs34.stat(srcEntry)).isDirectory()){let subResult=await copyDirRecursiveWithFailures(srcEntry,destEntry);count+=subResult.copied,failures.push(...subResult.failures)}else try{await fs34.copyFile(srcEntry,destEntry),count++}catch(err){if(err?.code!=="ENOENT")failures.push(`${srcEntry}: ${err instanceof Error?err.message:String(err)}`)}}catch(err){if(err?.code!=="ENOENT")failures.push(`${srcEntry}: ${err instanceof Error?err.message:String(err)}`)}}return{copied:count,failures}}async function copyDirRecursive(src,dest){return(await copyDirRecursiveWithFailures(src,dest)).copied}function guaranteeAllPlansComplete(planData){let closedPhaseIds=[],closedTaskIds=[];for(let phase of planData.phases??[]){if(!(phase.status==="complete"||phase.status==="completed"||phase.status==="closed"))phase.status="closed",closedPhaseIds.push(phase.id);for(let task of phase.tasks??[])if(!(task.status==="completed"||task.status==="complete"||task.status==="closed"))task.status="closed",task.close_reason="session_terminated",closedTaskIds.push(task.id)}return{closedPhaseIds,closedTaskIds}}async function runFinalizeStage(ctx){if(!ctx.planAlreadyDone)for(let phase of ctx.inProgressPhases){ctx.closedPhases.push(phase.id);let retroResult;try{retroResult=await executeWriteRetro({phase:phase.id,summary:ctx.isForced?"Phase force-closed via /swarm close --force":"Phase closed via /swarm close",task_count:Math.max(1,(phase.tasks??[]).length),task_complexity:"simple",total_tool_calls:0,coder_revisions:0,reviewer_rejections:0,test_failures:0,security_findings:0,integration_issues:0},ctx.directory)}catch(retroError){ctx.warnings.push(`Retrospective write threw for phase ${phase.id}: ${retroError instanceof Error?retroError.message:String(retroError)}`)}if(retroResult!==void 0)try{if(JSON.parse(retroResult).success!==!0)ctx.warnings.push(`Retrospective write failed for phase ${phase.id}`)}catch{}for(let task of phase.tasks??[])if(task.status!=="completed"&&task.status!=="complete")ctx.closedTasks.push(task.id)}{let earliest=1/0;for(let[,session]of swarmState.agentSessions)if(session.lastAgentEventTime>0&&session.lastAgentEventTime<earliest)earliest=session.lastAgentEventTime;if(earliest<1/0)ctx.sessionStart=new Date(earliest).toISOString()}if(!ctx.sessionStart)ctx.sessionStart=readEarliestSessionStart(ctx.directory)??void 0;if(!(ctx.closedPhases.length>0)&&!ctx.planExists)try{let sessionRetroResult=await executeWriteRetro({phase:1,task_id:"retro-session",summary:ctx.isForced?"Plan-free session force-closed via /swarm close --force":"Plan-free session closed via /swarm close",task_count:1,task_complexity:"simple",total_tool_calls:0,coder_revisions:0,reviewer_rejections:0,test_failures:0,security_findings:0,integration_issues:0,metadata:{session_scope:"plan_free",...ctx.sessionStart?{session_start:ctx.sessionStart}:{}}},ctx.directory);try{let parsed=JSON.parse(sessionRetroResult);if(parsed.success!==!0)ctx.warnings.push(`Session retrospective write failed: ${parsed.message??"unknown"}`)}catch{}}catch(retroError){ctx.warnings.push(`Session retrospective write threw: ${retroError instanceof Error?retroError.message:String(retroError)}`)}let lessonsFilePath=path76.join(ctx.swarmDir,"close-lessons.md");try{let lessonsText=await fs34.readFile(lessonsFilePath,"utf-8");ctx.explicitLessons=lessonsText.split(`
1321
1321
  `).map((line)=>line.trim()).filter((line)=>line.length>0&&!line.startsWith("#"))}catch{}try{let evidenceDir=path76.join(ctx.swarmDir,"evidence"),retroDirs=(await fs34.readdir(evidenceDir)).filter((e)=>e.startsWith("retro-")).sort((a,b)=>a.localeCompare(b,void 0,{numeric:!0}));for(let retroDir of retroDirs){let evidencePath=path76.join(evidenceDir,retroDir,"evidence.json");try{let content=await fs34.readFile(evidencePath,"utf-8"),parsed=JSON.parse(content),entries=parsed.entries??[parsed];for(let entry of entries)if(Array.isArray(entry.lessons_learned)){for(let lesson of entry.lessons_learned)if(typeof lesson==="string"&&lesson.trim().length>0)ctx.retroLessons.push(lesson.trim())}}catch{}}}catch{}let dedupedRetroLessons=ctx.retroLessons;try{let existingEntries=await readKnowledge(resolveSwarmKnowledgePath(ctx.directory)),existingLessonTexts=new Set(existingEntries.map((e)=>normalizeLessonText(e.lesson)).filter((t)=>t.length>0));if(existingLessonTexts.size>0)dedupedRetroLessons=ctx.retroLessons.filter((l)=>!existingLessonTexts.has(normalizeLessonText(l)))}catch{dedupedRetroLessons=ctx.retroLessons}ctx.allLessons=[...new Set([...ctx.explicitLessons,...dedupedRetroLessons])],ctx.curationSucceeded=!1;try{ctx.curationResult=await _internals45.curateAndStoreSwarm(ctx.allLessons,ctx.projectName,{phase_number:0},ctx.directory,ctx.config,{llmDelegate:_internals45.createCuratorLLMDelegate(ctx.directory,"phase",ctx.options.sessionID),enrichmentQuota:{maxCalls:ctx.config.enrichment.max_calls_per_day,window:ctx.config.enrichment.quota_window}}),ctx.curationSucceeded=!0}catch(error93){let msg=error93 instanceof Error?error93.message:String(error93);ctx.warnings.push(`Lessons curation failed: ${msg}`),console.warn("[close-command] curateAndStoreSwarm error:",error93)}if(ctx.curationSucceeded&&ctx.allLessons.length>0)await fs34.unlink(lessonsFilePath).catch(()=>{});if(ctx.curationSucceeded)if(ctx.config.hive_enabled===!1);else try{let entries=await readKnowledge(resolveSwarmKnowledgePath(ctx.directory)),result=await _internals45.checkHivePromotions(entries,ctx.config);ctx.hivePromoted=result.new_promotions}catch(hiveErr){let msg=hiveErr instanceof Error?hiveErr.message:String(hiveErr);ctx.warnings.push(`Hive promotion failed: ${msg}`)}ctx.fallbackKnowledgeCreated=ctx.curationResult?.stored??0,ctx.sessionKnowledgeCreated=ctx.fallbackKnowledgeCreated;try{let knowledgePath=resolveSwarmKnowledgePath(ctx.directory),entries=await readKnowledge(knowledgePath);ctx.sessionKnowledgeCreated=countSessionKnowledgeEntries(entries,ctx.sessionStart,ctx.fallbackKnowledgeCreated)}catch(knowledgeErr){let msg=knowledgeErr instanceof Error?knowledgeErr.message:String(knowledgeErr);ctx.warnings.push(`Knowledge session count failed: ${msg}`)}if(ctx.knowledgeSkillHint=ctx.sessionKnowledgeCreated>0?`${ctx.sessionKnowledgeCreated} knowledge entries created this session. Consider running skill_improve or skill_generate to compile mature entries into skills.`:"",ctx.runSkillReview)try{let{config:loadedConfig}=_internals45.loadPluginConfigWithMeta(ctx.directory),skillImproverConfig=SkillImproverConfigSchema.parse(loadedConfig.skill_improver??{}),skillReviewResult=await runAbortableSkillReview({directory:ctx.directory,config:skillImproverConfig,targets:["skills","knowledge"],mode:"proposal",sessionId:ctx.options.sessionID,enrichmentQuota:{maxCalls:ctx.config.enrichment.max_calls_per_day,window:ctx.config.enrichment.quota_window}},ctx.options.skillReviewTimeoutMs??CLOSE_SKILL_REVIEW_TIMEOUT_MS);if(skillReviewResult.ran){let proposal=skillReviewResult.proposalPath?` Proposal: ${skillReviewResult.proposalPath}.`:"",source=skillReviewResult.source?` Source: ${skillReviewResult.source}.`:"";ctx.skillReviewSummary=`Skill review proposal generated.${proposal}${source}`}else{let reason=skillReviewResult.reason??"unknown reason";ctx.skillReviewSummary=`Skill review skipped: ${reason}`,ctx.warnings.push(ctx.skillReviewSummary)}}catch(skillReviewErr){let msg=skillReviewErr instanceof Error?skillReviewErr.message:String(skillReviewErr);ctx.skillReviewSummary=`Skill review failed: ${msg}`,ctx.warnings.push(ctx.skillReviewSummary)}try{ctx.sessionReflection=await runAbortableReflection({directory:ctx.directory,toolAggregates:swarmState.toolAggregates,agentSessions:swarmState.agentSessions,sessionId:ctx.options.sessionID},CLOSE_REFLECTION_TIMEOUT_MS),await writeSessionReflection(ctx.directory,ctx.sessionReflection)}catch(reflectionErr){let msg=reflectionErr instanceof Error?reflectionErr.message:String(reflectionErr);ctx.warnings.push(`Session reflection failed: ${msg}`)}if(ctx.planExists){ctx.originalStatuses=new Map;for(let phase of ctx.planData.phases??[])for(let task of phase.tasks??[])ctx.originalStatuses.set(task.id,task.status);let planDataSnapshot=structuredClone(ctx.planData),closedPhasesLenBefore=ctx.closedPhases.length,closedTasksLenBefore=ctx.closedTasks.length;ctx.guaranteeResult=guaranteeAllPlansComplete(ctx.planData);for(let phaseId of ctx.guaranteeResult.closedPhaseIds)if(!ctx.closedPhases.includes(phaseId))ctx.closedPhases.push(phaseId);for(let taskId of ctx.guaranteeResult.closedTaskIds)if(!ctx.closedTasks.includes(taskId))ctx.closedTasks.push(taskId);if(!ctx.planAlreadyDone||ctx.guaranteeResult.closedPhaseIds.length>0||ctx.guaranteeResult.closedTaskIds.length>0)try{await _internals45.closePlanTerminalState(ctx.directory,ctx.planData,{closedPhaseIds:ctx.guaranteeResult.closedPhaseIds,closedTaskIds:ctx.guaranteeResult.closedTaskIds,originalStatuses:ctx.originalStatuses})}catch(error93){let msg=error93 instanceof Error?error93.message:String(error93);ctx.warnings.push(`Failed to persist terminal plan state: ${msg}`),console.warn("[close-command] Failed to write terminal plan state:",error93),ctx.planData=planDataSnapshot,ctx.closedPhases.length=closedPhasesLenBefore,ctx.closedTasks.length=closedTasksLenBefore}}try{let{CuratorConfigSchema:CCS}=await Promise.resolve().then(() => (init_schema(),exports_schema)),{config:pmLoadedConfig}=_internals45.loadPluginConfigWithMeta(ctx.directory),curatorCfg=CCS.parse(pmLoadedConfig.curator??{});if(curatorCfg.enabled&&curatorCfg.postmortem_enabled){let pmResult=await _internals45.runCuratorPostMortem(ctx.directory,{llmDelegate:_internals45.createCuratorLLMDelegate(ctx.directory,"postmortem",ctx.options.sessionID),scope:"project",sessionID:ctx.options.sessionID});if(pmResult.success&&pmResult.summary)ctx.postMortemSummary=pmResult.summary;for(let w of pmResult.warnings)ctx.warnings.push(`[POST-MORTEM] ${w}`)}}catch(err){let msg=err instanceof Error?err.message:String(err);ctx.warnings.push(`Post-mortem failed: ${msg}`)}}async function copySqliteSafe(srcPath,destPath,laneEnv){if(!fsSync8.existsSync(srcPath))return{success:!0,skipped:!0,reason:"source does not exist (ENOENT)"};let checkpointVerified=!1;try{let result=_internals45.spawnSync("sqlite3",[srcPath,"PRAGMA wal_checkpoint(TRUNCATE);"],{cwd:path76.dirname(srcPath),encoding:"utf-8",stdio:["ignore","pipe","pipe"],timeout:1e4,windowsHide:!0,maxBuffer:1024,envOverrides:laneEnv});if(result.error){if(result.error.code==="ENOENT")try{return await fs34.copyFile(srcPath,destPath),{success:!0,reason:"copied without WAL checkpoint (sqlite3 CLI unavailable)"}}catch(copyErr){return{success:!1,reason:`fallback copy failed: ${copyErr instanceof Error?copyErr.message:String(copyErr)}`}}return{success:!1,reason:`wal_checkpoint failed: ${result.error instanceof Error?result.error.message:String(result.error)}`}}if(result.status!==0)return{success:!1,reason:`wal_checkpoint exited with code ${result.status}`};let lines=(result.stdout||"").trim().split(`
1322
- `).filter((l)=>l.trim());if(lines.length>=1){let columns=lines[0].split("|"),busyFlag=parseInt(columns[0],10);checkpointVerified=!Number.isNaN(busyFlag)&&busyFlag===0}}catch(err){return{success:!1,reason:`wal_checkpoint error: ${err instanceof Error?err.message:String(err)}`}}try{if(await fs34.copyFile(srcPath,destPath),checkpointVerified)return{success:!0};return{success:!0,reason:"WAL checkpoint incomplete (busy) — archive copy may be stale, original preserved"}}catch(err){return{success:!1,reason:`copy failed: ${err instanceof Error?err.message:String(err)}`}}}async function runArchiveStage(ctx){ctx.timestamp=new Date().toISOString().replace(/[:.]/g,"-"),ctx.archiveSuffix=Math.random().toString(36).slice(2,8),ctx.archiveDir=path76.join(ctx.swarmDir,"archive",`swarm-${ctx.timestamp}-${ctx.archiveSuffix}`);try{await fs34.mkdir(ctx.archiveDir,{recursive:!0});let WAL_SIDECAR_FILES=new Set(["swarm.db-shm","swarm.db-wal"]),linkedKnowledgeShared=isLinked(ctx.directory);if(linkedKnowledgeShared)ctx.warnings.push("Worktree is linked: shared knowledge (knowledge.jsonl, knowledge-rejected.jsonl) lives in the link store and is not archived or cleaned by /swarm close. Manage it via the link.");for(let artifact of ARCHIVE_ARTIFACTS){if(WAL_SIDECAR_FILES.has(artifact))continue;if(linkedKnowledgeShared&&KNOWLEDGE_FAMILY_ARTIFACTS.has(artifact))continue;let srcPath=path76.join(ctx.swarmDir,artifact),destPath=path76.join(ctx.archiveDir,artifact);if(artifact==="swarm.db"){let result=await copySqliteSafe(srcPath,destPath,void 0);if(result.skipped);else if(result.success)if(ctx.archivedFileCount++,result.reason)ctx.warnings.push(`Archived ${artifact}: ${result.reason}. Original preserved to prevent data loss.`);else ctx.archivedActiveStateFiles.add(artifact);else ctx.archiveFailureReasons.set(artifact,result.reason),ctx.warnings.push(`Failed to archive ${artifact}: ${result.reason}. File preserved (not cleaned up).`)}else try{if(await fs34.copyFile(srcPath,destPath),ctx.archivedFileCount++,ACTIVE_STATE_TO_CLEAN.includes(artifact))ctx.archivedActiveStateFiles.add(artifact)}catch(err){let errno=err?.code;if(errno==="ENOENT");else{let reason=err instanceof Error?err.message:String(err);ctx.archiveFailureReasons.set(artifact,`${errno??"unknown"}: ${reason}`),ctx.warnings.push(`Failed to archive ${artifact} [${errno??"unknown"}]: ${reason}. File preserved (not cleaned up).`)}}}let dynamicArchiveArtifacts=(await fs34.readdir(ctx.swarmDir).catch(()=>[])).filter((name)=>/^post-mortem-[^/\\]+\.md$/.test(name)||/^drift-report-phase-\d+\.json$/.test(name));for(let artifact of dynamicArchiveArtifacts){let srcPath=path76.join(ctx.swarmDir,artifact),destPath=path76.join(ctx.archiveDir,artifact);try{await fs34.copyFile(srcPath,destPath),ctx.archivedFileCount++,ctx.archivedActiveStateFiles.add(artifact)}catch(err){let errno=err?.code;if(errno!=="ENOENT"){let reason=err instanceof Error?err.message:String(err);ctx.archiveFailureReasons.set(artifact,`${errno??"unknown"}: ${reason}`),ctx.warnings.push(`Failed to archive ${artifact} [${errno??"unknown"}]: ${reason}. File preserved (not cleaned up).`)}}}for(let dirName of ACTIVE_STATE_DIRS_TO_CLEAN){let srcDir=path76.join(ctx.swarmDir,dirName),destDir=path76.join(ctx.archiveDir,dirName);try{let result=await copyDirRecursiveWithFailures(srcDir,destDir);if(ctx.archivedFileCount+=result.copied,result.failures.length===0)ctx.archivedActiveStateDirs.add(dirName);else{ctx.warnings.push(`Directory ${dirName} not fully archived (${result.failures.length} failure(s)). Source preserved.`);for(let failure of result.failures)ctx.warnings.push(` - ${failure}`)}}catch(err){let code=err.code;if(code!=="ENOENT")ctx.warnings.push(`Failed to archive directory ${dirName} [${code??"unknown"}]: ${err.message}. Source preserved.`)}}ctx.archiveResult=`Archived ${ctx.archivedFileCount} artifact(s) to .swarm/archive/swarm-${ctx.timestamp}-${ctx.archiveSuffix}/`}catch(archiveError){ctx.warnings.push(`Archive creation failed: ${archiveError instanceof Error?archiveError.message:String(archiveError)}`),ctx.archiveResult="Archive creation failed (see warnings)"}await runArchiveEvidenceRetention({directory:ctx.directory,swarmDir:ctx.swarmDir,config:ctx.config,warnings:ctx.warnings})}async function runArchiveEvidenceRetention(ctx){let maxAgeDays=30,maxBundles=10;try{let{config:evidenceLoadedConfig}=_internals45.loadPluginConfigWithMeta(ctx.directory),evidenceCfg=evidenceLoadedConfig.evidence??{};if(typeof evidenceCfg.max_age_days==="number")maxAgeDays=evidenceCfg.max_age_days;if(typeof evidenceCfg.max_bundles==="number")maxBundles=evidenceCfg.max_bundles}catch{}try{await _internals45.archiveEvidence(ctx.directory,maxAgeDays,maxBundles)}catch(error93){let msg=error93 instanceof Error?error93.message:String(error93);ctx.warnings.push(`Evidence retention archive failed: ${msg}`),console.warn("[close-command] archiveEvidence error:",error93)}}async function runCleanStage(ctx){let configBackupsRemoved=0,cleanedFiles=[],linkedKnowledgeShared=isLinked(ctx.directory);if(linkedKnowledgeShared){for(let artifact of KNOWLEDGE_FAMILY_ARTIFACTS)if(ctx.archivedActiveStateFiles.has(artifact))ctx.warnings.push(`[link-guard] Shared knowledge artifact "${artifact}" appears in `+"the archive set while this worktree is linked — archive stage "+"should have skipped it. Artifact will NOT be deleted.")}if(ctx.archivedActiveStateFiles.size>0)for(let artifact of ACTIVE_STATE_TO_CLEAN){if(linkedKnowledgeShared&&KNOWLEDGE_FAMILY_ARTIFACTS.has(artifact))continue;if(!ctx.archivedActiveStateFiles.has(artifact)){let reason=ctx.archiveFailureReasons?.get(artifact);if(TERMINAL_STATE_FILES.includes(artifact)){ctx.warnings.push(reason?`${artifact} was not archived (${reason}); removing it anyway to prevent CLOSED-plan resurrection next session — no archive copy retained.`:`${artifact} was not archived; removing it anyway to prevent CLOSED-plan resurrection next session — no archive copy retained.`);continue}ctx.warnings.push(reason?`Preserved ${artifact} because it was not successfully archived: ${reason}.`:`Preserved ${artifact} because it was not successfully archived.`);continue}let filePath=path76.join(ctx.swarmDir,artifact);try{await fs34.unlink(filePath),cleanedFiles.push(artifact)}catch(err){let errno=err?.code;if(errno==="ENOENT");else{let reason=err instanceof Error?err.message:String(err);ctx.warnings.push(`Failed to clean active-state file ${artifact} [${errno??"unknown"}]: ${reason}`)}}}else ctx.warnings.push("Skipped active-state cleanup because no active-state files were archived. Files preserved to prevent data loss.");for(let artifact of ctx.archivedActiveStateFiles){if(!/^post-mortem-[^/\\]+\.md$/.test(artifact)&&!/^drift-report-phase-\d+\.json$/.test(artifact))continue;try{await fs34.unlink(path76.join(ctx.swarmDir,artifact)),cleanedFiles.push(artifact)}catch(err){let errno=err?.code;if(errno!=="ENOENT"){let reason=err instanceof Error?err.message:String(err);ctx.warnings.push(`Failed to clean active-state file ${artifact} [${errno??"unknown"}]: ${reason}`)}}}for(let dirName of ACTIVE_STATE_DIRS_TO_CLEAN){if(!ctx.archivedActiveStateDirs.has(dirName))continue;let dirPath=path76.join(ctx.swarmDir,dirName);try{await fs34.rm(dirPath,{recursive:!0,force:!0}),cleanedFiles.push(`${dirName}/`)}catch{}}try{let swarmFiles=await fs34.readdir(ctx.swarmDir),configBackups=swarmFiles.filter((f)=>f.startsWith("config-backup-")&&f.endsWith(".json"));for(let backup of configBackups)try{await fs34.unlink(path76.join(ctx.swarmDir,backup)),configBackupsRemoved++}catch(err){let errno=err?.code;if(errno==="ENOENT");else{let reason=err instanceof Error?err.message:String(err);ctx.warnings.push(`Failed to clean config-backup ${backup} [${errno??"unknown"}]: ${reason}`)}}let ledgerSiblings=swarmFiles.filter((f)=>(f.startsWith("plan-ledger.archived-")||f.startsWith("plan-ledger.backup-"))&&f.endsWith(".jsonl"));for(let sibling of ledgerSiblings)try{await fs34.unlink(path76.join(ctx.swarmDir,sibling))}catch(err){let errno=err?.code;if(errno==="ENOENT");else{let reason=err instanceof Error?err.message:String(err);ctx.warnings.push(`Failed to clean ledger sibling ${sibling} [${errno??"unknown"}]: ${reason}`)}}}catch(err){let errno=err?.code;if(errno==="ENOENT");else{let reason=err instanceof Error?err.message:String(err);ctx.warnings.push(`Failed to read ${ctx.swarmDir} for stale-file cleanup [${errno??"unknown"}]: ${reason}`)}}let swarmPlanFilesRemoved=0,candidates=[path76.join(ctx.directory,".swarm","plan-export","SWARM_PLAN.json"),path76.join(ctx.directory,".swarm","plan-export","SWARM_PLAN.md"),path76.join(ctx.directory,".swarm","SWARM_PLAN.json"),path76.join(ctx.directory,".swarm","SWARM_PLAN.md"),path76.join(ctx.directory,"SWARM_PLAN.json"),path76.join(ctx.directory,"SWARM_PLAN.md")];for(let candidate of candidates)try{await fs34.unlink(candidate),swarmPlanFilesRemoved++}catch(err){if(err?.code!=="ENOENT")ctx.warnings.push(`Failed to remove ${candidate}: ${err instanceof Error?err.message:String(err)}`)}let tmpFilesRemoved=0;try{let tmpFiles=(await fs34.readdir(ctx.swarmDir)).filter((f)=>f.startsWith(".tmp."));for(let tmp of tmpFiles)try{await fs34.unlink(path76.join(ctx.swarmDir,tmp)),tmpFilesRemoved++}catch(err){let errno=err?.code;if(errno==="ENOENT");else{let reason=err instanceof Error?err.message:String(err);ctx.warnings.push(`Failed to clean tmp file ${tmp} [${errno??"unknown"}]: ${reason}`)}}}catch(err){let errno=err?.code;if(errno==="ENOENT");else{let reason=err instanceof Error?err.message:String(err);ctx.warnings.push(`Failed to read ${ctx.swarmDir} for tmp-file cleanup [${errno??"unknown"}]: ${reason}`)}}if(tmpFilesRemoved>0)cleanedFiles.push(`${tmpFilesRemoved} .tmp.* file(s)`);for(let terminalFile of TERMINAL_STATE_FILES)try{if(await fs34.unlink(path76.join(ctx.swarmDir,terminalFile)),!cleanedFiles.includes(terminalFile))cleanedFiles.push(terminalFile)}catch(err){let errno=err?.code;if(errno==="ENOENT");else{let reason=err instanceof Error?err.message:String(err);ctx.warnings.push(`Failed to remove terminal-state file ${terminalFile} [${errno??"unknown"}]: ${reason}`)}}clearAllScopes(ctx.directory);let contextPath=path76.join(ctx.swarmDir,"context.md"),contextContent=["# Context","","## Status",`Session closed after: ${ctx.projectName}`,`Closed: ${new Date().toISOString()}`,`Finalization: ${ctx.isForced?"forced":ctx.planAlreadyDone?"plan-already-done":"normal"}`,"No active plan. Next session starts fresh.",""].join(`
1322
+ `).filter((l)=>l.trim());if(lines.length>=1){let columns=lines[0].split("|"),busyFlag=parseInt(columns[0],10);checkpointVerified=!Number.isNaN(busyFlag)&&busyFlag===0}}catch(err){return{success:!1,reason:`wal_checkpoint error: ${err instanceof Error?err.message:String(err)}`}}try{if(await fs34.copyFile(srcPath,destPath),checkpointVerified)return{success:!0};return{success:!0,reason:"WAL checkpoint incomplete (busy) — archive copy may be stale, original preserved"}}catch(err){return{success:!1,reason:`copy failed: ${err instanceof Error?err.message:String(err)}`}}}async function runArchiveStage(ctx){ctx.timestamp=new Date().toISOString().replace(/[:.]/g,"-"),ctx.archiveSuffix=Math.random().toString(36).slice(2,8),ctx.archiveDir=path76.join(ctx.swarmDir,"archive",`swarm-${ctx.timestamp}-${ctx.archiveSuffix}`);try{await fs34.mkdir(ctx.archiveDir,{recursive:!0});let WAL_SIDECAR_FILES=new Set(["swarm.db-shm","swarm.db-wal"]),linkedKnowledgeShared=isLinked(ctx.directory);if(linkedKnowledgeShared)ctx.warnings.push("Worktree is linked: shared knowledge (knowledge.jsonl, knowledge-rejected.jsonl) lives in the link store and is not archived or cleaned by /swarm close. Manage it via the link.");for(let artifact of ARCHIVE_ARTIFACTS){if(WAL_SIDECAR_FILES.has(artifact))continue;if(linkedKnowledgeShared&&KNOWLEDGE_FAMILY_ARTIFACTS.has(artifact))continue;let srcPath=path76.join(ctx.swarmDir,artifact),destPath=path76.join(ctx.archiveDir,artifact);if(artifact==="swarm.db"){let result=await copySqliteSafe(srcPath,destPath,void 0);if(result.skipped);else if(result.success)if(ctx.archivedFileCount++,result.reason)ctx.warnings.push(`Archived ${artifact}: ${result.reason}. Original preserved to prevent data loss.`);else ctx.archivedActiveStateFiles.add(artifact);else ctx.archiveFailureReasons.set(artifact,result.reason),ctx.warnings.push(`Failed to archive ${artifact}: ${result.reason}. File preserved (not cleaned up).`)}else try{if(await fs34.copyFile(srcPath,destPath),ctx.archivedFileCount++,ACTIVE_STATE_TO_CLEAN.includes(artifact))ctx.archivedActiveStateFiles.add(artifact)}catch(err){let errno=err?.code;if(errno==="ENOENT");else{let reason=err instanceof Error?err.message:String(err);ctx.archiveFailureReasons.set(artifact,`${errno??"unknown"}: ${reason}`),ctx.warnings.push(`Failed to archive ${artifact} [${errno??"unknown"}]: ${reason}. File preserved (not cleaned up).`)}}}let dynamicArchiveArtifacts=(await fs34.readdir(ctx.swarmDir).catch(()=>[])).filter((name)=>/^post-mortem-[^/\\]+\.md$/.test(name)||/^drift-report-phase-\d+\.json$/.test(name));for(let artifact of dynamicArchiveArtifacts){let srcPath=path76.join(ctx.swarmDir,artifact),destPath=path76.join(ctx.archiveDir,artifact);try{await fs34.copyFile(srcPath,destPath),ctx.archivedFileCount++,ctx.archivedActiveStateFiles.add(artifact)}catch(err){let errno=err?.code;if(errno!=="ENOENT"){let reason=err instanceof Error?err.message:String(err);ctx.archiveFailureReasons.set(artifact,`${errno??"unknown"}: ${reason}`),ctx.warnings.push(`Failed to archive ${artifact} [${errno??"unknown"}]: ${reason}. File preserved (not cleaned up).`)}}}for(let dirName of ACTIVE_STATE_DIRS_TO_CLEAN){let srcDir=path76.join(ctx.swarmDir,dirName),destDir=path76.join(ctx.archiveDir,dirName);try{let result=await copyDirRecursiveWithFailures(srcDir,destDir);if(ctx.archivedFileCount+=result.copied,result.failures.length===0)ctx.archivedActiveStateDirs.add(dirName);else{ctx.warnings.push(`Directory ${dirName} not fully archived (${result.failures.length} failure(s)). Source preserved.`);for(let failure of result.failures)ctx.warnings.push(` - ${failure}`)}}catch(err){let code=err.code;if(code!=="ENOENT")ctx.warnings.push(`Failed to archive directory ${dirName} [${code??"unknown"}]: ${err.message}. Source preserved.`)}}ctx.archiveResult=`Archived ${ctx.archivedFileCount} artifact(s) to .swarm/archive/swarm-${ctx.timestamp}-${ctx.archiveSuffix}/`}catch(archiveError){ctx.warnings.push(`Archive creation failed: ${archiveError instanceof Error?archiveError.message:String(archiveError)}`),ctx.archiveResult="Archive creation failed (see warnings)"}await runArchiveEvidenceRetention({directory:ctx.directory,swarmDir:ctx.swarmDir,config:ctx.config,warnings:ctx.warnings})}async function runArchiveEvidenceRetention(ctx){let maxAgeDays=30,maxBundles=10;try{let{config:evidenceLoadedConfig}=_internals45.loadPluginConfigWithMeta(ctx.directory),evidenceCfg=evidenceLoadedConfig.evidence??{};if(typeof evidenceCfg.max_age_days==="number")maxAgeDays=evidenceCfg.max_age_days;if(typeof evidenceCfg.max_bundles==="number")maxBundles=evidenceCfg.max_bundles}catch{}try{await _internals45.archiveEvidence(ctx.directory,maxAgeDays,maxBundles)}catch(error93){let msg=error93 instanceof Error?error93.message:String(error93);ctx.warnings.push(`Evidence retention archive failed: ${msg}`),console.warn("[close-command] archiveEvidence error:",error93)}}async function runCleanStage(ctx){let configBackupsRemoved=0,cleanedFiles=[],linkedKnowledgeShared=isLinked(ctx.directory);if(linkedKnowledgeShared){for(let artifact of KNOWLEDGE_FAMILY_ARTIFACTS)if(ctx.archivedActiveStateFiles.has(artifact))ctx.warnings.push(`[link-guard] Shared knowledge artifact "${artifact}" appears in `+"the archive set while this worktree is linked — archive stage "+"should have skipped it. Artifact will NOT be deleted.")}if(ctx.archivedActiveStateFiles.size>0)for(let artifact of ACTIVE_STATE_TO_CLEAN){if(linkedKnowledgeShared&&KNOWLEDGE_FAMILY_ARTIFACTS.has(artifact))continue;if(!ctx.archivedActiveStateFiles.has(artifact)){let reason=ctx.archiveFailureReasons?.get(artifact);if(TERMINAL_STATE_FILES.includes(artifact)){ctx.warnings.push(reason?`${artifact} was not archived (${reason}); removing it anyway to prevent CLOSED-plan resurrection next session — no archive copy retained.`:`${artifact} was not archived; removing it anyway to prevent CLOSED-plan resurrection next session — no archive copy retained.`);continue}if(reason)ctx.warnings.push(`Preserved ${artifact} because it was not successfully archived: ${reason}.`);continue}let filePath=path76.join(ctx.swarmDir,artifact);try{await fs34.unlink(filePath),cleanedFiles.push(artifact)}catch(err){let errno=err?.code;if(errno==="ENOENT");else{let reason=err instanceof Error?err.message:String(err);ctx.warnings.push(`Failed to clean active-state file ${artifact} [${errno??"unknown"}]: ${reason}`)}}}else ctx.warnings.push("Skipped active-state cleanup because no active-state files were archived. Files preserved to prevent data loss.");for(let artifact of ctx.archivedActiveStateFiles){if(!/^post-mortem-[^/\\]+\.md$/.test(artifact)&&!/^drift-report-phase-\d+\.json$/.test(artifact))continue;try{await fs34.unlink(path76.join(ctx.swarmDir,artifact)),cleanedFiles.push(artifact)}catch(err){let errno=err?.code;if(errno!=="ENOENT"){let reason=err instanceof Error?err.message:String(err);ctx.warnings.push(`Failed to clean active-state file ${artifact} [${errno??"unknown"}]: ${reason}`)}}}for(let dirName of ACTIVE_STATE_DIRS_TO_CLEAN){if(!ctx.archivedActiveStateDirs.has(dirName))continue;let dirPath=path76.join(ctx.swarmDir,dirName);try{await fs34.rm(dirPath,{recursive:!0,force:!0}),cleanedFiles.push(`${dirName}/`)}catch{}}try{let swarmFiles=await fs34.readdir(ctx.swarmDir),configBackups=swarmFiles.filter((f)=>f.startsWith("config-backup-")&&f.endsWith(".json"));for(let backup of configBackups)try{await fs34.unlink(path76.join(ctx.swarmDir,backup)),configBackupsRemoved++}catch(err){let errno=err?.code;if(errno==="ENOENT");else{let reason=err instanceof Error?err.message:String(err);ctx.warnings.push(`Failed to clean config-backup ${backup} [${errno??"unknown"}]: ${reason}`)}}let ledgerSiblings=swarmFiles.filter((f)=>(f.startsWith("plan-ledger.archived-")||f.startsWith("plan-ledger.backup-"))&&f.endsWith(".jsonl"));for(let sibling of ledgerSiblings)try{await fs34.unlink(path76.join(ctx.swarmDir,sibling))}catch(err){let errno=err?.code;if(errno==="ENOENT");else{let reason=err instanceof Error?err.message:String(err);ctx.warnings.push(`Failed to clean ledger sibling ${sibling} [${errno??"unknown"}]: ${reason}`)}}}catch(err){let errno=err?.code;if(errno==="ENOENT");else{let reason=err instanceof Error?err.message:String(err);ctx.warnings.push(`Failed to read ${ctx.swarmDir} for stale-file cleanup [${errno??"unknown"}]: ${reason}`)}}let swarmPlanFilesRemoved=0,candidates=[path76.join(ctx.directory,".swarm","plan-export","SWARM_PLAN.json"),path76.join(ctx.directory,".swarm","plan-export","SWARM_PLAN.md"),path76.join(ctx.directory,".swarm","SWARM_PLAN.json"),path76.join(ctx.directory,".swarm","SWARM_PLAN.md"),path76.join(ctx.directory,"SWARM_PLAN.json"),path76.join(ctx.directory,"SWARM_PLAN.md")];for(let candidate of candidates)try{await fs34.unlink(candidate),swarmPlanFilesRemoved++}catch(err){if(err?.code!=="ENOENT")ctx.warnings.push(`Failed to remove ${candidate}: ${err instanceof Error?err.message:String(err)}`)}let tmpFilesRemoved=0;try{let tmpFiles=(await fs34.readdir(ctx.swarmDir)).filter((f)=>f.startsWith(".tmp."));for(let tmp of tmpFiles)try{await fs34.unlink(path76.join(ctx.swarmDir,tmp)),tmpFilesRemoved++}catch(err){let errno=err?.code;if(errno==="ENOENT");else{let reason=err instanceof Error?err.message:String(err);ctx.warnings.push(`Failed to clean tmp file ${tmp} [${errno??"unknown"}]: ${reason}`)}}}catch(err){let errno=err?.code;if(errno==="ENOENT");else{let reason=err instanceof Error?err.message:String(err);ctx.warnings.push(`Failed to read ${ctx.swarmDir} for tmp-file cleanup [${errno??"unknown"}]: ${reason}`)}}if(tmpFilesRemoved>0)cleanedFiles.push(`${tmpFilesRemoved} .tmp.* file(s)`);for(let terminalFile of TERMINAL_STATE_FILES)try{if(await fs34.unlink(path76.join(ctx.swarmDir,terminalFile)),!cleanedFiles.includes(terminalFile))cleanedFiles.push(terminalFile)}catch(err){let errno=err?.code;if(errno==="ENOENT");else{let reason=err instanceof Error?err.message:String(err);ctx.warnings.push(`Failed to remove terminal-state file ${terminalFile} [${errno??"unknown"}]: ${reason}`)}}clearAllScopes(ctx.directory);let contextPath=path76.join(ctx.swarmDir,"context.md"),contextContent=["# Context","","## Status",`Session closed after: ${ctx.projectName}`,`Closed: ${new Date().toISOString()}`,`Finalization: ${ctx.isForced?"forced":ctx.planAlreadyDone?"plan-already-done":"normal"}`,"No active plan. Next session starts fresh.",""].join(`
1323
1323
  `),contextTempPath=path76.join(path76.dirname(contextPath),`${path76.basename(contextPath)}.tmp.${Date.now()}.${Math.floor(Math.random()*1e9)}`);try{await fs34.writeFile(contextTempPath,contextContent,"utf-8"),fsSync8.renameSync(contextTempPath,contextPath)}catch(error93){try{fsSync8.unlinkSync(contextTempPath)}catch{}let msg=error93 instanceof Error?error93.message:String(error93);ctx.warnings.push(`Failed to reset context.md: ${msg}`),console.warn("[close-command] Failed to write context.md:",error93)}return{cleanedFiles,configBackupsRemoved,swarmPlanFilesRemoved,tmpFilesRemoved}}async function runAlignStage(ctx){let pruneBranches=ctx.args.includes("--prune-branches"),gitAlignResult="",prunedBranches=[],gitStatus=_internals45.getGitRepositoryStatus(ctx.directory);if(gitStatus.isRepo){let aggressiveResult=await _internals45.resetToMainAfterMerge(ctx.directory,{pruneBranches});if(aggressiveResult.success){gitAlignResult=aggressiveResult.message;for(let w of aggressiveResult.warnings)ctx.warnings.push(w);if(aggressiveResult.changesDiscarded)ctx.warnings.push("Uncommitted changes were discarded during git alignment")}else{let alignResult=await _internals45.resetToRemoteBranch(ctx.directory,{pruneBranches});if(gitAlignResult=alignResult.message,prunedBranches.push(...alignResult.prunedBranches),!alignResult.success)ctx.warnings.push(`Git alignment: ${alignResult.message}`);if(alignResult.alreadyAligned)gitAlignResult=`Already aligned with ${alignResult.targetBranch}`;for(let w of alignResult.warnings)ctx.warnings.push(w)}}else if(gitStatus.reason==="git_unavailable")gitAlignResult=`Git executable unavailable — skipped git alignment: ${gitStatus.message}`,ctx.warnings.push(gitAlignResult);else if(gitStatus.reason==="git_error")gitAlignResult=`Git repository check failed — skipped git alignment: ${gitStatus.message}`,ctx.warnings.push(gitAlignResult);else gitAlignResult="Not a git repository — skipped git alignment";return{gitAlignResult,prunedBranches}}async function handleCloseCommand(directory,args2,options={}){let swarmDir=path76.join(directory,".swarm");try{if(fsSync8.lstatSync(swarmDir).isSymbolicLink())return"❌ Refused: .swarm/ is a symlink or junction. Refusing to operate on a redirected directory for safety."}catch(err){if(err?.code!=="ENOENT")throw err}let planPath=validateSwarmPath(directory,"plan.json"),planExists=!1,planData={title:path76.basename(directory)||"Ad-hoc session",phases:[]};try{let content=await fs34.readFile(planPath,"utf-8");planData=JSON.parse(content),planExists=!0}catch(error93){if(error93?.code!=="ENOENT")return`❌ Failed to read plan.json: ${error93 instanceof Error?error93.message:String(error93)}`;if(!await fs34.access(swarmDir).then(()=>!0).catch(()=>!1))return`❌ No .swarm/ directory found in ${directory}. Run /swarm close from the project root, or run /swarm plan first.`}let finalizeLock={acquired:!1};if(finalizeLock=await _internals45.acquireFinalizeLock(directory),!finalizeLock.acquired)return"❌ Another /swarm finalize is already running for this project. If you are certain no other run is active, wait for the lock to expire or remove the stale lock and retry.";try{if(!planExists){let archiveDir=path76.join(swarmDir,"archive");try{if((await fs34.readdir(archiveDir)).some((entry)=>entry.startsWith("swarm-"))){if(![...ACTIVE_STATE_TO_CLEAN,...ACTIVE_STATE_DIRS_TO_CLEAN].some((entry)=>fsSync8.existsSync(path76.join(swarmDir,entry))))return`✅ Already finalized — nothing to do.
1324
1324
 
1325
1325
  This project was already finalized in a previous /swarm close run. The plan has been archived and cleaned up. No further action is needed.`}}catch{}}let phases=planData.phases??[],inProgressPhases=phases.filter((p)=>p.status==="in_progress"),isForced=args2.includes("--force"),runSkillReview=args2.includes("--skill-review"),planAlreadyDone=!1;if(planExists)planAlreadyDone=phases.length>0&&phases.every((p)=>p.status==="complete"||p.status==="completed"||p.status==="blocked"||p.status==="closed");let{config:loadedConfig}=_internals45.loadPluginConfigWithMeta(directory),config3=KnowledgeConfigSchema.parse(loadedConfig.knowledge??{}),ctx={directory,swarmDir,planData,planExists,planAlreadyDone,config:config3,projectName:planData.title??"Unknown Project",warnings:[],closedPhases:[],closedTasks:[],sessionStart:void 0,isForced,runSkillReview,options,phases,inProgressPhases,curationSucceeded:!1,curationResult:void 0,allLessons:[],explicitLessons:[],retroLessons:[],knowledgeSkillHint:"",skillReviewSummary:"",postMortemSummary:"",sessionReflection:void 0,hivePromoted:0,sessionKnowledgeCreated:0,fallbackKnowledgeCreated:0,originalStatuses:new Map,guaranteeResult:{closedPhaseIds:[],closedTaskIds:[]},archiveResult:"",archivedFileCount:0,archivedActiveStateFiles:new Set,archivedActiveStateDirs:new Set,archiveFailureReasons:new Map,timestamp:"",archiveDir:"",archiveSuffix:"",args:args2};await runFinalizeStage(ctx),await _internals45.runFinalizeRewardSweep({directory,closedTaskIds:ctx.guaranteeResult.closedTaskIds,memoryConfig:loadedConfig.memory}),await runArchiveStage(ctx);let cleanResult=await runCleanStage(ctx),{gitAlignResult,prunedBranches}=await runAlignStage(ctx),closeSummaryPath=validateSwarmPath(ctx.directory,"close-summary.md"),finalizationType=ctx.isForced?"Forced closure":ctx.planAlreadyDone?"Plan already terminal — cleanup only":"Normal finalization",summaryContent=["# Swarm Close Summary","",`**Project:** ${ctx.projectName}`,`**Closed:** ${new Date().toISOString()}`,`**Finalization:** ${finalizationType}`,"","## Retrospective",!ctx.planExists?"_No plan — ad-hoc session_":ctx.closedPhases.length>0?ctx.closedPhases.map((id)=>`- Phase ${id} closed`).join(`
@@ -1352,7 +1352,7 @@ ${ctx.sessionReflection.architectReport}`}if(ctx.planAlreadyDone)return`✅ Sess
1352
1352
  **Git:** ${gitAlignResult}${lessonSummary}${knowledgeHintSummary}${skillReviewOutput}${postMortemOutput}${reflectionOutput}${warningMsg}`;return`✅ Swarm finalized. ${ctx.closedPhases.length} phase(s) closed, ${ctx.closedTasks.length} incomplete task(s) marked closed.
1353
1353
 
1354
1354
  **Archive:** ${ctx.archiveResult}
1355
- **Git:** ${gitAlignResult}${lessonSummary}${knowledgeHintSummary}${skillReviewOutput}${postMortemOutput}${reflectionOutput}${warningMsg}`}finally{if(finalizeLock.release)try{await finalizeLock.release()}catch{}}}async function acquireFinalizeLock(directory){let result=await tryAcquireLock(directory,"finalize.lock","close-command","finalize");if(result.acquired)return{acquired:!0,release:result.lock._release};return{acquired:!1}}var CLOSE_SKILL_REVIEW_TIMEOUT_MS=120000,CLOSE_REFLECTION_TIMEOUT_MS=90000,ARCHIVE_ARTIFACTS,ACTIVE_STATE_TO_CLEAN,TERMINAL_STATE_FILES,KNOWLEDGE_FAMILY_ARTIFACTS,ACTIVE_STATE_DIRS_TO_CLEAN,_internals45;var init_close=__esm(()=>{init_config();init_schema();init_manager2();init_branch();init_curator_llm_factory();init_curator_postmortem();init_hive_promoter();init_knowledge_curator();init_knowledge_link();init_knowledge_store();init_utils2();init_finalize_reward_sweep();init_file_locks();init_manager();init_scope_persistence();init_session_reflection();init_skill_improver();init_session_start_store();init_state2();init_write_retro();init_bun_compat();ARCHIVE_ARTIFACTS=["plan.json","plan.md","plan-ledger.jsonl","context.md","events.jsonl","handoff.md","handoff-prompt.md","handoff-consumed.md","escalation-report.md","close-lessons.md","knowledge.jsonl","knowledge-rejected.jsonl","repo-graph.json","doc-manifest.json","dark-matter.md","telemetry.jsonl","swarm.db","swarm.db-shm","swarm.db-wal","close-summary.md","session-reflection.md","spec.md"],ACTIVE_STATE_TO_CLEAN=["plan.json","plan.md","plan-ledger.jsonl","events.jsonl","handoff.md","handoff-prompt.md","handoff-consumed.md","escalation-report.md","knowledge-rejected.jsonl","repo-graph.json","doc-manifest.json","dark-matter.md","telemetry.jsonl","session-reflection.md","swarm.db","swarm.db-shm","swarm.db-wal"],TERMINAL_STATE_FILES=["plan.json","plan-ledger.jsonl"],KNOWLEDGE_FAMILY_ARTIFACTS=new Set(["knowledge.jsonl","knowledge-rejected.jsonl"]),ACTIVE_STATE_DIRS_TO_CLEAN=["evidence","session","scopes","spec-archive"];_internals45={ACTIVE_STATE_DIRS_TO_CLEAN,countSessionKnowledgeEntries,CLOSE_SKILL_REVIEW_TIMEOUT_MS,CLOSE_REFLECTION_TIMEOUT_MS,guaranteeAllPlansComplete,getGitRepositoryStatus,resetToMainAfterMerge,resetToRemoteBranch,copyDirRecursive,loadPluginConfigWithMeta,curateAndStoreSwarm,checkHivePromotions,runCuratorPostMortem,createCuratorLLMDelegate,resetSwarmStatePreservingSingletons,runFinalizeStage,runFinalizeRewardSweep,acquireFinalizeLock,runArchiveStage,runArchiveEvidenceRetention,runCleanStage,runAlignStage,archiveEvidence,closePlanTerminalState,endAgentSession,spawnSync:(cmd,args2,options)=>{let mergedEnv=mergeEnvForChild(options?.env,options?.envOverrides);return child_process4.spawnSync(cmd,args2,{...options,env:mergedEnv})}}});function sanitizeText(raw,maxLen){let normalized=raw.replace(/\[+\s*MODE\s*:[^\]]*(?:\]+|$)/gi,"").replace(/\s+/g," ").trim();if(normalized.length<=maxLen)return normalized;return`${normalized.slice(0,maxLen)}...`}function hasFlagValue(args2,index){return index+1<args2.length&&!args2[index+1].startsWith("--")}function jsonForModeHeader(value){return JSON.stringify(value).replace(/[[\]]/g,(ch)=>ch==="["?"\\u005B":"\\u005D")}function parseArgs(args2){let result={mode:"phase0",tracks:"",continueRun:"",output:"markdown",updateMain:!0,allowDirty:!1,rest:[]},i=0;while(i<args2.length){let token=args2[i];if(token==="--help"||token==="-h")result.help=!0;else if(token==="--mode"){if(!hasFlagValue(args2,i))return{...result,error:FLAG_VALUE_MISSING(token)};let value=args2[++i];if(!MODES.has(value))return{...result,error:`Invalid mode "${value}". Must be one of: ${[...MODES].join(", ")}.`};result.mode=value}else if(token==="--tracks"){if(!hasFlagValue(args2,i))return{...result,error:FLAG_VALUE_MISSING(token)};result.tracks=sanitizeText(args2[++i],1000)}else if(token==="--continue"){if(!hasFlagValue(args2,i))return{...result,error:FLAG_VALUE_MISSING(token)};let runId=sanitizeText(args2[++i],128);if(!/^[A-Za-z0-9_.-]+$/.test(runId))return{...result,error:"Invalid --continue value. Use only letters, numbers, dot, underscore, or dash."};result.continueRun=runId}else if(token==="--json")result.output="json";else if(token==="--skip-update")result.updateMain=!1;else if(token==="--allow-dirty")result.allowDirty=!0;else if(token.startsWith("--"))return{...result,error:`Unknown flag "${token}"`};else result.rest.push(token);i++}return result}async function handleCodebaseReviewCommand(_directory,args2){let parsed=parseArgs(args2);if(parsed.help)return`Usage: /swarm codebase-review [scope] [--mode phase0|complete|defect|security|correctness|testing|ui|performance|ai-slop|enhancements|custom] [--tracks <list>] [--continue <run-id>] [--json] [--skip-update] [--allow-dirty]
1355
+ **Git:** ${gitAlignResult}${lessonSummary}${knowledgeHintSummary}${skillReviewOutput}${postMortemOutput}${reflectionOutput}${warningMsg}`}finally{if(finalizeLock.release)try{await finalizeLock.release()}catch{}}}async function acquireFinalizeLock(directory){let result=await tryAcquireLock(directory,"finalize.lock","close-command","finalize");if(result.acquired)return{acquired:!0,release:result.lock._release};return{acquired:!1}}var CLOSE_SKILL_REVIEW_TIMEOUT_MS=120000,CLOSE_REFLECTION_TIMEOUT_MS=90000,ARCHIVE_ARTIFACTS,ACTIVE_STATE_TO_CLEAN,TERMINAL_STATE_FILES,KNOWLEDGE_FAMILY_ARTIFACTS,ACTIVE_STATE_DIRS_TO_CLEAN,_internals45;var init_close=__esm(()=>{init_config();init_schema();init_manager2();init_branch();init_curator_llm_factory();init_curator_postmortem();init_hive_promoter();init_knowledge_curator();init_knowledge_link();init_knowledge_store();init_utils2();init_finalize_reward_sweep();init_file_locks();init_manager();init_scope_persistence();init_session_reflection();init_skill_improver();init_session_start_store();init_state2();init_write_retro();init_bun_compat();ARCHIVE_ARTIFACTS=["plan.json","plan.md","plan-ledger.jsonl","context.md","events.jsonl","handoff.md","handoff-prompt.md","handoff-consumed.md","escalation-report.md","close-lessons.md","knowledge.jsonl","knowledge-rejected.jsonl","repo-graph.json","doc-manifest.json","dark-matter.md","telemetry.jsonl","swarm.db","swarm.db-shm","swarm.db-wal","close-summary.md","session-reflection.md","spec.md","spec-staleness.json","spec-snapshot.md"],ACTIVE_STATE_TO_CLEAN=["plan.json","plan.md","plan-ledger.jsonl","events.jsonl","handoff.md","handoff-prompt.md","handoff-consumed.md","escalation-report.md","knowledge-rejected.jsonl","repo-graph.json","doc-manifest.json","dark-matter.md","telemetry.jsonl","session-reflection.md","spec.md","spec-staleness.json","spec-snapshot.md","swarm.db","swarm.db-shm","swarm.db-wal"],TERMINAL_STATE_FILES=["plan.json","plan-ledger.jsonl","spec-staleness.json","spec-snapshot.md"],KNOWLEDGE_FAMILY_ARTIFACTS=new Set(["knowledge.jsonl","knowledge-rejected.jsonl"]),ACTIVE_STATE_DIRS_TO_CLEAN=["evidence","session","scopes","spec-archive"];_internals45={ACTIVE_STATE_DIRS_TO_CLEAN,countSessionKnowledgeEntries,CLOSE_SKILL_REVIEW_TIMEOUT_MS,CLOSE_REFLECTION_TIMEOUT_MS,guaranteeAllPlansComplete,getGitRepositoryStatus,resetToMainAfterMerge,resetToRemoteBranch,copyDirRecursive,loadPluginConfigWithMeta,curateAndStoreSwarm,checkHivePromotions,runCuratorPostMortem,createCuratorLLMDelegate,resetSwarmStatePreservingSingletons,runFinalizeStage,runFinalizeRewardSweep,acquireFinalizeLock,runArchiveStage,runArchiveEvidenceRetention,runCleanStage,runAlignStage,archiveEvidence,closePlanTerminalState,endAgentSession,spawnSync:(cmd,args2,options)=>{let mergedEnv=mergeEnvForChild(options?.env,options?.envOverrides);return child_process4.spawnSync(cmd,args2,{...options,env:mergedEnv})}}});function sanitizeText(raw,maxLen){let normalized=raw.replace(/\[+\s*MODE\s*:[^\]]*(?:\]+|$)/gi,"").replace(/\s+/g," ").trim();if(normalized.length<=maxLen)return normalized;return`${normalized.slice(0,maxLen)}...`}function hasFlagValue(args2,index){return index+1<args2.length&&!args2[index+1].startsWith("--")}function jsonForModeHeader(value){return JSON.stringify(value).replace(/[[\]]/g,(ch)=>ch==="["?"\\u005B":"\\u005D")}function parseArgs(args2){let result={mode:"phase0",tracks:"",continueRun:"",output:"markdown",updateMain:!0,allowDirty:!1,rest:[]},i=0;while(i<args2.length){let token=args2[i];if(token==="--help"||token==="-h")result.help=!0;else if(token==="--mode"){if(!hasFlagValue(args2,i))return{...result,error:FLAG_VALUE_MISSING(token)};let value=args2[++i];if(!MODES.has(value))return{...result,error:`Invalid mode "${value}". Must be one of: ${[...MODES].join(", ")}.`};result.mode=value}else if(token==="--tracks"){if(!hasFlagValue(args2,i))return{...result,error:FLAG_VALUE_MISSING(token)};result.tracks=sanitizeText(args2[++i],1000)}else if(token==="--continue"){if(!hasFlagValue(args2,i))return{...result,error:FLAG_VALUE_MISSING(token)};let runId=sanitizeText(args2[++i],128);if(!/^[A-Za-z0-9_.-]+$/.test(runId))return{...result,error:"Invalid --continue value. Use only letters, numbers, dot, underscore, or dash."};result.continueRun=runId}else if(token==="--json")result.output="json";else if(token==="--skip-update")result.updateMain=!1;else if(token==="--allow-dirty")result.allowDirty=!0;else if(token.startsWith("--"))return{...result,error:`Unknown flag "${token}"`};else result.rest.push(token);i++}return result}async function handleCodebaseReviewCommand(_directory,args2){let parsed=parseArgs(args2);if(parsed.help)return`Usage: /swarm codebase-review [scope] [--mode phase0|complete|defect|security|correctness|testing|ui|performance|ai-slop|enhancements|custom] [--tracks <list>] [--continue <run-id>] [--json] [--skip-update] [--allow-dirty]
1356
1356
 
1357
1357
  Run the codebase-review-swarm workflow in the current repository.
1358
1358
 
@@ -1717,7 +1717,7 @@ ${stackPrefix}`;return INFRASTRUCTURE_FAILURE_PATTERNS.some((pattern)=>pattern.t
1717
1717
  `)||" (none)"].join(`
1718
1718
  `)}return["Usage:"," /swarm qa-gates show current profile + effective gates"," /swarm qa-gates enable <gate>... persist-enable gate(s) (rejected if locked)"," /swarm qa-gates override <gate>... session-only enable (ratchet-tighter)",`Valid gates: ${ALL_GATE_NAMES.join(", ")}`].join(`
1719
1719
  `)}var ALL_GATE_NAMES;var init_qa_gates=__esm(()=>{init_qa_gate_profile();init_manager();init_utils3();init_state2();ALL_GATE_NAMES=["reviewer","test_engineer","council_mode","sme_enabled","critic_pre_plan","hallucination_guard","sast_enabled","mutation_test","phase_council","drift_check","final_council"]});class CircuitBreaker{state="closed";failureCount=0;successCount=0;lastFailureTime;config;name;onStateChange;constructor(name,config3,onStateChange){this.name=name,this.config={failureThreshold:config3?.failureThreshold??5,resetTimeoutMs:config3?.resetTimeoutMs??30000,successThreshold:config3?.successThreshold??3,callTimeoutMs:config3?.callTimeoutMs??1e4},this.onStateChange=onStateChange}getState(){if(this.state==="open"&&this.lastFailureTime){if(Date.now()-this.lastFailureTime>=this.config.resetTimeoutMs)this.transitionTo("half-open")}return this.state}async execute(fn2){if(this.getState()==="open")throw Error(`Circuit breaker '${this.name}' is open`);let startTime=Date.now();try{let result=await this.executeWithTimeout(fn2),duration5=Date.now()-startTime;return this.recordSuccess(duration5),result}catch(error93){let duration5=Date.now()-startTime;throw this.recordFailure(error93,duration5),error93}}async executeWithTimeout(fn2){if(this.config.callTimeoutMs<=0)return fn2();return new Promise((resolve46,reject)=>{let timeout=setTimeout(()=>{reject(Error(`Call timeout after ${this.config.callTimeoutMs}ms`))},this.config.callTimeoutMs);fn2().then((result)=>{clearTimeout(timeout),resolve46(result)}).catch((error93)=>{clearTimeout(timeout),reject(error93)})})}recordSuccess(duration5){if(this.failureCount=0,this.state==="half-open"){if(this.successCount++,this.successCount>=this.config.successThreshold)this.transitionTo("closed")}this.onStateChange?.("callSuccess",{duration:duration5})}recordFailure(error93,duration5){if(this.failureCount++,this.lastFailureTime=Date.now(),this.state==="half-open")this.transitionTo("open");else if(this.state==="closed"&&this.failureCount>=this.config.failureThreshold)this.transitionTo("open");this.onStateChange?.("callFailure",{error:error93,duration:duration5})}transitionTo(newState){let oldState=this.state;if(this.state=newState,newState==="closed")this.failureCount=0,this.successCount=0,this.onStateChange?.("closed",{timestamp:Date.now(),successCount:0,oldState});else if(newState==="open")this.successCount=0,this.onStateChange?.("opened",{timestamp:Date.now(),failureCount:this.failureCount,oldState});else if(newState==="half-open")this.successCount=0,this.onStateChange?.("half-open",{timestamp:Date.now(),oldState})}reset(){this.transitionTo("closed")}getStats(){return{state:this.getState(),failureCount:this.failureCount,successCount:this.successCount,lastFailureTime:this.lastFailureTime}}}class LoopProtection{records=new Map;config;onLoopDetected;constructor(config3,onLoopDetected){this.config=config3,this.onLoopDetected=onLoopDetected}recordAttempt(key){let operationKey=key??this.config.operationKey,now=Date.now(),record3=this.records.get(operationKey);if(record3&&now-record3.firstAttempt>this.config.timeWindowMs)record3=void 0;if(!record3)return this.records.set(operationKey,{count:1,firstAttempt:now,lastAttempt:now}),!0;if(record3.count++,record3.lastAttempt=now,record3.count>this.config.maxIterations)return this.onLoopDetected?.(operationKey,record3.count),!1;return!0}canProceed(key){let operationKey=key??this.config.operationKey,record3=this.records.get(operationKey);if(!record3)return!0;if(Date.now()-record3.firstAttempt>this.config.timeWindowMs)return!0;return record3.count<=this.config.maxIterations}getRemainingIterations(key){let operationKey=key??this.config.operationKey,record3=this.records.get(operationKey);if(!record3)return this.config.maxIterations;if(Date.now()-record3.firstAttempt>this.config.timeWindowMs)return this.config.maxIterations;return Math.max(0,this.config.maxIterations-record3.count)}reset(key){let operationKey=key??this.config.operationKey;this.records.delete(operationKey)}resetAll(){this.records.clear()}getIterationCount(key){let operationKey=key??this.config.operationKey,record3=this.records.get(operationKey);if(!record3)return 0;if(Date.now()-record3.firstAttempt>this.config.timeWindowMs)return 0;return record3.count}getTrackedOperations(){return Array.from(this.records.keys())}}function comparePriority(a,b){let priorityOrder={critical:0,high:1,normal:2,low:3},priorityDiff=priorityOrder[a.priority]-priorityOrder[b.priority];if(priorityDiff!==0)return priorityDiff;return a.createdAt-b.createdAt}class AutomationQueue{items=[];maxSize;defaultMaxRetries;defaultBackoffMs;maxBackoffMs;eventBus;overflowStrategy;itemCounter=0;constructor(config3){this.maxSize=config3?.maxSize??1000,this.defaultMaxRetries=config3?.defaultMaxRetries??3,this.defaultBackoffMs=config3?.defaultBackoffMs??1000,this.maxBackoffMs=config3?.maxBackoffMs??60000,this.overflowStrategy=config3?.overflowStrategy??"throw",this.eventBus=getGlobalEventBus()}generateId(){return`queue-${Date.now()}-${++this.itemCounter}`}enqueue(payload,priority="normal",metadata){if(this.items.length>=this.maxSize)if(this.overflowStrategy==="evict-oldest"){let oldestIdx=0;for(let i=1;i<this.items.length;i++)if(this.items[i].createdAt<this.items[oldestIdx].createdAt)oldestIdx=i;let[evicted]=this.items.splice(oldestIdx,1);if(evicted)this.eventBus.publish("queue.item.evicted",{itemId:evicted.id})}else throw Error(`Queue is full (max ${this.maxSize} items)`);let item={id:this.generateId(),priority,payload,createdAt:Date.now(),metadata,retry:{attempts:0,maxAttempts:this.defaultMaxRetries,backoffMs:this.defaultBackoffMs,maxBackoffMs:this.maxBackoffMs}};return this.items.push(item),this.items.sort(comparePriority),this.eventBus.publish("queue.item.enqueued",{itemId:item.id,priority}),item.id}dequeue(){let item=this.items.shift();if(item)this.eventBus.publish("queue.item.dequeued",{itemId:item.id});return item}peek(){return this.items[0]}get(id){return this.items.find((item)=>item.id===id)}remove(id){let index=this.items.findIndex((item)=>item.id===id);if(index!==-1)return this.items.splice(index,1),!0;return!1}complete(id){let removed=this.remove(id);if(removed)this.eventBus.publish("queue.item.completed",{itemId:id});return removed}retry(id,_error){let item=this.get(id);if(!item||!item.retry)return!1;if(item.retry.attempts++,item.retry.lastAttempt=Date.now(),item.retry.attempts>=item.retry.maxAttempts)return this.eventBus.publish("queue.item.failed",{itemId:id,attempts:item.retry.attempts}),this.remove(id),!1;let backoff=Math.min(item.retry.backoffMs*2**(item.retry.attempts-1),item.retry.maxBackoffMs);return item.retry.nextAttemptAt=Date.now()+backoff,this.eventBus.publish("queue.item.retry scheduled",{itemId:id,attempt:item.retry.attempts,nextAttemptAt:item.retry.nextAttemptAt,backoffMs:backoff}),!0}getRetryableItems(){let now=Date.now();return this.items.filter((item)=>item.retry?.nextAttemptAt&&item.retry.nextAttemptAt<=now)}size(){return this.items.length}isEmpty(){return this.items.length===0}isFull(){return this.items.length>=this.maxSize}clear(){this.items=[]}getAll(){return[...this.items]}getByPriority(priority){return this.items.filter((item)=>item.priority===priority)}getStats(){return{size:this.items.length,maxSize:this.maxSize,byPriority:{critical:this.items.filter((i)=>i.priority==="critical").length,high:this.items.filter((i)=>i.priority==="high").length,normal:this.items.filter((i)=>i.priority==="normal").length,low:this.items.filter((i)=>i.priority==="low").length},retryable:this.getRetryableItems().length}}}var init_queue=__esm(()=>{init_event_bus()});function sleep2(ms){return new Promise((resolve46)=>setTimeout(resolve46,ms))}class WorkerManager{workers=new Map;eventBus;constructor(){this.eventBus=getGlobalEventBus()}register(registration){if(this.workers.has(registration.name))throw Error(`Worker '${registration.name}' is already registered`);let worker={name:registration.name,handler:registration.handler,queue:registration.queue,concurrency:registration.concurrency??1,status:"idle",activeCount:0,processedCount:0,errorCount:0};if(this.workers.set(registration.name,worker),this.eventBus.publish("worker.started",{workerName:registration.name,concurrency:worker.concurrency}),registration.autoStart)this.start(registration.name)}unregister(name){let worker=this.workers.get(name);if(!worker)return!1;if(worker.status==="running")this.stop(name);return this.workers.delete(name),!0}start(name){let worker=this.workers.get(name);if(!worker)throw Error(`Worker '${name}' is not registered`);if(worker.status==="running")return!1;return worker.status="running",this.startProcessingLoop(worker),this.eventBus.publish("worker.started",{workerName:name,concurrency:worker.concurrency}),!0}startProcessingLoop(worker){(async()=>{while(worker.status==="running"){if(worker.activeCount>=worker.concurrency){await sleep2(50);continue}let item=worker.queue.dequeue();if(!item){await sleep2(100);continue}worker.activeCount++,this.handleItem(worker,item).finally(()=>{worker.activeCount--})}})().catch((error93)=>{this.eventBus.publish("worker.error",{workerName:worker.name,itemId:"loop",error:error93})})}async handleItem(worker,item){try{let result=await worker.handler(item);if(result.success)worker.processedCount++,worker.queue.complete(item.id);else worker.errorCount++,worker.lastError=result.error,worker.queue.retry(item.id,result.error)}catch(error93){worker.errorCount++,worker.lastError=error93,this.eventBus.publish("worker.error",{workerName:worker.name,itemId:item.id,error:error93}),worker.queue.retry(item.id,error93)}}stop(name){let worker=this.workers.get(name);if(!worker)return!1;if(worker.status!=="running")return!1;return worker.status="stopping",this.eventBus.publish("worker.stopped",{workerName:name,processedCount:worker.processedCount,errorCount:worker.errorCount}),worker.status="stopped",!0}startAll(){for(let[name,worker]of this.workers)if(worker.status==="idle"||worker.status==="stopped")this.start(name)}stopAll(){for(let name of this.workers.keys())this.stop(name)}getStatus(name){return this.workers.get(name)?.status}getStats(name){let worker=this.workers.get(name);if(!worker)return;return{status:worker.status,activeCount:worker.activeCount,processedCount:worker.processedCount,errorCount:worker.errorCount,lastError:worker.lastError,queueSize:worker.queue.size()}}getWorkerNames(){return Array.from(this.workers.keys())}isAnyRunning(){for(let worker of this.workers.values())if(worker.status==="running")return!0;return!1}getTotalStats(){let stats2={};for(let name of this.workers.keys())stats2[name]=this.getStats(name);return stats2}}var init_worker=__esm(()=>{init_event_bus()});class BackgroundAutomationManager{config;eventBus;workerManager;queues=new Map;circuitBreakers=new Map;loopProtections=new Map;isInitialized=!1;isRunning=!1;constructor(config3){this.config={enabled:config3.enabled,maxQueueSize:config3.maxQueueSize??1000,maxRetries:config3.maxRetries??3,circuitBreaker:config3.circuitBreaker,loopProtection:config3.loopProtection},this.eventBus=getGlobalEventBus(),this.workerManager=new WorkerManager}initialize(){if(!this.config.enabled){log("[Automation] Framework disabled, skipping initialization");return}if(this.isInitialized){log("[Automation] Already initialized");return}log("[Automation] Initializing framework..."),this.isInitialized=!0,this.eventBus.publish("automation.started",{config:this.config})}start(){if(!this.config.enabled||!this.isInitialized)return;if(this.isRunning)return;log("[Automation] Starting framework..."),this.isRunning=!0,this.eventBus.publish("automation.started",{timestamp:Date.now()})}stop(){if(!this.isRunning)return;log("[Automation] Stopping framework..."),this.workerManager.stopAll(),this.isRunning=!1,this.eventBus.publish("automation.stopped",{timestamp:Date.now()})}isEnabled(){return this.config.enabled}isActive(){return this.isRunning}getOrCreateQueue(name){if(!this.queues.has(name)){let queue=new AutomationQueue({maxSize:this.config.maxQueueSize,defaultMaxRetries:this.config.maxRetries});this.queues.set(name,queue)}return this.queues.get(name)}registerWorker(registration){if(!this.config.enabled)throw Error("Cannot register worker: automation framework is disabled");this.workerManager.register(registration)}startWorker(name){if(!this.config.enabled)return!1;return this.workerManager.start(name)}stopWorker(name){if(!this.config.enabled)return!1;return this.workerManager.stop(name)}getOrCreateCircuitBreaker(name){if(!this.circuitBreakers.has(name)){let cb=new CircuitBreaker(name,this.config.circuitBreaker,(eventType,event)=>{log(`[CircuitBreaker] ${name}: ${eventType}`,event),this.eventBus.publish("circuit.breaker.opened",{breakerName:name,eventType,event})});this.circuitBreakers.set(name,cb)}return this.circuitBreakers.get(name)}getOrCreateLoopProtection(operationKey){if(!this.loopProtections.has(operationKey)){let config3={maxIterations:this.config.loopProtection?.maxIterations??10,timeWindowMs:this.config.loopProtection?.timeWindowMs??60000,operationKey},lp=new LoopProtection(config3,(key,count)=>{log(`[LoopProtection] ${key}: Detected potential loop (${count} iterations)`),this.eventBus.publish("loop.protection.triggered",{operationKey:key,count,timestamp:Date.now()})});this.loopProtections.set(operationKey,lp)}return this.loopProtections.get(operationKey)}subscribe(type,listener){return this.eventBus.subscribe(type,listener)}async publish(type,payload,source){await this.eventBus.publish(type,payload,source)}getStats(){return{enabled:this.config.enabled,initialized:this.isInitialized,running:this.isRunning,queues:Object.fromEntries(Array.from(this.queues.entries()).map(([name,queue])=>[name,queue.getStats()])),workers:this.workerManager.getTotalStats(),circuitBreakers:Object.fromEntries(Array.from(this.circuitBreakers.entries()).map(([name,cb])=>[name,cb.getStats()])),loopProtections:Array.from(this.loopProtections.keys())}}reset(){this.stop(),this.workerManager.stopAll(),this.queues.clear(),this.circuitBreakers.clear(),this.loopProtections.clear(),this.isInitialized=!1}}function createAutomationManager(automationConfig){let config3={enabled:automationConfig?.mode!=="manual",maxQueueSize:500,maxRetries:3,circuitBreaker:{failureThreshold:5,resetTimeoutMs:30000,successThreshold:2,callTimeoutMs:15000},loopProtection:{maxIterations:10,timeWindowMs:60000}},manager=new BackgroundAutomationManager(config3);return manager.initialize(),manager}function resetAutomationManager(){if(managerInstance)managerInstance.reset(),managerInstance=null}var managerInstance=null;var init_manager3=__esm(()=>{init_utils();init_event_bus();init_queue();init_worker()});import*as fs58 from"node:fs";import*as path114 from"node:path";async function handleResetCommand(directory,args2){if(!args2.includes("--confirm"))return["## Swarm Reset","","⚠️ This will delete all swarm state from .swarm/ (plan, context, checkpoints, SWARM_PLAN artifacts including .swarm/plan-export/)","","**Tip**: Run `/swarm export` first to backup your state.","","To confirm, run: `/swarm reset --confirm`"].join(`
1720
- `);let filesToReset=["plan.md","plan.json","context.md","SWARM_PLAN.md","SWARM_PLAN.json","plan-export/SWARM_PLAN.md","plan-export/SWARM_PLAN.json","checkpoints.json","events.jsonl"],results=[];for(let filename of filesToReset)try{let resolvedPath=validateSwarmPath(directory,filename);if(fs58.existsSync(resolvedPath))fs58.unlinkSync(resolvedPath),results.push(`- ✅ Deleted ${filename}`);else results.push(`- ⏭️ ${filename} not found (skipped)`)}catch{results.push(`- ❌ Failed to delete ${filename}`)}for(let filename of["SWARM_PLAN.md","SWARM_PLAN.json"])try{let rootPath=path114.join(directory,filename);if(fs58.existsSync(rootPath))fs58.unlinkSync(rootPath),results.push(`- ✅ Deleted ${filename} (root)`)}catch(err){results.push(`- ❌ Failed to delete ${filename}: ${err instanceof Error?err.message:String(err)}`)}try{resetAutomationManager(),results.push("- ✅ Stopped background automation (in-memory queues cleared)")}catch{results.push("- ⏭️ Background automation not running (skipped)")}try{let summariesPath=validateSwarmPath(directory,"summaries");if(fs58.existsSync(summariesPath))fs58.rmSync(summariesPath,{recursive:!0,force:!0}),results.push("- ✅ Deleted summaries/ directory");else results.push("- ⏭️ summaries/ not found (skipped)")}catch{results.push("- ❌ Failed to delete summaries/")}return["## Swarm Reset Complete","",...results,"","Swarm state has been cleared. Start fresh with a new plan."].join(`
1720
+ `);let filesToReset=["plan.md","plan.json","plan-ledger.jsonl","context.md","spec.md","spec-staleness.json","spec-snapshot.md","SWARM_PLAN.md","SWARM_PLAN.json","plan-export/SWARM_PLAN.md","plan-export/SWARM_PLAN.json","checkpoints.json","events.jsonl"],results=[];for(let filename of filesToReset)try{let resolvedPath=validateSwarmPath(directory,filename);if(fs58.existsSync(resolvedPath))fs58.unlinkSync(resolvedPath),results.push(`- ✅ Deleted ${filename}`);else results.push(`- ⏭️ ${filename} not found (skipped)`)}catch{results.push(`- ❌ Failed to delete ${filename}`)}for(let filename of["SWARM_PLAN.md","SWARM_PLAN.json"])try{let rootPath=path114.join(directory,filename);if(fs58.existsSync(rootPath))fs58.unlinkSync(rootPath),results.push(`- ✅ Deleted ${filename} (root)`)}catch(err){results.push(`- ❌ Failed to delete ${filename}: ${err instanceof Error?err.message:String(err)}`)}try{resetAutomationManager(),results.push("- ✅ Stopped background automation (in-memory queues cleared)")}catch{results.push("- ⏭️ Background automation not running (skipped)")}try{let summariesPath=validateSwarmPath(directory,"summaries");if(fs58.existsSync(summariesPath))fs58.rmSync(summariesPath,{recursive:!0,force:!0}),results.push("- ✅ Deleted summaries/ directory");else results.push("- ⏭️ summaries/ not found (skipped)")}catch{results.push("- ❌ Failed to delete summaries/")}return["## Swarm Reset Complete","",...results,"","Swarm state has been cleared. Start fresh with a new plan."].join(`
1721
1721
  `)}var init_reset=__esm(()=>{init_manager3();init_utils2()});import*as fs59 from"node:fs/promises";import*as path115 from"node:path";function isSensitiveKey(key){let lower=key.toLowerCase();return SENSITIVE_SUBSTRINGS.some((substr)=>lower.includes(substr))}async function truncateTrajectoryFile(filePath,maxLines){try{let lines=(await fs59.readFile(filePath,"utf-8")).split(`
1722
1722
  `).filter((line)=>line.trim().length>0);if(lines.length<=maxLines)return;let keepCount=Math.floor(maxLines/2),keptLines=lines.slice(-keepCount);await fs59.writeFile(filePath,`${keptLines.join(`
1723
1723
  `)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-swarm",
3
- "version": "7.114.2",
3
+ "version": "7.114.3",
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",