opencode-swarm 7.114.0 → 7.114.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/.opencode/skills/brainstorm/SKILL.md +10 -8
  2. package/.opencode/skills/ci-fix-monitor/SKILL.md +2 -2
  3. package/.opencode/skills/clarify/SKILL.md +2 -2
  4. package/.opencode/skills/clarify-spec/SKILL.md +4 -4
  5. package/.opencode/skills/commit-pr/SKILL.md +32 -20
  6. package/.opencode/skills/council/SKILL.md +1 -1
  7. package/.opencode/skills/deep-dive/SKILL.md +3 -3
  8. package/.opencode/skills/design-docs/SKILL.md +2 -1
  9. package/.opencode/skills/discover/SKILL.md +2 -2
  10. package/.opencode/skills/engineering-conventions/SKILL.md +54 -1
  11. package/.opencode/skills/gate-attribution/SKILL.md +11 -8
  12. package/.opencode/skills/issue-ingest/SKILL.md +18 -14
  13. package/.opencode/skills/loop/SKILL.md +3 -4
  14. package/.opencode/skills/merge-queue-readiness/SKILL.md +6 -13
  15. package/.opencode/skills/phase-wrap/SKILL.md +30 -28
  16. package/.opencode/skills/plan/SKILL.md +8 -7
  17. package/.opencode/skills/resume/SKILL.md +5 -5
  18. package/.opencode/skills/running-tests/SKILL.md +3 -4
  19. package/.opencode/skills/specify/SKILL.md +2 -1
  20. package/.opencode/skills/swarm/SKILL.md +8 -0
  21. package/.opencode/skills/swarm-ci-monitor/SKILL.md +4 -4
  22. package/.opencode/skills/swarm-pr-feedback/SKILL.md +55 -38
  23. package/.opencode/skills/swarm-pr-subscribe/SKILL.md +2 -0
  24. package/.opencode/skills/test-file-split/SKILL.md +2 -4
  25. package/.opencode/skills/writing-tests/SKILL.md +97 -27
  26. package/README.md +2 -2
  27. package/dist/cli/{curator-llm-factory-awp6xgvt.js → curator-llm-factory-26pyy8cq.js} +1 -1
  28. package/dist/cli/{curator-wvv628sv.js → curator-wwyj379g.js} +1 -1
  29. package/dist/cli/{guardrail-explain-hhdtrm60.js → guardrail-explain-qzg7rr7f.js} +2 -2
  30. package/dist/cli/{hive-promoter-1qkybw79.js → hive-promoter-kfjbydfj.js} +1 -1
  31. package/dist/cli/{index-jhdv0jdf.js → index-2aszzcyk.js} +1 -1
  32. package/dist/cli/{index-zezjy05g.js → index-8phvk4v4.js} +16 -20
  33. package/dist/cli/{index-p35ayncy.js → index-gge9vh5s.js} +2 -2
  34. package/dist/cli/index.js +1 -1
  35. package/dist/commands/council.d.ts +0 -1
  36. package/dist/commands/registry.d.ts +3 -3
  37. package/dist/index.js +15 -11
  38. package/dist/tools/test-runner.d.ts +0 -1
  39. package/package.json +1 -3
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.0",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/swarm",".opencode/skills/swarm-ci-monitor",".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.1",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
 
@@ -1398,7 +1398,7 @@ Flags:
1398
1398
  `)}catch(err){return["Skill consolidation encountered an error.","",`Error: ${err instanceof Error?err.message:String(err)}`].join(`
1399
1399
  `)}}var init_consolidate=__esm(()=>{init_config();init_schema();init_skill_consolidation()});async function handleCostsCommand(directory,args2){let summary=summarizeTelemetryCosts(directory);if(args2.includes("--json"))return["[COSTS_JSON]",JSON.stringify(summary,null,2),"[/COSTS_JSON]"].join(`
1400
1400
  `);return renderCostSummary(summary)}function renderCostSummary(summary){let lines=["## Swarm Costs","",`Total tracked cost: ${formatUsd(summary.total_cost_usd)}`,`Delegations: ${summary.delegations}`,`Tokens: input ${summary.total_input_tokens.toLocaleString()}, output ${summary.total_output_tokens.toLocaleString()}, reasoning ${summary.total_reasoning_tokens.toLocaleString()}, cache ${summary.total_cache_tokens.toLocaleString()}`,`Cost source: reported ${formatUsd(summary.total_reported_usd)}, estimated ${formatUsd(summary.total_estimated_usd)}, unavailable ${summary.unavailable_delegations}`,"","### By Agent"];return appendCostRows(lines,"Agent",summary.by_agent,"No delegation cost telemetry recorded."),lines.push("","### By Task"),appendCostRows(lines,"Task",summary.by_task,"No task cost telemetry recorded."),lines.push("","### By Gate"),appendCostRows(lines,"Gate",summary.by_gate,"No gate cost telemetry recorded."),lines.push("","### By Retry Loop"),appendCostRows(lines,"Retry",summary.by_retry,"No retry-loop cost telemetry recorded."),lines.join(`
1401
- `)}function appendCostRows(lines,label,rows,emptyMessage){if(rows.length===0){lines.push(emptyMessage);return}lines.push(`| ${label} | Delegations | Cost | Input | Output | Reasoning | Cache | Unavailable |`,"|------|-------------|------|-------|--------|-----------|-------|-------------|");for(let row of rows)lines.push(`| ${row.name} | ${row.delegations} | ${formatUsd(row.cost_usd)} | ${row.input_tokens.toLocaleString()} | ${row.output_tokens.toLocaleString()} | ${row.reasoning_tokens.toLocaleString()} | ${row.cache_tokens.toLocaleString()} | ${row.unavailable_delegations} |`)}function formatUsd(value){return`$${value.toFixed(6)}`}var init_costs=__esm(()=>{init_cost_accounting()});function sanitizeQuestion(raw){let normalized=raw.replace(/\s+/g," ").trim().replace(/\[\s*MODE\s*:[^\]]*\]/gi,"").replace(/\s+/g," ").trim();if(normalized.length<=2000)return normalized;return`${normalized.slice(0,2000)}…`}function sanitizePresetName(raw){let trimmed=raw.trim();if(!trimmed)return null;if(trimmed.length>64)return null;if(!/^[A-Za-z0-9_-]+$/.test(trimmed))return null;return trimmed}function parseArgs2(args2){let out={specReview:!1,rest:[]};for(let i=0;i<args2.length;i++){let token=args2[i];if(token==="--spec-review"){out.specReview=!0;continue}if(token==="--preset"){let next=args2[i+1];if(next!==void 0){let sanitized=sanitizePresetName(next);if(sanitized)out.preset=sanitized;i++}continue}out.rest.push(token)}return out}async function handleCouncilCommand(_directory,args2){let parsed=parseArgs2(args2),question=sanitizeQuestion(parsed.rest.join(" "));if(!question)return USAGE;let tokens=["MODE: COUNCIL"];if(parsed.preset)tokens.push(`preset=${parsed.preset}`);if(parsed.specReview)tokens.push("spec_review");return`[${tokens.join(" ")}] ${question}`}var USAGE;var init_council=__esm(()=>{USAGE=["Usage: /swarm council <question> [--preset <name>] [--spec-review]",""," question The question to put to the council"," --preset <name> Use a named member preset from council.general.presets"," --spec-review Use spec_review mode (single advisory pass on a draft spec)","","Requires council.general.enabled: true and a configured search API key in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides."].join(`
1401
+ `)}function appendCostRows(lines,label,rows,emptyMessage){if(rows.length===0){lines.push(emptyMessage);return}lines.push(`| ${label} | Delegations | Cost | Input | Output | Reasoning | Cache | Unavailable |`,"|------|-------------|------|-------|--------|-----------|-------|-------------|");for(let row of rows)lines.push(`| ${row.name} | ${row.delegations} | ${formatUsd(row.cost_usd)} | ${row.input_tokens.toLocaleString()} | ${row.output_tokens.toLocaleString()} | ${row.reasoning_tokens.toLocaleString()} | ${row.cache_tokens.toLocaleString()} | ${row.unavailable_delegations} |`)}function formatUsd(value){return`$${value.toFixed(6)}`}var init_costs=__esm(()=>{init_cost_accounting()});function sanitizeQuestion(raw){let normalized=raw.replace(/\s+/g," ").trim().replace(/\[\s*MODE\s*:[^\]]*\]/gi,"").replace(/\s+/g," ").trim();if(normalized.length<=2000)return normalized;return`${normalized.slice(0,2000)}…`}function sanitizePresetName(raw){let trimmed=raw.trim();if(!trimmed)return null;if(trimmed.length>64)return null;if(!/^[A-Za-z0-9_-]+$/.test(trimmed))return null;return trimmed}function parseArgs2(args2){let out={specReview:!1,rest:[]};for(let i=0;i<args2.length;i++){let token=args2[i];if(token==="--spec-review"){out.specReview=!0;continue}if(token==="--preset"){let next=args2[i+1];if(next!==void 0){let sanitized=sanitizePresetName(next);if(sanitized)out.preset=sanitized;i++}continue}out.rest.push(token)}return out}async function handleCouncilCommand(_directory,args2){let parsed=parseArgs2(args2),question=sanitizeQuestion(parsed.rest.join(" "));if(!question)return USAGE;let tokens=["MODE: COUNCIL"];if(parsed.preset)tokens.push(`preset=${parsed.preset}`);if(parsed.specReview)tokens.push("spec_review");return`[${tokens.join(" ")}] ${question}`}var USAGE;var init_council=__esm(()=>{USAGE=["Usage: /swarm council <question> [--spec-review]",""," question The question to put to the council"," --spec-review Use spec_review mode (single advisory pass on a draft spec)","","Requires council.general.enabled: true and a configured search API key in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides."].join(`
1402
1402
  `)});import*as child_process5 from"node:child_process";import{randomUUID as randomUUID8}from"node:crypto";import{readdir as readdir5,readFile as readFile21,stat as stat10}from"node:fs/promises";import*as path79 from"node:path";import{promisify}from"node:util";function getExecFileAsync(){return promisify(child_process5.execFile)}async function parseGitLog(directory,maxCommits){let commitMap=new Map;try{let{stdout}=await getExecFileAsync()("git",["log","--name-only","--pretty=format:COMMIT:%H","--no-merges",`-n${maxCommits}`],{cwd:directory,timeout:1e4}),currentCommit=null;for(let line of stdout.split(`
1403
1403
  `))if(line.startsWith("COMMIT:")){if(currentCommit=line.slice(7),currentCommit&&!commitMap.has(currentCommit))commitMap.set(currentCommit,new Set)}else if(currentCommit&&line.trim()){let filePath=line.trim();if(filePath.startsWith(".swarm/")||filePath.startsWith("node_modules/")||filePath==="")continue;commitMap.get(currentCommit).add(filePath)}}catch{return new Map}return commitMap}function buildCoChangeMatrix(commitMap,maxFilesPerCommit=500){let matrix=new Map,fileCommitCount=new Map;for(let files of commitMap.values()){for(let file3 of files)fileCommitCount.set(file3,(fileCommitCount.get(file3)||0)+1);if(files.size>maxFilesPerCommit)continue;let fileArray=Array.from(files).sort();for(let i=0;i<fileArray.length;i++)for(let j=i+1;j<fileArray.length;j++){let fileA=fileArray[i],fileB=fileArray[j],[key,a,b]=fileA<fileB?[`${fileA}::${fileB}`,fileA,fileB]:[`${fileB}::${fileA}`,fileB,fileA],existing=matrix.get(key);if(existing)existing.coChangeCount++;else matrix.set(key,{fileA:a,fileB:b,coChangeCount:1,npmi:0,lift:0,hasStaticEdge:!1,totalCommits:0,commitsA:0,commitsB:0})}}let totalCommits=commitMap.size;for(let entry of matrix.values()){if(entry.coChangeCount<3)continue;let pAB=entry.coChangeCount/totalCommits,pA=(fileCommitCount.get(entry.fileA)||0)/totalCommits,pB=(fileCommitCount.get(entry.fileB)||0)/totalCommits;if(entry.commitsA=fileCommitCount.get(entry.fileA)||0,entry.commitsB=fileCommitCount.get(entry.fileB)||0,entry.totalCommits=totalCommits,pA>0&&pB>0)entry.lift=pAB/(pA*pB);if(pAB>0){let logPAB=Math.log(pAB),negLogPAB=-logPAB;if(negLogPAB>0){let numerator=logPAB-Math.log(pA*pB);entry.npmi=numerator/negLogPAB,entry.npmi=Math.max(-1,Math.min(1,entry.npmi))}else entry.npmi=1}}return matrix}async function scanSourceFiles(dir){let results=[],skipDirs=new Set(["node_modules",".swarm","dist","build"]);try{let entries=await readdir5(dir,{withFileTypes:!0});for(let entry of entries){let fullPath=path79.join(dir,entry.name);if(entry.isDirectory()){if(skipDirs.has(entry.name))continue;let subFiles=await scanSourceFiles(fullPath);results.push(...subFiles)}else if(entry.isFile()){let ext=path79.extname(entry.name);if([".ts",".tsx",".js",".jsx",".mjs"].includes(ext))results.push(fullPath)}}}catch{}return results}async function getStaticEdges(directory){let edges=new Set,sourceFiles=await scanSourceFiles(directory);for(let sourceFile of sourceFiles)try{let content=await readFile21(sourceFile,"utf-8"),importRegex=/(?:import|require)\s*(?:\(?\s*['"`]|.*?from\s+['"`])([^'"`]+)['"`]/g;for(let match=importRegex.exec(content);match!==null;match=importRegex.exec(content)){let importPath=match[1].trim();if(!importPath.startsWith("."))continue;try{let sourceDir=path79.dirname(sourceFile),resolvedPath=path79.resolve(sourceDir,importPath),extensions=["",".ts",".tsx",".js",".jsx",".mjs","/index.ts","/index.js"],targetFile=null;for(let ext of extensions){let testPath=resolvedPath+ext;try{if((await stat10(testPath)).isFile()){targetFile=testPath;break}}catch{}}if(!targetFile)continue;let relSource=path79.relative(directory,sourceFile).replace(/\\/g,"/"),relTarget=path79.relative(directory,targetFile).replace(/\\/g,"/"),[key]=relSource<relTarget?[`${relSource}::${relTarget}`,relSource,relTarget]:[`${relTarget}::${relSource}`,relTarget,relSource];edges.add(key)}catch{}}}catch{}return edges}function isTestImplementationPair(fileA,fileB){let testPatterns=[".test.ts",".test.js",".spec.ts",".spec.js"],getBaseName=(filePath)=>{let base=path79.basename(filePath);for(let pattern of testPatterns)if(base.endsWith(pattern))return base.slice(0,-pattern.length);return base.replace(/\.(ts|js|tsx|jsx|mjs)$/,"")},baseA=getBaseName(fileA),baseB=getBaseName(fileB);return baseA===baseB&&baseA!==path79.basename(fileA)&&baseA!==path79.basename(fileB)}function hasSharedPrefix(fileA,fileB){let dirA=path79.dirname(fileA),dirB=path79.dirname(fileB);if(dirA!==dirB)return!1;let baseA=path79.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/,""),baseB=path79.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/,"");if(baseA.startsWith(baseB)||baseB.startsWith(baseA))return!0;let splitA=baseA.split(/-|_/),splitB=baseB.split(/-|_/);if(splitA.length>0&&splitB.length>0&&splitA[0]===splitB[0])return!0;return!1}async function detectDarkMatter(directory,options){let minCommits=options?.minCommits??20,minCoChanges=options?.minCoChanges??3,npmiThreshold=options?.npmiThreshold??0.5,maxCommitsToAnalyze=options?.maxCommitsToAnalyze??500,maxFilesPerCommit=options?.maxFilesPerCommit??500;try{let{stdout}=await getExecFileAsync()("git",["rev-list","--count","HEAD"],{cwd:directory,timeout:1e4}),totalCommitCount=parseInt(stdout.trim(),10);if(Number.isNaN(totalCommitCount)||totalCommitCount<minCommits)return[]}catch{return[]}let commitMap=await _internals47.parseGitLog(directory,maxCommitsToAnalyze),matrix=_internals47.buildCoChangeMatrix(commitMap,maxFilesPerCommit),staticEdges=await _internals47.getStaticEdges(directory),results=[];for(let entry of matrix.values()){let key=`${entry.fileA}::${entry.fileB}`;if(entry.hasStaticEdge=staticEdges.has(key),entry.coChangeCount<minCoChanges)continue;if(entry.npmi<npmiThreshold)continue;if(entry.hasStaticEdge)continue;if(isTestImplementationPair(entry.fileA,entry.fileB))continue;if(hasSharedPrefix(entry.fileA,entry.fileB))continue;results.push(entry)}return results.sort((a,b)=>b.npmi-a.npmi),results.slice(0,20)}function darkMatterToKnowledgeEntries(pairs,projectName){let entries=[],now=new Date().toISOString();for(let pair of pairs.slice(0,10)){let baseA=path79.basename(pair.fileA),baseB=path79.basename(pair.fileB),lesson=`Files ${pair.fileA} and ${pair.fileB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern — changes to one likely require changes to the other.`;if(lesson.length>280)lesson=`Files ${baseA} and ${baseB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern — changes to one likely require changes to the other.`;if(lesson.length>280)lesson=`Files ${baseA} and ${baseB} co-change frequently (NPMI=${pair.npmi.toFixed(3)}) without import relationship. This hidden coupling suggests a shared architectural concern.`;if(lesson.length>280)lesson=`Hidden coupling: ${baseA.slice(0,50)}... ↔ ${baseB.slice(0,50)}... (NPMI=${pair.npmi.toFixed(3)})`;let confidence=Math.min(0.3+0.2*Math.min(pair.coChangeCount/10,1),0.5);entries.push({id:randomUUID8(),tier:"swarm",lesson,category:"architecture",tags:["hidden-coupling","co-change","dark-matter"],scope:"global",confidence,status:"candidate",confirmed_by:[],retrieval_outcomes:{applied_count:0,succeeded_after_count:0,failed_after_count:0},schema_version:1,created_at:now,updated_at:now,auto_generated:!0,project_name:projectName,applies_to_agents:["coder","reviewer"],required_actions:[`when modifying ${baseA}, check whether ${baseB} needs a matching change (and vice versa)`.slice(0,200)],verification_checks:[`coupled file ${baseB} was considered when ${baseA} changed`.slice(0,200)],triggers:[baseA,baseB].map((t)=>t.slice(0,80))})}return entries}function formatDarkMatterOutput(pairs){if(pairs.length===0)return`## Dark Matter: Hidden Couplings
1404
1404
 
@@ -1605,7 +1605,7 @@ ${markdown}`}}var HANDOFF_SOURCE_SESSION_PREFIX="<!-- opencode-swarm-handoff-sou
1605
1605
 
1606
1606
  ${USAGE3}`;let issueUrl=`https://github.com/${issueInfo.owner}/${issueInfo.repo}/issues/${issueInfo.number}`,result=validateAndSanitizeUrl(issueUrl);if("error"in result)return`Error: ${result.error}
1607
1607
 
1608
- ${USAGE3}`;let flags=[];if(parsed.plan)flags.push("plan=true");if(parsed.trace)flags.push("trace=true");if(parsed.noRepro)flags.push("noRepro=true");let flagsStr=flags.length>0?` ${flags.join(" ")}`:"";return`[MODE: ISSUE_INGEST issue="${result.sanitized}"${flagsStr}]`}var USAGE3;var init_issue=__esm(()=>{init_url_security();USAGE3=["Usage: /swarm issue <url|owner/repo#N|N> [--plan] [--trace] [--no-repro]","","Ingest a GitHub issue into the swarm workflow."," /swarm issue https://github.com/owner/repo/issues/42"," /swarm issue owner/repo#42"," /swarm issue 42 --plan"," /swarm issue 42 --trace --no-repro","","Flags:"," --plan Transition to plan creation after spec generation"," --trace Run full fix-and-PR workflow (implies --plan)"," --no-repro Skip reproduction step"].join(`
1608
+ ${USAGE3}`;let flags=[];if(parsed.plan)flags.push("plan=true");if(parsed.trace)flags.push("trace=true");if(parsed.noRepro)flags.push("noRepro=true");let flagsStr=flags.length>0?` ${flags.join(" ")}`:"";return`[MODE: ISSUE_INGEST issue="${result.sanitized}"${flagsStr}]`}var USAGE3;var init_issue=__esm(()=>{init_url_security();USAGE3=["Usage: /swarm issue <url|owner/repo#N|N> [--plan] [--trace] [--no-repro]","","Ingest a GitHub issue into the swarm workflow."," /swarm issue https://github.com/owner/repo/issues/42"," /swarm issue owner/repo#42"," /swarm issue 42 --plan"," /swarm issue 42 --trace --no-repro","","Flags:"," --plan Transition to plan creation after spec generation"," --trace Run the fix workflow end-to-end (implies --plan); compose commit-pr to publish."," --no-repro Skip reproduction step"].join(`
1609
1609
  `)});import{randomUUID as randomUUID9}from"node:crypto";import{existsSync as existsSync51,readFileSync as readFileSync31}from"node:fs";import{mkdir as mkdir20,readFile as readFile23,writeFile as writeFile18}from"node:fs/promises";import*as os20 from"node:os";import*as path91 from"node:path";async function migrateKnowledgeToExternal(_directory,_config){let externalSentinelPath=path91.join(_directory,".swarm",".knowledge-external-migrated"),contextPath=path91.join(_directory,".swarm","context.md");if(_internals60.existsSync(externalSentinelPath))return{migrated:!1,entriesMigrated:0,entriesDropped:0,entriesTotal:0,skippedReason:"external-sentinel-exists"};if(!_internals60.existsSync(contextPath))return{migrated:!1,entriesMigrated:0,entriesDropped:0,entriesTotal:0,skippedReason:"no-context-file"};let contextContent=await _internals60.readFile(contextPath,"utf-8");if(contextContent.trim().length===0)return{migrated:!1,entriesMigrated:0,entriesDropped:0,entriesTotal:0,skippedReason:"empty-context"};let lines=contextContent.split(`
1610
1610
  `),entriesCount=0;for(let line of lines)if(line.trimStart().startsWith("- "))entriesCount++;return await _internals60.writeSentinel(externalSentinelPath,entriesCount,entriesCount),{migrated:!0,entriesMigrated:entriesCount,entriesDropped:0,entriesTotal:entriesCount}}async function migrateContextToKnowledge(directory,config3){let sentinelPath=path91.join(directory,".swarm",".knowledge-migrated"),contextPath=path91.join(directory,".swarm","context.md"),knowledgePath=resolveSwarmKnowledgePath(directory);if(existsSync51(sentinelPath))return{migrated:!1,entriesMigrated:0,entriesDropped:0,entriesTotal:0,skippedReason:"sentinel-exists"};if(!existsSync51(contextPath))return{migrated:!1,entriesMigrated:0,entriesDropped:0,entriesTotal:0,skippedReason:"no-context-file"};let contextContent=await readFile23(contextPath,"utf-8");if(contextContent.trim().length===0)return{migrated:!1,entriesMigrated:0,entriesDropped:0,entriesTotal:0,skippedReason:"empty-context"};let rawEntries=_internals60.parseContextMd(contextContent);if(rawEntries.length===0)return await _internals60.writeSentinel(sentinelPath,0,0),{migrated:!0,entriesMigrated:0,entriesDropped:0,entriesTotal:0};let existing=await readKnowledge(knowledgePath),migrated=0,dropped=0,projectName=_internals60.inferProjectName(directory);for(let raw of rawEntries){if(config3.validation_enabled!==!1){let category=raw.categoryHint??_internals60.inferCategoryFromText(raw.text);if(!validateLesson(raw.text,existing.map((e)=>e.lesson),{category,scope:"global",confidence:0.3}).valid){dropped++;continue}}if(findNearDuplicate(raw.text,existing,config3.dedup_threshold??0.6)){dropped++;continue}let inferredTags=inferTags2(raw.text),entry={id:randomUUID9(),tier:"swarm",lesson:_internals60.truncateLesson(raw.text),category:raw.categoryHint??_internals60.inferCategoryFromText(raw.text),tags:[...inferredTags,`migration:${raw.sourceSection}`],scope:"global",confidence:0.3,status:"candidate",confirmed_by:[],retrieval_outcomes:{applied_count:0,succeeded_after_count:0,failed_after_count:0},schema_version:config3.schema_version??KNOWLEDGE_SCHEMA_VERSION,created_at:new Date().toISOString(),updated_at:new Date().toISOString(),project_name:projectName,auto_generated:!0};existing.push(entry),migrated++}if(migrated>0)await rewriteKnowledge(knowledgePath,existing);return await _internals60.writeSentinel(sentinelPath,migrated,dropped),log(`[knowledge-migrator] Migrated ${migrated} entries, dropped ${dropped}`),{migrated:!0,entriesMigrated:migrated,entriesDropped:dropped,entriesTotal:rawEntries.length}}async function migrateHiveKnowledgeLegacy(config3){let legacyHivePath=_internals60.resolveLegacyHiveKnowledgePath(),canonicalHivePath=resolveHiveKnowledgePath(),sentinelPath=path91.join(path91.dirname(canonicalHivePath),".hive-knowledge-migrated");if(existsSync51(sentinelPath))return{migrated:!1,entriesMigrated:0,entriesDropped:0,entriesTotal:0,skippedReason:"sentinel-exists"};if(!existsSync51(legacyHivePath))return{migrated:!1,entriesMigrated:0,entriesDropped:0,entriesTotal:0,skippedReason:"no-context-file"};let legacyEntries=await readKnowledge(legacyHivePath);if(legacyEntries.length===0)return await _internals60.writeSentinel(sentinelPath,0,0),{migrated:!0,entriesMigrated:0,entriesDropped:0,entriesTotal:0};let existingHiveEntries=await readKnowledge(canonicalHivePath),migrated=0,dropped=0,entryErrors=[];for(let legacyEntry of legacyEntries)try{let lesson=legacyEntry.lesson;if(!lesson||typeof lesson!=="string"||lesson.length<15){dropped++;continue}if(findNearDuplicate(lesson,existingHiveEntries,config3.dedup_threshold??0.6)){dropped++;continue}let category=legacyEntry.category||"process",validationResult=validateLesson(lesson,existingHiveEntries.map((e)=>e.lesson),{category,scope:"global",confidence:0.3});if(!validationResult.valid){let errorMsg=`Validation failed for legacy entry: ${validationResult.reason}`;entryErrors.push(errorMsg),warn(`[knowledge-migrator] ${errorMsg}`),dropped++;continue}let confidence=legacyEntry.confidence??0.8,scopeTag=legacyEntry.scope_tag||"global",legacyId=legacyEntry.id,existingIds=new Set(existingHiveEntries.map((e)=>e.id)),resolvedId=legacyId&&existingIds.has(legacyId)?randomUUID9():legacyId||randomUUID9();if(legacyId&&existingIds.has(legacyId))warn(`[knowledge-migrator] Legacy entry ID collision for "${legacyId}", generating new UUID`);let newHiveEntry={id:resolvedId,tier:"hive",lesson:_internals60.truncateLesson(lesson),category,tags:["migration:legacy-hive"],scope:scopeTag,confidence:Math.min(Math.max(confidence,0),1),status:"established",confirmed_by:[],retrieval_outcomes:{applied_count:0,succeeded_after_count:0,failed_after_count:0},schema_version:KNOWLEDGE_SCHEMA_VERSION,created_at:legacyEntry.created_at||new Date().toISOString(),updated_at:legacyEntry.updated_at||new Date().toISOString(),source_project:"legacy-promotion",encounter_score:1};try{await _internals60.appendKnowledge(canonicalHivePath,newHiveEntry),existingHiveEntries.push(newHiveEntry),migrated++}catch(appendError){let errorMsg=`Failed to append entry: ${appendError instanceof Error?appendError.message:String(appendError)}`;entryErrors.push(errorMsg),warn(`[knowledge-migrator] ${errorMsg}`),dropped++}}catch(entryError){let errorMsg=`Unexpected error processing legacy entry: ${entryError instanceof Error?entryError.message:String(entryError)}`;entryErrors.push(errorMsg),warn(`[knowledge-migrator] ${errorMsg}`),dropped++}return await _internals60.writeSentinel(sentinelPath,migrated,dropped),log(`[knowledge-migrator] Migrated ${migrated} legacy hive entries, dropped ${dropped}`),{migrated:!0,entriesMigrated:migrated,entriesDropped:dropped,entriesTotal:legacyEntries.length,...entryErrors.length>0&&{entryErrors}}}function parseContextMd(content){let sections=_internals60.splitIntoSections(content),entries=[],seen=new Set,sectionPatterns=[{pattern:/^#{1,3}\s+lessons?\s+learned/i,sourceSection:"lessons-learned"},{pattern:/^#{1,3}\s+patterns?/i,sourceSection:"patterns"},{pattern:/^#{1,3}\s+sme\s+cache/i,sourceSection:"sme-cache"},{pattern:/^#{1,3}\s+decisions?/i,sourceSection:"decisions"}];for(let section of sections){let match=sectionPatterns.find((sp)=>sp.pattern.test(section.heading));if(!match)continue;let bullets=_internals60.extractBullets(section.body);for(let bullet of bullets){if(bullet.length<15)continue;let normalized=normalize5(bullet);if(seen.has(normalized))continue;seen.add(normalized),entries.push({text:_internals60.truncateLesson(bullet),sourceSection:match.sourceSection,categoryHint:_internals60.inferCategoryFromText(bullet)})}}return entries}function splitIntoSections(content){let sections=[],headingRegex=/^(#{1,3})\s+(.+)/gm,matches=[],match=headingRegex.exec(content);while(match!==null)matches.push({index:match.index,heading:match[0]}),match=headingRegex.exec(content);for(let i=0;i<matches.length;i++){let current=matches[i],next=matches[i+1],bodyStart=current.index+current.heading.length,bodyEnd=next?next.index:content.length,body=content.slice(bodyStart,bodyEnd).trim();sections.push({heading:current.heading,body})}return sections}function extractBullets(body){let bullets=[],bulletRegex=/^\s*[-*]\s+(.+)/;for(let line of body.split(`
1611
1611
  `)){let match=line.match(bulletRegex);if(match)bullets.push(match[1].trim())}return bullets}function inferCategoryFromText(text){let lower=text.toLowerCase();if(/\b(?:test|spec|vitest|jest)\b/.test(lower))return"testing";if(/\b(?:security|auth|token|password|encrypt)\b/.test(lower))return"security";if(/\b(?:performance|latency|cache|throughput)\b/.test(lower))return"performance";if(/\b(?:architecture|design|pattern|structure)\b/.test(lower))return"architecture";if(/\b(?:debug|error|fix|bug|issue)\b/.test(lower))return"debugging";if(/\b(?:tool|config|setup|install|build)\b/.test(lower))return"tooling";if(/\b(?:integrate|api|hook|connect)\b/.test(lower))return"integration";if(/\b(?:process|workflow|step|approach)\b/.test(lower))return"process";return"other"}function truncateLesson2(text){if(text.length<=280)return text;return`${text.slice(0,277)}...`}function inferProjectName(directory){let packageJsonPath=path91.join(directory,"package.json");if(existsSync51(packageJsonPath))try{let pkg=JSON.parse(readFileSync31(packageJsonPath,"utf-8"));if(pkg.name&&typeof pkg.name==="string")return pkg.name}catch{}return path91.basename(directory)}async function writeSentinel(sentinelPath,migrated,dropped){let sentinel={migrated_at:new Date().toISOString(),source_version:"6.16",target_version:"6.17",entries_migrated:migrated,entries_dropped:dropped,schema_version:1,migration_tool:"knowledge-migrator.ts"};await _internals60.mkdir(path91.dirname(sentinelPath),{recursive:!0}),await _internals60.writeFile(sentinelPath,JSON.stringify(sentinel,null,2),"utf-8")}function resolveLegacyHiveKnowledgePath(){let platform=process.platform,home=process.env.HOME||os20.homedir(),dataDir;if(platform==="win32")dataDir=path91.join(process.env.LOCALAPPDATA||path91.join(home,"AppData","Local"),"opencode-swarm","Data");else if(platform==="darwin")dataDir=path91.join(home,"Library","Application Support","opencode-swarm");else dataDir=path91.join(process.env.XDG_DATA_HOME||path91.join(home,".local","share"),"opencode-swarm");return path91.join(dataDir,"hive-knowledge.jsonl")}var _internals60;var init_knowledge_migrator=__esm(()=>{init_logger();init_knowledge_store();init_knowledge_types();init_knowledge_validator();_internals60={appendKnowledge,migrateContextToKnowledge,migrateKnowledgeToExternal,migrateHiveKnowledgeLegacy,parseContextMd,splitIntoSections,extractBullets,inferCategoryFromText,truncateLesson:truncateLesson2,inferProjectName,writeSentinel,resolveLegacyHiveKnowledgePath,existsSync:existsSync51,readFileSync:readFileSync31,readFile:readFile23,mkdir:mkdir20,writeFile:writeFile18}});import{join as join73}from"node:path";function resolveEntryByPrefix(entries,inputId){let exact=entries.find((e)=>e.id===inputId);if(exact)return{entry:exact};let matches=entries.filter((e)=>e.id.startsWith(inputId));if(matches.length===0)return{error:`No entry found matching '${inputId}'.`};if(matches.length===1)return{entry:matches[0]};let candidates=matches.map((e)=>e.id).join(`
@@ -1709,7 +1709,7 @@ ${stackPrefix}`;return INFRASTRUCTURE_FAILURE_PATTERNS.some((pattern)=>pattern.t
1709
1709
  `)){let trimmed=line.trim();if(!trimmed.startsWith("{")||!trimmed.endsWith("}"))continue;try{let parsed=JSON.parse(trimmed),testResults=parseJestLikeJsonTestResults(parsed);if(testResults.length>0)return testResults}catch{}}if(framework==="bun")return parseBunJsonLines(output);return[]}function parseTestOutput2(framework,output){let totals={passed:0,failed:0,skipped:0,total:0},coveragePercent;switch(framework){case"vitest":case"jest":case"bun":{let jsonMatch=output.match(/\{[\s\S]*"testResults"[\s\S]*\}/);if(jsonMatch)try{let parsed=JSON.parse(jsonMatch[0]);if(parsed.numTotalTests!==void 0)totals.passed=parsed.numPassedTests||0,totals.failed=parsed.numFailedTests||0,totals.skipped=parsed.numPendingTests||0,totals.total=parsed.numTotalTests||0;if(parsed.coverage!==void 0)coveragePercent=parsed.coverage}catch{}if(totals.total===0){let passMatch=output.match(/(\d+)\s+pass(ing|ed)?/),failMatch=output.match(/(\d+)\s+fail(ing|ed)?/),skipMatch=output.match(/(\d+)\s+skip(ping|ped)?/);if(passMatch)totals.passed=parseInt(passMatch[1],10);if(failMatch)totals.failed=parseInt(failMatch[1],10);if(skipMatch)totals.skipped=parseInt(skipMatch[1],10);totals.total=totals.passed+totals.failed+totals.skipped}let coverageMatch=output.match(/All files[^\d]*(\d+\.?\d*)\s*%/);if(!coveragePercent&&coverageMatch)coveragePercent=parseFloat(coverageMatch[1]);break}case"mocha":{let passMatch=output.match(/(\d+)\s+passing/),failMatch=output.match(/(\d+)\s+failing/),pendingMatch=output.match(/(\d+)\s+pending/);if(passMatch)totals.passed=parseInt(passMatch[1],10);if(failMatch)totals.failed=parseInt(failMatch[1],10);if(pendingMatch)totals.skipped=parseInt(pendingMatch[1],10);totals.total=totals.passed+totals.failed+totals.skipped;break}case"pytest":{let passMatch=output.match(/(\d+)\s+passed/),failMatch=output.match(/(\d+)\s+failed/),skipMatch=output.match(/(\d+)\s+skipped/);if(passMatch)totals.passed=parseInt(passMatch[1],10);if(failMatch)totals.failed=parseInt(failMatch[1],10);if(skipMatch)totals.skipped=parseInt(skipMatch[1],10);totals.total=totals.passed+totals.failed+totals.skipped;let coverageMatch=output.match(/TOTAL\s+(\d+\.?\d*)\s*%/);if(coverageMatch)coveragePercent=parseFloat(coverageMatch[1]);break}case"cargo":{let passMatch=output.match(/test result: ok\. (\d+) passed/),failMatch=output.match(/test result: FAILED\. (\d+) passed; (\d+) failed/);if(failMatch)totals.passed=parseInt(failMatch[1],10),totals.failed=parseInt(failMatch[2],10);else if(passMatch)totals.passed=parseInt(passMatch[1],10);totals.total=totals.passed+totals.failed;break}case"pester":{let passMatch=output.match(/Passed:\s*(\d+)/),failMatch=output.match(/Failed:\s*(\d+)/),skipMatch=output.match(/Skipped:\s*(\d+)/);if(passMatch)totals.passed=parseInt(passMatch[1],10);if(failMatch)totals.failed=parseInt(failMatch[1],10);if(skipMatch)totals.skipped=parseInt(skipMatch[1],10);totals.total=totals.passed+totals.failed+totals.skipped;break}case"go-test":{let passMatches=[...output.matchAll(/--- PASS:/g)],failMatches=[...output.matchAll(/--- FAIL:/g)],skipMatches=[...output.matchAll(/--- SKIP:/g)];totals.passed=passMatches.length,totals.failed=failMatches.length,totals.skipped=skipMatches.length,totals.total=totals.passed+totals.failed+totals.skipped;let covMatch=output.match(/coverage:\s*(\d+\.?\d*)\s*%/);if(covMatch)coveragePercent=parseFloat(covMatch[1]);break}case"maven":{let mavenMatch=output.match(/Tests run:\s*(\d+),\s*Failures:\s*(\d+),\s*Errors:\s*(\d+),\s*Skipped:\s*(\d+)/);if(mavenMatch){let total=parseInt(mavenMatch[1],10),failures=parseInt(mavenMatch[2],10),errors5=parseInt(mavenMatch[3],10),skipped=parseInt(mavenMatch[4],10);totals.failed=failures+errors5,totals.skipped=skipped,totals.passed=total-totals.failed-skipped,totals.total=total}break}case"gradle":{let gradleMatch=output.match(/(\d+) tests? completed(?:,\s*(\d+) failed)?(?:,\s*(\d+) skipped)?/);if(gradleMatch)totals.total=parseInt(gradleMatch[1],10),totals.failed=gradleMatch[2]?parseInt(gradleMatch[2],10):0,totals.skipped=gradleMatch[3]?parseInt(gradleMatch[3],10):0,totals.passed=totals.total-totals.failed-totals.skipped;break}case"dotnet-test":{let passMatch=output.match(/Passed[!:]?\s*(\d+)/i),failMatch=output.match(/Failed[!:]?\s*(\d+)/i),skipMatch=output.match(/Skipped[!:]?\s*(\d+)/i);if(passMatch)totals.passed=parseInt(passMatch[1],10);if(failMatch)totals.failed=parseInt(failMatch[1],10);if(skipMatch)totals.skipped=parseInt(skipMatch[1],10);totals.total=totals.passed+totals.failed+totals.skipped;break}case"ctest":{let ctestMatch=output.match(/(\d+) tests? failed out of (\d+)/);if(ctestMatch)totals.failed=parseInt(ctestMatch[1],10),totals.total=parseInt(ctestMatch[2],10),totals.passed=totals.total-totals.failed;else{let allPassMatch=output.match(/100% tests passed.*?(\d+) tests?/);if(allPassMatch)totals.total=parseInt(allPassMatch[1],10),totals.passed=totals.total}break}case"swift-test":{let swiftMatch=output.match(/Executed (\d+) tests?,\s*with (\d+) failures?/);if(swiftMatch)totals.total=parseInt(swiftMatch[1],10),totals.failed=parseInt(swiftMatch[2],10),totals.passed=totals.total-totals.failed;break}case"dart-test":{let dartPassMatch=output.match(/\+(\d+):\s*All tests passed/),dartMixMatch=output.match(/\+(\d+)\s+-(\d+):/);if(dartPassMatch)totals.passed=parseInt(dartPassMatch[1],10),totals.total=totals.passed;else if(dartMixMatch)totals.passed=parseInt(dartMixMatch[1],10),totals.failed=parseInt(dartMixMatch[2],10),totals.total=totals.passed+totals.failed;break}case"rspec":{let rspecMatch=output.match(/(\d+) examples?,\s*(\d+) failures?(?:,\s*(\d+) pending)?/);if(rspecMatch)totals.total=parseInt(rspecMatch[1],10),totals.failed=parseInt(rspecMatch[2],10),totals.skipped=rspecMatch[3]?parseInt(rspecMatch[3],10):0,totals.passed=totals.total-totals.failed-totals.skipped;break}case"minitest":{let minitestMatch=output.match(/(\d+) runs?,\s*\d+ assertions?,\s*(\d+) failures?,\s*(\d+) errors?,\s*(\d+) skips?/);if(minitestMatch)totals.total=parseInt(minitestMatch[1],10),totals.failed=parseInt(minitestMatch[2],10)+parseInt(minitestMatch[3],10),totals.skipped=parseInt(minitestMatch[4],10),totals.passed=totals.total-totals.failed-totals.skipped;break}case"pest":case"phpunit":case"php-artisan":{let phpunitMatch=output.match(/Tests:\s*(\d+),\s*Assertions:\s*\d+(?:,\s*Failures:\s*(\d+))?(?:,\s*Errors:\s*(\d+))?(?:,\s*Skipped:\s*(\d+))?/),okMatch=output.match(/OK\s*\((\d+)\s+tests?/);if(phpunitMatch){totals.total=parseInt(phpunitMatch[1],10);let failures=phpunitMatch[2]?parseInt(phpunitMatch[2],10):0,errors5=phpunitMatch[3]?parseInt(phpunitMatch[3],10):0;totals.skipped=phpunitMatch[4]?parseInt(phpunitMatch[4],10):0,totals.failed=failures+errors5,totals.passed=totals.total-totals.failed-totals.skipped}else if(okMatch)totals.total=parseInt(okMatch[1],10),totals.passed=totals.total;break}default:break}return{totals,coveragePercent}}async function readBoundedStream2(stream,maxBytes){let reader=stream.getReader(),chunks=[],totalBytes=0,truncated=!1;try{while(!0){let{done,value}=await reader.read();if(done)break;if(totalBytes+value.length>maxBytes){let remaining=maxBytes-totalBytes;if(remaining>0)chunks.push(value.slice(0,remaining));totalBytes=maxBytes,truncated=!0,reader.cancel().catch(()=>{});break}chunks.push(value),totalBytes+=value.length}}catch{}finally{try{reader.releaseLock()}catch{}}let decoder=new TextDecoder("utf-8",{fatal:!1}),combined=new Uint8Array(totalBytes),offset=0;for(let chunk of chunks)combined.set(chunk,offset),offset+=chunk.length;return{text:decoder.decode(combined),truncated}}async function runTests(framework,scope,files,coverage,timeout_ms,cwd,bail){if(scope!=="all"&&files.length>0){let unsupportedReason=getTargetedExecutionUnsupportedReason(framework);if(unsupportedReason)return{success:!1,framework,scope,error:`Framework "${framework}" does not support targeted test-file execution`,message:`The resolved test selection cannot be run safely because ${unsupportedReason}. Use a framework-native selector manually or let the architect handle the broader sweep.`,outcome:"error"}}let command=process.env.SWARM_LANG_BACKEND!=="legacy"?await buildTestCommandViaDispatch(framework,scope,files,coverage,cwd,bail)??buildTestCommand2(framework,scope,files,coverage,cwd,bail):buildTestCommand2(framework,scope,files,coverage,cwd,bail);if(!command)return{success:!1,framework,scope,error:`No test command available for framework: ${framework}`,message:"Install a supported test framework to run tests",outcome:"error"};if(command.join(" ").length>MAX_COMMAND_LENGTH2)return{success:!1,framework,scope,command,error:"Command exceeds maximum allowed length",outcome:"error"};let startTime=Date.now(),vitestJsonOutputPath=framework==="vitest"?path112.join(cwd,".swarm","cache","test-runner-vitest.json"):void 0;try{if(vitestJsonOutputPath)try{if(fs56.mkdirSync(path112.dirname(vitestJsonOutputPath),{recursive:!0}),fs56.existsSync(vitestJsonOutputPath))fs56.unlinkSync(vitestJsonOutputPath)}catch{}let proc=bunSpawn(command,{stdout:"pipe",stderr:"pipe",cwd}),timeoutPromise=new Promise((resolve45)=>setTimeout(()=>{proc.kill(),resolve45(-1)},timeout_ms)),[exitCode,stdoutResult,stderrResult]=await Promise.all([Promise.race([proc.exited,timeoutPromise]),readBoundedStream2(proc.stdout,MAX_OUTPUT_BYTES3),readBoundedStream2(proc.stderr,MAX_OUTPUT_BYTES3)]),duration_ms=Date.now()-startTime,output=stdoutResult.text;if(stderrResult.text)output+=(output?`
1710
1710
  `:"")+stderrResult.text;if(vitestJsonOutputPath)try{if(fs56.existsSync(vitestJsonOutputPath)){let vitestJsonOutput=fs56.readFileSync(vitestJsonOutputPath,"utf-8");if(vitestJsonOutput.trim().length>0)output+=(output?`
1711
1711
  `:"")+vitestJsonOutput}}catch{}if(stdoutResult.truncated||stderrResult.truncated)output+=`
1712
- ... (output truncated at stream read limit)`;let parsed=process.env.SWARM_LANG_BACKEND!=="legacy"?await parseTestOutputViaDispatch(framework,output,cwd)??parseTestOutput2(framework,output):parseTestOutput2(framework,output),parsedTestCases=parseFrameworkJsonTestResults(framework,output),totals={...parsed.totals},{coveragePercent}=parsed;if(totals.total===0&&parsedTestCases.length>0){for(let entry of parsedTestCases)if(entry.result==="pass")totals.passed++;else if(entry.result==="fail")totals.failed++;else totals.skipped++;totals.total=parsedTestCases.length}let isTimeout=exitCode===-1;if(exitCode===0&&totals.failed===0){let result={success:!0,framework,scope,command,timeout_ms,duration_ms,totals,rawOutput:output,outcome:"pass",testCases:parsedTestCases};if(coveragePercent!==void 0)result.coveragePercent=coveragePercent;if(result.message=`${framework} tests passed (${totals.passed}/${totals.total})`,coveragePercent!==void 0)result.message+=` with ${coveragePercent}% coverage`;return result}else{let result={success:!1,framework,scope,command,timeout_ms,duration_ms,totals,rawOutput:output,error:isTimeout?`Tests timed out after ${timeout_ms}ms`:`Tests failed with ${totals.failed} failures`,message:isTimeout?`${framework} tests timed out after ${timeout_ms}ms`:`${framework} tests failed (${totals.failed}/${totals.total} failed)`,outcome:isTimeout?"error":"regression",testCases:parsedTestCases};if(coveragePercent!==void 0)result.coveragePercent=coveragePercent;return result}}catch(error93){let duration_ms=Date.now()-startTime;return{success:!1,framework,scope,command,timeout_ms,duration_ms,error:error93 instanceof Error?`Execution failed: ${error93.message}`:"Execution failed: unknown error",outcome:"error"}}}function normalizeHistoryTestFile(testFile,workingDir){let normalized=testFile.replace(/\\/g,"/");if(!path112.isAbsolute(testFile))return normalized;let relative23=path112.relative(workingDir,testFile);if(relative23.startsWith("..")||path112.isAbsolute(relative23))return normalized;return relative23.replace(/\\/g,"/")}function combineAggregateResult(current,next){if(current==="fail"||next==="fail")return"fail";if(current==="pass"||next==="pass")return"pass";return"skip"}function recordAndAnalyzeResults(result,testFiles,workingDir,sourceFiles,parsedTestCases){if(!result.totals||result.totals.total===0)return;let now=new Date().toISOString(),changedFiles=(sourceFiles&&sourceFiles.length>0?sourceFiles:testFiles).map((f)=>f.replace(/\\/g,"/")),aggregateResultsByFile=new Map,validParsedCases=parsedTestCases?.filter((parsedCase)=>parsedCase.testFile.length>0&&parsedCase.testName.length>0)??[],allRecords=[];for(let parsedCase of validParsedCases){let normalizedTestFile=normalizeHistoryTestFile(parsedCase.testFile,workingDir);allRecords.push({timestamp:now,taskId:"auto",testFile:normalizedTestFile,testName:parsedCase.testName,result:parsedCase.result,durationMs:parsedCase.durationMs,errorMessage:parsedCase.errorMessage,stackPrefix:parsedCase.stackPrefix,changedFiles}),aggregateResultsByFile.set(normalizedTestFile,combineAggregateResult(aggregateResultsByFile.get(normalizedTestFile),parsedCase.result))}if(aggregateResultsByFile.size===0){let aggregateResult=result.success?"pass":"fail";for(let testFile of testFiles)aggregateResultsByFile.set(testFile.replace(/\\/g,"/"),aggregateResult)}for(let[testFile,aggregateResult]of aggregateResultsByFile)allRecords.push({timestamp:now,taskId:"auto",testFile,testName:AGGREGATE_TEST_NAME,result:aggregateResult,durationMs:result.duration_ms||0,changedFiles});try{batchAppendTestRuns(allRecords,workingDir)}catch{}}function selectHistoryForAnalysis(history){let filesWithIndividualRecords=new Set;for(let record3 of history)if(record3.testName!==AGGREGATE_TEST_NAME)filesWithIndividualRecords.add(record3.testFile.toLowerCase());if(filesWithIndividualRecords.size===0)return history;return history.filter((record3)=>record3.testName!==AGGREGATE_TEST_NAME||!filesWithIndividualRecords.has(record3.testFile.toLowerCase()))}function analyzeFailures(workingDir){let report={flakyTests:[],failureClusters:[],quarantinedFailures:[]};try{let history=selectHistoryForAnalysis(getAllHistory(workingDir));if(history.length===0)return report;report.flakyTests=detectFlakyTests(history);let failingResults=history.filter((r)=>r.result==="fail");if(failingResults.length>0){let{clusters}=classifyAndCluster(failingResults,history);report.failureClusters=clusters.map((c)=>({rootCause:c.rootCause,affectedFiles:c.affectedTestFiles,classification:c.classification}))}for(let entry of report.flakyTests)if(entry.isQuarantined)report.quarantinedFailures.push(`${entry.testFile}: ${entry.testName}`)}catch{}return report}var MAX_OUTPUT_BYTES3=512000,MAX_COMMAND_LENGTH2=500,DEFAULT_TIMEOUT_MS=60000,MAX_TIMEOUT_MS=300000,MAX_SAFE_TEST_FILES=50,MAX_SAFE_SOURCE_FILES=1,AGGREGATE_TEST_NAME="(aggregate)",VITEST_JSON_OUTPUT_RELATIVE_PATH=".swarm/cache/test-runner-vitest.json",POWERSHELL_METACHARACTERS,DISPATCH_FRAMEWORK_MAP,COMPOUND_TEST_EXTENSIONS,TEST_DIRECTORY_NAMES,SOURCE_EXTENSIONS,test_runner;var init_test_runner=__esm(()=>{init_zod();init_discovery();init_analyzer();init_failure_classifier();init_history_store();init_bun_compat();init_path_security();init_create_tool();init_resolve_working_directory();POWERSHELL_METACHARACTERS=/[|;&`$(){}[\]<>"'#*?\x00-\x1f]/;DISPATCH_FRAMEWORK_MAP={bun:"bun",vitest:"vitest",jest:"jest",mocha:"mocha",pytest:"pytest",cargo:"cargo",pester:"pester","go-test":"go-test",maven:"maven",gradle:"gradle","dotnet-test":"dotnet-test",ctest:"ctest","swift-test":"swift-test","dart-test":"dart-test",rspec:"rspec",minitest:"minitest",pest:"pest",phpunit:"phpunit","php-artisan":"php-artisan","bun:test":"bun","xcodebuild-test":"swift-test","flutter test":"dart-test","dart test":"dart-test",Pest:"pest",PHPUnit:"phpunit"};COMPOUND_TEST_EXTENSIONS=[".test.ts",".test.tsx",".test.js",".test.jsx",".tests.ps1",".spec.ts",".spec.tsx",".spec.js",".spec.jsx",".test.ps1",".spec.ps1"],TEST_DIRECTORY_NAMES=["__tests__","tests","test","spec"];SOURCE_EXTENSIONS=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".py",".rs",".ps1",".psm1",".go",".java",".kt",".kts",".cs",".c",".h",".cpp",".hpp",".cc",".cxx",".php",".swift",".dart",".rb",".pyi"]);test_runner=createSwarmTool({description:'Run project tests with framework detection. Supports bun, vitest, jest, mocha, pytest, cargo, pester, go-test, maven, gradle, dotnet-test, ctest, swift-test, dart-test, rspec, and minitest. Returns deterministic normalized JSON with framework, scope, command, totals, coverage, duration, success status, and failures. Use scope "all" for full suite, "convention" to accept direct test files or map source files to test files, "graph" to find related tests via imports from source files, or "impact" to find tests covering changed source files using test-impact analysis.',args:{scope:exports_external.enum(["all","convention","graph","impact"]).optional().describe('Test scope: "all" runs full suite, "convention" accepts direct test files or maps source files to tests by naming, "graph" finds related tests via imports from source files, "impact" finds tests covering changed source files via test-impact analysis'),files:exports_external.array(exports_external.string()).optional().describe('Specific files to test. For "convention", pass source files or direct test files. For "graph" and "impact", pass source files only.'),coverage:exports_external.boolean().optional().describe("Enable coverage reporting if supported"),bail:exports_external.boolean().optional().describe("Stop running tests after the first failure. Default false. Note: coverage may be incomplete when bail=true with coverage=true."),timeout_ms:exports_external.number().optional().describe("Timeout in milliseconds (default 60000, max 300000)"),allow_full_suite:exports_external.boolean().optional().describe('Explicit opt-in for scope "all". Required because full-suite output can destabilize SSE streaming.'),working_directory:exports_external.string().optional().describe("Explicit project root directory. When provided, tests run relative to this path instead of the plugin context directory. Use this when CWD differs from the actual project root.")},async execute(args2,directory){let workingDirInput;if(args2&&typeof args2==="object"){let obj=args2;workingDirInput=typeof obj.working_directory==="string"?obj.working_directory:void 0}let dirResult=resolveWorkingDirectory(workingDirInput,directory);if(!dirResult.success){let errorResult={success:!1,framework:"none",scope:"all",error:dirResult.message,outcome:"error"};return JSON.stringify(errorResult,null,2)}let workingDir=dirResult.directory;if(workingDir.length>4096)return JSON.stringify({success:!1,framework:"none",scope:"all",error:"Invalid working directory",outcome:"error"},null,2);if(/^[/\\]{2}/.test(workingDir))return JSON.stringify({success:!1,framework:"none",scope:"all",error:"Invalid working directory",outcome:"error"},null,2);if(containsControlChars(workingDir))return JSON.stringify({success:!1,framework:"none",scope:"all",error:"Invalid working directory",outcome:"error"},null,2);if(containsPathTraversal(workingDir))return JSON.stringify({success:!1,framework:"none",scope:"all",error:"Invalid working directory",outcome:"error"},null,2);if(!validateArgs2(args2))return JSON.stringify({success:!1,framework:"none",scope:"all",error:"Invalid arguments",message:'scope must be "all", "convention", "graph", or "impact"; files must be array of strings; coverage must be boolean; timeout_ms must be a positive number',outcome:"error"},null,2);let scope=args2.scope||"all";if(scope==="all"){if(!process.env.SWARM_ALLOW_FULL_SUITE)return JSON.stringify({success:!1,framework:"none",scope:"all",error:'scope "all" is blocked for agent use. Use scope "convention" with specific test files, or scope "graph" with exactly one source file.',message:'The full test suite is blocked in agent context. Use scope "convention" with specific test files, or scope "graph" with exactly one source file. Example: { scope: "convention", files: ["src/tools/test-runner.ts"] }',outcome:"error"},null,2)}if((scope==="convention"||scope==="graph"||scope==="impact")&&(!args2.files||args2.files.length===0))return JSON.stringify({success:!1,framework:"none",scope,error:'scope "convention" and "graph" require explicit files array - omitting files causes unsafe full-project discovery',message:'When using scope "convention" or "graph", you must provide a non-empty "files" array. Use scope "all" for full project test suite without specifying files.',outcome:"error"},null,2);let _files=args2.files||[],coverage=args2.coverage||!1,bail=args2.bail||!1,timeout_ms=Math.min(args2.timeout_ms||DEFAULT_TIMEOUT_MS,MAX_TIMEOUT_MS),useDispatch=process.env.SWARM_LANG_BACKEND!=="legacy",framework;if(useDispatch){if(framework=await detectTestFrameworkViaDispatch(workingDir),framework==="none")framework=await detectTestFramework(workingDir)}else framework=await detectTestFramework(workingDir);if(framework==="none")return JSON.stringify({success:!1,framework:"none",scope,error:"No test framework detected",message:"No supported test framework found. Install bun, vitest, jest, mocha, pytest, cargo, pester, or a supported language test runner (go test, maven, gradle, dotnet test, ctest, swift test, dart test, rspec, minitest).",totals:{passed:0,failed:0,skipped:0,total:0},outcome:"error"},null,2);let testFiles=[],graphFallbackReason,effectiveScope=scope;if(scope==="all");else if(scope==="convention"){let directTestFiles=args2.files.filter((file3)=>isConventionTestFilePath(file3)),sourceFiles=args2.files.filter((file3)=>{if(directTestFiles.includes(file3))return!1;let ext=path112.extname(file3).toLowerCase();return SOURCE_EXTENSIONS.has(ext)}),invalidFiles=args2.files.filter((file3)=>!directTestFiles.includes(file3)&&!sourceFiles.includes(file3));if(directTestFiles.length===0&&sourceFiles.length===0)return JSON.stringify({success:!1,framework,scope,error:"Provided files contain no recognized source files or direct test files",message:"The files array must contain at least one source file with a recognized extension (.ts, .tsx, .js, .jsx, .py, .rs, .ps1, etc.) or a direct test file in a supported test location/naming convention.",outcome:"error"},null,2);if(invalidFiles.length>0){let errorResult={success:!1,framework,scope,error:"Provided files include entries that are neither recognized source files nor direct test files",message:`These files are not valid for targeted test discovery: ${invalidFiles.join(", ")}`,outcome:"error"};return JSON.stringify(errorResult,null,2)}if(sourceFiles.length>MAX_SAFE_SOURCE_FILES){let errorResult={success:!1,framework,scope,error:`scope "convention" accepts at most ${MAX_SAFE_SOURCE_FILES} source file for discovery (got ${sourceFiles.length}). Treat this as SKIP without retry.`,message:`Too many source files for scope "convention" discovery (${sourceFiles.length} provided, limit is ${MAX_SAFE_SOURCE_FILES}). Call test_runner once per source file, or pass direct test file paths instead of source files.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}testFiles=[...directTestFiles,...getTestFilesFromConvention(sourceFiles,workingDir)].filter((file3,index,items)=>items.indexOf(file3)===index)}else if(scope==="graph"){let sourceFiles=args2.files.filter((f)=>{if(isConventionTestFilePath(f))return!1;let ext=path112.extname(f).toLowerCase();return SOURCE_EXTENSIONS.has(ext)});if(sourceFiles.length===0)return JSON.stringify({success:!1,framework,scope,error:"Provided files contain no source files with recognized extensions",message:'The files array for scope "graph" must contain at least one source file with a recognized extension (.ts, .tsx, .js, .jsx, .py, .rs, .ps1, etc.). Direct test files belong in scope "convention".',outcome:"error"},null,2);if(sourceFiles.length>MAX_SAFE_SOURCE_FILES){let errorResult={success:!1,framework,scope,error:`scope "graph" accepts at most ${MAX_SAFE_SOURCE_FILES} source file (got ${sourceFiles.length}). Treat this as SKIP without retry.`,message:`Too many source files for scope "graph" (${sourceFiles.length} provided, limit is ${MAX_SAFE_SOURCE_FILES}). Call test_runner once per source file, or use scope "convention" with direct test file paths.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}let estimate=await estimateFanOut(sourceFiles,workingDir);if(estimate.estimatedCount>MAX_SAFE_TEST_FILES){let errorResult={success:!1,framework,scope,error:"Estimated test file count exceeds safe maximum",message:`Scope "graph" resolution would produce approximately ${estimate.estimatedCount} test files, which exceeds the safe limit of ${MAX_SAFE_TEST_FILES}. Break the source files into smaller batches and retry.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}let graphTestFiles=await getTestFilesFromGraph(sourceFiles,workingDir);if(graphTestFiles.length>0)testFiles=graphTestFiles;else graphFallbackReason="imports resolution returned no results, falling back to convention",effectiveScope="convention",testFiles=getTestFilesFromConvention(sourceFiles,workingDir)}else if(scope==="impact"){let sourceFiles=args2.files.filter((f)=>{if(isConventionTestFilePath(f))return!1;let ext=path112.extname(f).toLowerCase();return SOURCE_EXTENSIONS.has(ext)});if(sourceFiles.length===0)return JSON.stringify({success:!1,framework,scope,error:"Provided files contain no source files with recognized extensions",message:'The files array for scope "impact" must contain at least one source file with a recognized extension (.ts, .tsx, .js, .jsx, .py, .rs, .ps1, etc.). Direct test files belong in scope "convention".',outcome:"error"},null,2);if(sourceFiles.length>MAX_SAFE_SOURCE_FILES){let errorResult={success:!1,framework,scope,error:`scope "impact" accepts at most ${MAX_SAFE_SOURCE_FILES} source file (got ${sourceFiles.length}). Treat this as SKIP without retry.`,message:`Too many source files for scope "impact" (${sourceFiles.length} provided, limit is ${MAX_SAFE_SOURCE_FILES}). Call test_runner once per source file, or use scope "convention" with direct test file paths.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}let estimate=await estimateFanOut(sourceFiles,workingDir);if(estimate.estimatedCount>MAX_SAFE_TEST_FILES){let errorResult={success:!1,framework,scope,error:"Estimated test file count exceeds safe maximum",message:`Scope "impact" resolution would produce approximately ${estimate.estimatedCount} test files, which exceeds the safe limit of ${MAX_SAFE_TEST_FILES}. Break the source files into smaller batches and retry.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}try{let impactResult=await analyzeImpact(sourceFiles,workingDir,MAX_SAFE_TEST_FILES);if(impactResult.budgetExceeded){let errorResult={success:!1,framework,scope,error:"Budget exceeded during impact analysis",message:`Impact analysis exceeded safe budget of ${MAX_SAFE_TEST_FILES} test files.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}if(impactResult.impactedTests.length>0)testFiles=impactResult.impactedTests.map((absPath)=>{let relativePath=path112.relative(workingDir,absPath);return path112.isAbsolute(relativePath)?absPath:relativePath});else{graphFallbackReason="no impacted tests found via impact analysis, falling back to graph",effectiveScope="graph";let graphTestFiles=await getTestFilesFromGraph(sourceFiles,workingDir);if(graphTestFiles.length>0)testFiles=graphTestFiles;else graphFallbackReason="imports resolution returned no results, falling back to convention",effectiveScope="convention",testFiles=getTestFilesFromConvention(sourceFiles,workingDir)}}catch{graphFallbackReason="impact analysis failed, falling back to graph",effectiveScope="graph";let graphTestFiles=await getTestFilesFromGraph(sourceFiles,workingDir);if(graphTestFiles.length>0)testFiles=graphTestFiles;else graphFallbackReason="imports resolution returned no results, falling back to convention",effectiveScope="convention",testFiles=getTestFilesFromConvention(sourceFiles,workingDir)}}if(scope!=="all"&&testFiles.length===0){let errorResult={success:!1,framework,scope:effectiveScope,error:"Provided source files resolved to zero test files",message:graphFallbackReason?`No matching test files found for the provided source files. Check that test files exist with matching naming conventions (.spec.*, .test.*, .Tests.ps1, __tests__/, tests/, test/, spec/). (${graphFallbackReason})`:"No matching test files found for the provided source files. Check that test files exist with matching naming conventions (.spec.*, .test.*, .Tests.ps1, __tests__/, tests/, test/, spec/).",outcome:"skip",...scope==="graph"&&{attempted_scope:"graph"},...scope==="impact"&&{attempted_scope:"graph"}};return JSON.stringify(errorResult,null,2)}if(scope!=="all"&&testFiles.length>MAX_SAFE_TEST_FILES){let sampleFiles=testFiles.slice(0,5),errorResult={success:!1,framework,scope:effectiveScope,error:`Resolved test file count (${testFiles.length}) exceeds safe maximum (${MAX_SAFE_TEST_FILES})`,message:`Too many test files resolved (${testFiles.length}). Maximum allowed is ${MAX_SAFE_TEST_FILES}. Treat this as SKIP without retry. Provide more specific source files to narrow down test scope. First few resolved: ${sampleFiles.join(", ")}`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}let result=await runTests(framework,effectiveScope,testFiles,coverage,timeout_ms,workingDir,bail);recordAndAnalyzeResults(result,testFiles,workingDir,_files.length>0?_files:void 0,result.testCases);let historyReport;if(!result.success&&result.totals&&result.totals.failed>0){if(historyReport=analyzeFailures(workingDir),historyReport.quarantinedFailures.length>0)result.message=(result.message||"")+` | QUARANTINED (flaky): ${historyReport.quarantinedFailures.join(", ")}`;if(historyReport.failureClusters.length>0){let clusterSummary=historyReport.failureClusters.slice(0,3).map((c)=>`${c.classification}: ${c.rootCause.substring(0,80)}`).join("; ");result.message=`${result.message||""} | FAILURE ANALYSIS: ${clusterSummary}`}}if(graphFallbackReason&&result.message)result.message=`${result.message} (${graphFallbackReason})`;if(bail&&coverage&&result.message)result.message=`${result.message} (coverage may be incomplete: bail=true stopped early)`;return JSON.stringify(result,null,2)}})});import*as fs57 from"node:fs";import*as path113 from"node:path";function validateDirectoryPath(dir){if(!dir||typeof dir!=="string")throw Error("Directory path is required");if(dir.includes(".."))throw Error("Directory path must not contain path traversal sequences");let normalized=path113.normalize(dir);return path113.isAbsolute(normalized)?normalized:path113.resolve(normalized)}function validateTimeout(timeoutMs,defaultValue){if(timeoutMs===void 0)return defaultValue;if(typeof timeoutMs!=="number"||!Number.isFinite(timeoutMs))throw Error("Timeout must be a finite number");if(timeoutMs<=0)throw Error("Timeout must be greater than 0");if(timeoutMs<MIN_CHECK_TIMEOUT_MS)throw Error(`Timeout must be at least ${MIN_CHECK_TIMEOUT_MS}ms (5 seconds)`);if(timeoutMs>MAX_CHECK_TIMEOUT_MS)throw Error(`Timeout must not exceed ${MAX_CHECK_TIMEOUT_MS}ms (5 minutes)`);return timeoutMs}function getPackageVersion(dir){try{let packagePath=path113.join(dir,"package.json");if(fs57.existsSync(packagePath)){let content=fs57.readFileSync(packagePath,"utf-8");return JSON.parse(content).version??null}}catch{}return null}function getChangelogVersion(dir){try{let changelogPath=path113.join(dir,"CHANGELOG.md");if(fs57.existsSync(changelogPath)){let match=fs57.readFileSync(changelogPath,"utf-8").match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);if(match)return match[1]}}catch{}return null}function getVersionFileVersion(dir){let possibleFiles=["VERSION.txt","version.txt","VERSION","version"];for(let file3 of possibleFiles){let filePath=path113.join(dir,file3);if(fs57.existsSync(filePath))try{let match=fs57.readFileSync(filePath,"utf-8").trim().match(/(\d+\.\d+\.\d+)/);if(match)return match[1]}catch{}}return null}async function runVersionCheck2(dir,_timeoutMs){let startTime=Date.now();try{let packageVersion=_internals76.getPackageVersion(dir),changelogVersion=_internals76.getChangelogVersion(dir),versionFileVersion=_internals76.getVersionFileVersion(dir),versions3=[];if(packageVersion)versions3.push(`package.json: ${packageVersion}`);if(changelogVersion)versions3.push(`CHANGELOG.md: ${changelogVersion}`);if(versionFileVersion)versions3.push(`version file: ${versionFileVersion}`);if(new Set([packageVersion,changelogVersion,versionFileVersion].filter(Boolean)).size<=1){if(versions3.length===0)return{type:"version",status:"skip",message:"No version information found to check",details:{},durationMs:Date.now()-startTime};return{type:"version",status:"pass",message:`Version consistent: ${versions3.join(", ")}`,details:{packageVersion,changelogVersion,versionFileVersion},durationMs:Date.now()-startTime}}return{type:"version",status:"fail",message:`Version mismatch: ${versions3.join("; ")}`,details:{packageVersion,changelogVersion,versionFileVersion},durationMs:Date.now()-startTime}}catch(error93){return{type:"version",status:"error",message:`Version check failed: ${error93 instanceof Error?error93.message:String(error93)}`,durationMs:Date.now()-startTime}}}async function runLintCheck(dir,linter,timeoutMs){let startTime=Date.now();try{let lintPromise=runLint(linter,"check",dir),timeoutId,timeoutPromise=new Promise((_,reject)=>{timeoutId=setTimeout(()=>{reject(Error(`Lint check timed out after ${timeoutMs}ms`))},timeoutMs)}),result=await Promise.race([lintPromise,timeoutPromise]).finally(()=>clearTimeout(timeoutId));if(!result.success)return{type:"lint",status:"error",message:result.error??"Lint check failed",details:{linter,success:result.success},durationMs:Date.now()-startTime};if(result.exitCode!==0){let issueMatch=result.output.match(/(\d+)\s+(issues?|errors?)/i),issueCount=issueMatch?parseInt(issueMatch[1],10):void 0;return{type:"lint",status:"fail",message:issueCount?`Lint found ${issueCount} issue(s)`:"Lint found issues",details:{linter,exitCode:result.exitCode,issueCount,hasOutput:result.output.length>0},durationMs:Date.now()-startTime}}return{type:"lint",status:"pass",message:"Lint check passed",details:{linter,exitCode:result.exitCode},durationMs:Date.now()-startTime}}catch(error93){if(error93 instanceof Error&&error93.message.includes("timed out"))return{type:"lint",status:"error",message:error93.message,details:{linter},durationMs:Date.now()-startTime};return{type:"lint",status:"error",message:`Lint check failed: ${error93 instanceof Error?error93.message:String(error93)}`,details:{linter},durationMs:Date.now()-startTime}}}async function runTestsCheck(_dir,scope,timeoutMs){let startTime=Date.now();try{let result=await runTests("none",scope,[],!1,timeoutMs,_dir,!1);if(!result.success)return{type:"tests",status:"error",message:result.error??"Tests check failed",details:{framework:result.framework,scope,success:result.success},durationMs:Date.now()-startTime};if(result.totals.failed>0)return{type:"tests",status:"fail",message:`Tests failed: ${result.totals.failed}/${result.totals.total} failed`,details:{framework:result.framework,scope,totals:result.totals},durationMs:Date.now()-startTime};if(result.totals.total===0)return{type:"tests",status:"skip",message:"No tests found to run",details:{framework:result.framework,scope},durationMs:Date.now()-startTime};return{type:"tests",status:"pass",message:`Tests passed: ${result.totals.passed} passed`,details:{framework:result.framework,scope,totals:result.totals},durationMs:Date.now()-startTime}}catch(error93){if(error93 instanceof Error&&(error93.message.includes("timeout")||error93.message.includes("ETIMEDOUT")))return{type:"tests",status:"error",message:`Tests check timed out after ${timeoutMs}ms`,durationMs:Date.now()-startTime};return{type:"tests",status:"error",message:`Tests check failed: ${error93 instanceof Error?error93.message:String(error93)}`,durationMs:Date.now()-startTime}}}async function runSecretsCheck(dir,timeoutMs){let startTime=Date.now();try{let secretsPromise=runSecretscan(dir),timeoutPromise=new Promise((_,reject)=>{setTimeout(()=>{reject(Error(`Secrets check timed out after ${timeoutMs}ms`))},timeoutMs)}),result=await Promise.race([secretsPromise,timeoutPromise]);if(result.findings&&result.findings.length>0){let critical=result.findings.filter((f)=>f.severity==="critical").length,high=result.findings.filter((f)=>f.severity==="high").length;return{type:"secrets",status:"fail",message:`Found ${result.findings.length} secret(s): ${critical} critical, ${high} high`,details:{count:result.count,critical,high,filesScanned:result.files_scanned},durationMs:Date.now()-startTime}}return{type:"secrets",status:"pass",message:"No secrets detected",details:{filesScanned:result.files_scanned},durationMs:Date.now()-startTime}}catch(error93){if(error93 instanceof Error&&error93.name==="AbortError")return{type:"secrets",status:"error",message:`Secrets check timed out after ${timeoutMs}ms`,durationMs:Date.now()-startTime};return{type:"secrets",status:"error",message:`Secrets check failed: ${error93 instanceof Error?error93.message:String(error93)}`,durationMs:Date.now()-startTime}}}async function runEvidenceCheck(dir){let startTime=Date.now();try{let plan=await loadPlan(dir);if(!plan)return{type:"evidence",status:"skip",message:"No plan found to check evidence against",details:{},durationMs:Date.now()-startTime};let completedTaskIds=[];for(let phase of plan.phases)for(let task of phase.tasks)if(task.status==="completed")completedTaskIds.push(task.id);if(completedTaskIds.length===0)return{type:"evidence",status:"skip",message:"No completed tasks yet",details:{completedTasks:0},durationMs:Date.now()-startTime};let evidenceTaskIds=new Set(await listEvidenceTaskIds(dir)),missingEvidence=[];for(let id of completedTaskIds){let gateStatus=await getDurableGateEvidenceStatusForTask(dir,id);if(gateStatus.isComplete)continue;if(gateStatus.evidenceExists&&gateStatus.missingGates.length>0){missingEvidence.push(id);continue}if(evidenceTaskIds.has(id))continue;missingEvidence.push(id)}let completedWithEvidence=completedTaskIds.length-missingEvidence.length;if(missingEvidence.length>0)return{type:"evidence",status:"fail",message:`${missingEvidence.length} completed task(s) missing evidence`,details:{totalCompleted:completedTaskIds.length,totalWithEvidence:completedWithEvidence,missingTasks:missingEvidence.slice(0,10),missingCount:missingEvidence.length},durationMs:Date.now()-startTime};return{type:"evidence",status:"pass",message:`All ${completedTaskIds.length} completed tasks have evidence`,details:{totalCompleted:completedTaskIds.length,totalWithEvidence:completedWithEvidence},durationMs:Date.now()-startTime}}catch(error93){return{type:"evidence",status:"error",message:`Evidence check failed: ${error93 instanceof Error?error93.message:String(error93)}`,durationMs:Date.now()-startTime}}}async function runRequirementCoverageCheck(dir,currentPhase){let startTime=Date.now();try{if(readEffectiveSpecSync(dir)===null)return{type:"req_coverage",status:"skip",message:"No effective spec found, requirement coverage not required",details:{},durationMs:Date.now()-startTime};let coverage=await checkRequirementCoverage(currentPhase,dir);if(coverage.exists)return{type:"req_coverage",status:"pass",message:"Requirement coverage report found",details:{path:coverage.path},durationMs:Date.now()-startTime};return{type:"req_coverage",status:"fail",message:"Requirement coverage report missing but effective spec exists",details:{expectedPath:coverage.path},durationMs:Date.now()-startTime}}catch(error93){return{type:"req_coverage",status:"error",message:`Requirement coverage check failed: ${error93 instanceof Error?error93.message:String(error93)}`,durationMs:Date.now()-startTime}}}async function runPreflight(dir,phase,config3){let startTime=Date.now(),reportId=`preflight-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,validatedDir;try{validatedDir=_internals76.validateDirectoryPath(dir)}catch(error93){return{id:reportId,timestamp:startTime,phase,overall:"fail",checks:[{type:"lint",status:"error",message:`Invalid directory: ${error93 instanceof Error?error93.message:String(error93)}`}],totalDurationMs:Date.now()-startTime,message:"Preflight aborted: invalid directory"}}let validatedTimeout;try{validatedTimeout=_internals76.validateTimeout(config3?.checkTimeoutMs,DEFAULT_CONFIG.checkTimeoutMs)}catch(error93){return{id:reportId,timestamp:startTime,phase,overall:"fail",checks:[{type:"lint",status:"error",message:`Invalid config: ${error93 instanceof Error?error93.message:String(error93)}`}],totalDurationMs:Date.now()-startTime,message:"Preflight aborted: invalid configuration"}}let cfg={checkTimeoutMs:validatedTimeout,skipTests:config3?.skipTests??DEFAULT_CONFIG.skipTests,skipSecrets:config3?.skipSecrets??DEFAULT_CONFIG.skipSecrets,skipEvidence:config3?.skipEvidence??DEFAULT_CONFIG.skipEvidence,skipVersion:config3?.skipVersion??DEFAULT_CONFIG.skipVersion,testScope:config3?.testScope??DEFAULT_CONFIG.testScope,linter:config3?.linter??DEFAULT_CONFIG.linter};log("[Preflight] Starting preflight checks",{reportId,phase,config:{skipTests:cfg.skipTests,skipSecrets:cfg.skipSecrets,skipEvidence:cfg.skipEvidence,skipVersion:cfg.skipVersion,testScope:cfg.testScope,linter:cfg.linter}});let checks5=[];log("[Preflight] Running lint check...");let lintResult=await _internals76.runLintCheck(validatedDir,cfg.linter,cfg.checkTimeoutMs);if(checks5.push(lintResult),log(`[Preflight] Lint check: ${lintResult.status} ${lintResult.message}`),!cfg.skipTests){log("[Preflight] Running tests check...");let testsResult=await _internals76.runTestsCheck(validatedDir,cfg.testScope,cfg.checkTimeoutMs);checks5.push(testsResult),log(`[Preflight] Tests check: ${testsResult.status} ${testsResult.message}`)}else checks5.push({type:"tests",status:"skip",message:"Tests check skipped by configuration"});if(!cfg.skipSecrets){log("[Preflight] Running secrets check...");let secretsResult=await _internals76.runSecretsCheck(validatedDir,cfg.checkTimeoutMs);checks5.push(secretsResult),log(`[Preflight] Secrets check: ${secretsResult.status} ${secretsResult.message}`)}else checks5.push({type:"secrets",status:"skip",message:"Secrets check skipped by configuration"});if(!cfg.skipEvidence){log("[Preflight] Running evidence check...");let evidenceResult=await _internals76.runEvidenceCheck(validatedDir);checks5.push(evidenceResult),log(`[Preflight] Evidence check: ${evidenceResult.status} ${evidenceResult.message}`)}else checks5.push({type:"evidence",status:"skip",message:"Evidence check skipped by configuration"});log("[Preflight] Running requirement coverage check...");let reqCoverageResult=await _internals76.runRequirementCoverageCheck(validatedDir,phase);if(checks5.push(reqCoverageResult),log(`[Preflight] Requirement coverage check: ${reqCoverageResult.status} ${reqCoverageResult.message}`),!cfg.skipVersion){log("[Preflight] Running version check...");let versionResult=await _internals76.runVersionCheck(validatedDir,cfg.checkTimeoutMs);checks5.push(versionResult),log(`[Preflight] Version check: ${versionResult.status} ${versionResult.message}`)}else checks5.push({type:"version",status:"skip",message:"Version check skipped by configuration"});let totalDurationMs=Date.now()-startTime,failedChecks=checks5.filter((c)=>c.status==="fail").length,errorChecks=checks5.filter((c)=>c.status==="error").length,skippedChecks=checks5.filter((c)=>c.status==="skip").length,overall,message;if(errorChecks>0)overall="fail",message=`Preflight failed with ${errorChecks} error(s)`;else if(failedChecks>0)overall="fail",message=`Preflight failed: ${failedChecks} check(s) failed`;else if(skippedChecks===checks5.length)overall="skipped",message="All checks were skipped";else overall="pass",message="Preflight passed all checks";return log(`[Preflight] Complete: ${overall} ${message}`),{id:reportId,timestamp:startTime,phase,overall,checks:checks5,totalDurationMs,message}}function formatPreflightMarkdown(report){let lines=["## Preflight Report","",`**Phase**: ${report.phase}`,`**Overall**: ${report.overall==="pass"?"✅ PASS":report.overall==="fail"?"❌ FAIL":"⏭️ SKIPPED"}`,`**Duration**: ${(report.totalDurationMs/1000).toFixed(2)}s`,"","### Checks",""];for(let check3 of report.checks){let icon=check3.status==="pass"?"✅":check3.status==="fail"?"❌":check3.status==="error"?"⚠️":"⏭️";lines.push(`- ${icon} **${check3.type}**: ${check3.message}`)}return lines.push(""),lines.push(report.message),lines.join(`
1712
+ ... (output truncated at stream read limit)`;let parsed=process.env.SWARM_LANG_BACKEND!=="legacy"?await parseTestOutputViaDispatch(framework,output,cwd)??parseTestOutput2(framework,output):parseTestOutput2(framework,output),parsedTestCases=parseFrameworkJsonTestResults(framework,output),totals={...parsed.totals},{coveragePercent}=parsed;if(totals.total===0&&parsedTestCases.length>0){for(let entry of parsedTestCases)if(entry.result==="pass")totals.passed++;else if(entry.result==="fail")totals.failed++;else totals.skipped++;totals.total=parsedTestCases.length}let isTimeout=exitCode===-1;if(exitCode===0&&totals.failed===0){let result={success:!0,framework,scope,command,timeout_ms,duration_ms,totals,rawOutput:output,outcome:"pass",testCases:parsedTestCases};if(coveragePercent!==void 0)result.coveragePercent=coveragePercent;if(result.message=`${framework} tests passed (${totals.passed}/${totals.total})`,coveragePercent!==void 0)result.message+=` with ${coveragePercent}% coverage`;return result}else{let result={success:!1,framework,scope,command,timeout_ms,duration_ms,totals,rawOutput:output,error:isTimeout?`Tests timed out after ${timeout_ms}ms`:`Tests failed with ${totals.failed} failures`,message:isTimeout?`${framework} tests timed out after ${timeout_ms}ms`:`${framework} tests failed (${totals.failed}/${totals.total} failed)`,outcome:isTimeout?"error":"regression",testCases:parsedTestCases};if(coveragePercent!==void 0)result.coveragePercent=coveragePercent;return result}}catch(error93){let duration_ms=Date.now()-startTime;return{success:!1,framework,scope,command,timeout_ms,duration_ms,error:error93 instanceof Error?`Execution failed: ${error93.message}`:"Execution failed: unknown error",outcome:"error"}}}function normalizeHistoryTestFile(testFile,workingDir){let normalized=testFile.replace(/\\/g,"/");if(!path112.isAbsolute(testFile))return normalized;let relative23=path112.relative(workingDir,testFile);if(relative23.startsWith("..")||path112.isAbsolute(relative23))return normalized;return relative23.replace(/\\/g,"/")}function combineAggregateResult(current,next){if(current==="fail"||next==="fail")return"fail";if(current==="pass"||next==="pass")return"pass";return"skip"}function recordAndAnalyzeResults(result,testFiles,workingDir,sourceFiles,parsedTestCases){if(!result.totals||result.totals.total===0)return;let now=new Date().toISOString(),changedFiles=(sourceFiles&&sourceFiles.length>0?sourceFiles:testFiles).map((f)=>f.replace(/\\/g,"/")),aggregateResultsByFile=new Map,validParsedCases=parsedTestCases?.filter((parsedCase)=>parsedCase.testFile.length>0&&parsedCase.testName.length>0)??[],allRecords=[];for(let parsedCase of validParsedCases){let normalizedTestFile=normalizeHistoryTestFile(parsedCase.testFile,workingDir);allRecords.push({timestamp:now,taskId:"auto",testFile:normalizedTestFile,testName:parsedCase.testName,result:parsedCase.result,durationMs:parsedCase.durationMs,errorMessage:parsedCase.errorMessage,stackPrefix:parsedCase.stackPrefix,changedFiles}),aggregateResultsByFile.set(normalizedTestFile,combineAggregateResult(aggregateResultsByFile.get(normalizedTestFile),parsedCase.result))}if(aggregateResultsByFile.size===0){let aggregateResult=result.success?"pass":"fail";for(let testFile of testFiles)aggregateResultsByFile.set(testFile.replace(/\\/g,"/"),aggregateResult)}for(let[testFile,aggregateResult]of aggregateResultsByFile)allRecords.push({timestamp:now,taskId:"auto",testFile,testName:AGGREGATE_TEST_NAME,result:aggregateResult,durationMs:result.duration_ms||0,changedFiles});try{batchAppendTestRuns(allRecords,workingDir)}catch{}}function selectHistoryForAnalysis(history){let filesWithIndividualRecords=new Set;for(let record3 of history)if(record3.testName!==AGGREGATE_TEST_NAME)filesWithIndividualRecords.add(record3.testFile.toLowerCase());if(filesWithIndividualRecords.size===0)return history;return history.filter((record3)=>record3.testName!==AGGREGATE_TEST_NAME||!filesWithIndividualRecords.has(record3.testFile.toLowerCase()))}function analyzeFailures(workingDir){let report={flakyTests:[],failureClusters:[],quarantinedFailures:[]};try{let history=selectHistoryForAnalysis(getAllHistory(workingDir));if(history.length===0)return report;report.flakyTests=detectFlakyTests(history);let failingResults=history.filter((r)=>r.result==="fail");if(failingResults.length>0){let{clusters}=classifyAndCluster(failingResults,history);report.failureClusters=clusters.map((c)=>({rootCause:c.rootCause,affectedFiles:c.affectedTestFiles,classification:c.classification}))}for(let entry of report.flakyTests)if(entry.isQuarantined)report.quarantinedFailures.push(`${entry.testFile}: ${entry.testName}`)}catch{}return report}var MAX_OUTPUT_BYTES3=512000,MAX_COMMAND_LENGTH2=500,DEFAULT_TIMEOUT_MS=60000,MAX_TIMEOUT_MS=300000,MAX_SAFE_TEST_FILES=50,MAX_SAFE_SOURCE_FILES=1,AGGREGATE_TEST_NAME="(aggregate)",VITEST_JSON_OUTPUT_RELATIVE_PATH=".swarm/cache/test-runner-vitest.json",POWERSHELL_METACHARACTERS,DISPATCH_FRAMEWORK_MAP,COMPOUND_TEST_EXTENSIONS,TEST_DIRECTORY_NAMES,SOURCE_EXTENSIONS,test_runner;var init_test_runner=__esm(()=>{init_zod();init_discovery();init_analyzer();init_failure_classifier();init_history_store();init_bun_compat();init_path_security();init_create_tool();init_resolve_working_directory();POWERSHELL_METACHARACTERS=/[|;&`$(){}[\]<>"'#*?\x00-\x1f]/;DISPATCH_FRAMEWORK_MAP={bun:"bun",vitest:"vitest",jest:"jest",mocha:"mocha",pytest:"pytest",cargo:"cargo",pester:"pester","go-test":"go-test",maven:"maven",gradle:"gradle","dotnet-test":"dotnet-test",ctest:"ctest","swift-test":"swift-test","dart-test":"dart-test",rspec:"rspec",minitest:"minitest",pest:"pest",phpunit:"phpunit","php-artisan":"php-artisan","bun:test":"bun","xcodebuild-test":"swift-test","flutter test":"dart-test","dart test":"dart-test",Pest:"pest",PHPUnit:"phpunit"};COMPOUND_TEST_EXTENSIONS=[".test.ts",".test.tsx",".test.js",".test.jsx",".tests.ps1",".spec.ts",".spec.tsx",".spec.js",".spec.jsx",".test.ps1",".spec.ps1"],TEST_DIRECTORY_NAMES=["__tests__","tests","test","spec"];SOURCE_EXTENSIONS=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".py",".rs",".ps1",".psm1",".go",".java",".kt",".kts",".cs",".c",".h",".cpp",".hpp",".cc",".cxx",".php",".swift",".dart",".rb",".pyi"]);test_runner=createSwarmTool({description:'Run project tests with framework detection. Supports bun, vitest, jest, mocha, pytest, cargo, pester, go-test, maven, gradle, dotnet-test, ctest, swift-test, dart-test, rspec, and minitest. Returns deterministic normalized JSON with framework, scope, command, totals, coverage, duration, success status, and failures. Use scope "all" for full suite, "convention" to accept direct test files or map source files to test files, "graph" to find related tests via imports from source files, or "impact" to find tests covering changed source files using test-impact analysis.',args:{scope:exports_external.enum(["all","convention","graph","impact"]).optional().describe('Test scope: "all" runs full suite, "convention" accepts direct test files or maps source files to tests by naming, "graph" finds related tests via imports from source files, "impact" finds tests covering changed source files via test-impact analysis'),files:exports_external.array(exports_external.string()).optional().describe('Specific files to test. For "convention", pass source files or direct test files. For "graph" and "impact", pass source files only.'),coverage:exports_external.boolean().optional().describe("Enable coverage reporting if supported"),bail:exports_external.boolean().optional().describe("Stop running tests after the first failure. Default false. Note: coverage may be incomplete when bail=true with coverage=true."),timeout_ms:exports_external.number().optional().describe("Timeout in milliseconds (default 60000, max 300000)"),working_directory:exports_external.string().optional().describe("Explicit project root directory. When provided, tests run relative to this path instead of the plugin context directory. Use this when CWD differs from the actual project root.")},async execute(args2,directory){let workingDirInput;if(args2&&typeof args2==="object"){let obj=args2;workingDirInput=typeof obj.working_directory==="string"?obj.working_directory:void 0}let dirResult=resolveWorkingDirectory(workingDirInput,directory);if(!dirResult.success){let errorResult={success:!1,framework:"none",scope:"all",error:dirResult.message,outcome:"error"};return JSON.stringify(errorResult,null,2)}let workingDir=dirResult.directory;if(workingDir.length>4096)return JSON.stringify({success:!1,framework:"none",scope:"all",error:"Invalid working directory",outcome:"error"},null,2);if(/^[/\\]{2}/.test(workingDir))return JSON.stringify({success:!1,framework:"none",scope:"all",error:"Invalid working directory",outcome:"error"},null,2);if(containsControlChars(workingDir))return JSON.stringify({success:!1,framework:"none",scope:"all",error:"Invalid working directory",outcome:"error"},null,2);if(containsPathTraversal(workingDir))return JSON.stringify({success:!1,framework:"none",scope:"all",error:"Invalid working directory",outcome:"error"},null,2);if(!validateArgs2(args2))return JSON.stringify({success:!1,framework:"none",scope:"all",error:"Invalid arguments",message:'scope must be "all", "convention", "graph", or "impact"; files must be array of strings; coverage must be boolean; timeout_ms must be a positive number',outcome:"error"},null,2);let scope=args2.scope||"all";if(scope==="all"){if(!process.env.SWARM_ALLOW_FULL_SUITE)return JSON.stringify({success:!1,framework:"none",scope:"all",error:'scope "all" is blocked for agent use. Use scope "convention" with specific test files, or scope "graph" with exactly one source file.',message:'The full test suite is blocked in agent context. Use scope "convention" with specific test files, or scope "graph" with exactly one source file. Example: { scope: "convention", files: ["src/tools/test-runner.ts"] }',outcome:"error"},null,2)}if((scope==="convention"||scope==="graph"||scope==="impact")&&(!args2.files||args2.files.length===0))return JSON.stringify({success:!1,framework:"none",scope,error:'scope "convention" and "graph" require explicit files array - omitting files causes unsafe full-project discovery',message:'When using scope "convention" or "graph", you must provide a non-empty "files" array. Use scope "all" for full project test suite without specifying files.',outcome:"error"},null,2);let _files=args2.files||[],coverage=args2.coverage||!1,bail=args2.bail||!1,timeout_ms=Math.min(args2.timeout_ms||DEFAULT_TIMEOUT_MS,MAX_TIMEOUT_MS),useDispatch=process.env.SWARM_LANG_BACKEND!=="legacy",framework;if(useDispatch){if(framework=await detectTestFrameworkViaDispatch(workingDir),framework==="none")framework=await detectTestFramework(workingDir)}else framework=await detectTestFramework(workingDir);if(framework==="none")return JSON.stringify({success:!1,framework:"none",scope,error:"No test framework detected",message:"No supported test framework found. Install bun, vitest, jest, mocha, pytest, cargo, pester, or a supported language test runner (go test, maven, gradle, dotnet test, ctest, swift test, dart test, rspec, minitest).",totals:{passed:0,failed:0,skipped:0,total:0},outcome:"error"},null,2);let testFiles=[],graphFallbackReason,effectiveScope=scope;if(scope==="all");else if(scope==="convention"){let directTestFiles=args2.files.filter((file3)=>isConventionTestFilePath(file3)),sourceFiles=args2.files.filter((file3)=>{if(directTestFiles.includes(file3))return!1;let ext=path112.extname(file3).toLowerCase();return SOURCE_EXTENSIONS.has(ext)}),invalidFiles=args2.files.filter((file3)=>!directTestFiles.includes(file3)&&!sourceFiles.includes(file3));if(directTestFiles.length===0&&sourceFiles.length===0)return JSON.stringify({success:!1,framework,scope,error:"Provided files contain no recognized source files or direct test files",message:"The files array must contain at least one source file with a recognized extension (.ts, .tsx, .js, .jsx, .py, .rs, .ps1, etc.) or a direct test file in a supported test location/naming convention.",outcome:"error"},null,2);if(invalidFiles.length>0){let errorResult={success:!1,framework,scope,error:"Provided files include entries that are neither recognized source files nor direct test files",message:`These files are not valid for targeted test discovery: ${invalidFiles.join(", ")}`,outcome:"error"};return JSON.stringify(errorResult,null,2)}if(sourceFiles.length>MAX_SAFE_SOURCE_FILES){let errorResult={success:!1,framework,scope,error:`scope "convention" accepts at most ${MAX_SAFE_SOURCE_FILES} source file for discovery (got ${sourceFiles.length}). Treat this as SKIP without retry.`,message:`Too many source files for scope "convention" discovery (${sourceFiles.length} provided, limit is ${MAX_SAFE_SOURCE_FILES}). Call test_runner once per source file, or pass direct test file paths instead of source files.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}testFiles=[...directTestFiles,...getTestFilesFromConvention(sourceFiles,workingDir)].filter((file3,index,items)=>items.indexOf(file3)===index)}else if(scope==="graph"){let sourceFiles=args2.files.filter((f)=>{if(isConventionTestFilePath(f))return!1;let ext=path112.extname(f).toLowerCase();return SOURCE_EXTENSIONS.has(ext)});if(sourceFiles.length===0)return JSON.stringify({success:!1,framework,scope,error:"Provided files contain no source files with recognized extensions",message:'The files array for scope "graph" must contain at least one source file with a recognized extension (.ts, .tsx, .js, .jsx, .py, .rs, .ps1, etc.). Direct test files belong in scope "convention".',outcome:"error"},null,2);if(sourceFiles.length>MAX_SAFE_SOURCE_FILES){let errorResult={success:!1,framework,scope,error:`scope "graph" accepts at most ${MAX_SAFE_SOURCE_FILES} source file (got ${sourceFiles.length}). Treat this as SKIP without retry.`,message:`Too many source files for scope "graph" (${sourceFiles.length} provided, limit is ${MAX_SAFE_SOURCE_FILES}). Call test_runner once per source file, or use scope "convention" with direct test file paths.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}let estimate=await estimateFanOut(sourceFiles,workingDir);if(estimate.estimatedCount>MAX_SAFE_TEST_FILES){let errorResult={success:!1,framework,scope,error:"Estimated test file count exceeds safe maximum",message:`Scope "graph" resolution would produce approximately ${estimate.estimatedCount} test files, which exceeds the safe limit of ${MAX_SAFE_TEST_FILES}. Break the source files into smaller batches and retry.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}let graphTestFiles=await getTestFilesFromGraph(sourceFiles,workingDir);if(graphTestFiles.length>0)testFiles=graphTestFiles;else graphFallbackReason="imports resolution returned no results, falling back to convention",effectiveScope="convention",testFiles=getTestFilesFromConvention(sourceFiles,workingDir)}else if(scope==="impact"){let sourceFiles=args2.files.filter((f)=>{if(isConventionTestFilePath(f))return!1;let ext=path112.extname(f).toLowerCase();return SOURCE_EXTENSIONS.has(ext)});if(sourceFiles.length===0)return JSON.stringify({success:!1,framework,scope,error:"Provided files contain no source files with recognized extensions",message:'The files array for scope "impact" must contain at least one source file with a recognized extension (.ts, .tsx, .js, .jsx, .py, .rs, .ps1, etc.). Direct test files belong in scope "convention".',outcome:"error"},null,2);if(sourceFiles.length>MAX_SAFE_SOURCE_FILES){let errorResult={success:!1,framework,scope,error:`scope "impact" accepts at most ${MAX_SAFE_SOURCE_FILES} source file (got ${sourceFiles.length}). Treat this as SKIP without retry.`,message:`Too many source files for scope "impact" (${sourceFiles.length} provided, limit is ${MAX_SAFE_SOURCE_FILES}). Call test_runner once per source file, or use scope "convention" with direct test file paths.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}let estimate=await estimateFanOut(sourceFiles,workingDir);if(estimate.estimatedCount>MAX_SAFE_TEST_FILES){let errorResult={success:!1,framework,scope,error:"Estimated test file count exceeds safe maximum",message:`Scope "impact" resolution would produce approximately ${estimate.estimatedCount} test files, which exceeds the safe limit of ${MAX_SAFE_TEST_FILES}. Break the source files into smaller batches and retry.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}try{let impactResult=await analyzeImpact(sourceFiles,workingDir,MAX_SAFE_TEST_FILES);if(impactResult.budgetExceeded){let errorResult={success:!1,framework,scope,error:"Budget exceeded during impact analysis",message:`Impact analysis exceeded safe budget of ${MAX_SAFE_TEST_FILES} test files.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}if(impactResult.impactedTests.length>0)testFiles=impactResult.impactedTests.map((absPath)=>{let relativePath=path112.relative(workingDir,absPath);return path112.isAbsolute(relativePath)?absPath:relativePath});else{graphFallbackReason="no impacted tests found via impact analysis, falling back to graph",effectiveScope="graph";let graphTestFiles=await getTestFilesFromGraph(sourceFiles,workingDir);if(graphTestFiles.length>0)testFiles=graphTestFiles;else graphFallbackReason="imports resolution returned no results, falling back to convention",effectiveScope="convention",testFiles=getTestFilesFromConvention(sourceFiles,workingDir)}}catch{graphFallbackReason="impact analysis failed, falling back to graph",effectiveScope="graph";let graphTestFiles=await getTestFilesFromGraph(sourceFiles,workingDir);if(graphTestFiles.length>0)testFiles=graphTestFiles;else graphFallbackReason="imports resolution returned no results, falling back to convention",effectiveScope="convention",testFiles=getTestFilesFromConvention(sourceFiles,workingDir)}}if(scope!=="all"&&testFiles.length===0){let errorResult={success:!1,framework,scope:effectiveScope,error:"Provided source files resolved to zero test files",message:graphFallbackReason?`No matching test files found for the provided source files. Check that test files exist with matching naming conventions (.spec.*, .test.*, .Tests.ps1, __tests__/, tests/, test/, spec/). (${graphFallbackReason})`:"No matching test files found for the provided source files. Check that test files exist with matching naming conventions (.spec.*, .test.*, .Tests.ps1, __tests__/, tests/, test/, spec/).",outcome:"skip",...scope==="graph"&&{attempted_scope:"graph"},...scope==="impact"&&{attempted_scope:"graph"}};return JSON.stringify(errorResult,null,2)}if(scope!=="all"&&testFiles.length>MAX_SAFE_TEST_FILES){let sampleFiles=testFiles.slice(0,5),errorResult={success:!1,framework,scope:effectiveScope,error:`Resolved test file count (${testFiles.length}) exceeds safe maximum (${MAX_SAFE_TEST_FILES})`,message:`Too many test files resolved (${testFiles.length}). Maximum allowed is ${MAX_SAFE_TEST_FILES}. Treat this as SKIP without retry. Provide more specific source files to narrow down test scope. First few resolved: ${sampleFiles.join(", ")}`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}let result=await runTests(framework,effectiveScope,testFiles,coverage,timeout_ms,workingDir,bail);recordAndAnalyzeResults(result,testFiles,workingDir,_files.length>0?_files:void 0,result.testCases);let historyReport;if(!result.success&&result.totals&&result.totals.failed>0){if(historyReport=analyzeFailures(workingDir),historyReport.quarantinedFailures.length>0)result.message=(result.message||"")+` | QUARANTINED (flaky): ${historyReport.quarantinedFailures.join(", ")}`;if(historyReport.failureClusters.length>0){let clusterSummary=historyReport.failureClusters.slice(0,3).map((c)=>`${c.classification}: ${c.rootCause.substring(0,80)}`).join("; ");result.message=`${result.message||""} | FAILURE ANALYSIS: ${clusterSummary}`}}if(graphFallbackReason&&result.message)result.message=`${result.message} (${graphFallbackReason})`;if(bail&&coverage&&result.message)result.message=`${result.message} (coverage may be incomplete: bail=true stopped early)`;return JSON.stringify(result,null,2)}})});import*as fs57 from"node:fs";import*as path113 from"node:path";function validateDirectoryPath(dir){if(!dir||typeof dir!=="string")throw Error("Directory path is required");if(dir.includes(".."))throw Error("Directory path must not contain path traversal sequences");let normalized=path113.normalize(dir);return path113.isAbsolute(normalized)?normalized:path113.resolve(normalized)}function validateTimeout(timeoutMs,defaultValue){if(timeoutMs===void 0)return defaultValue;if(typeof timeoutMs!=="number"||!Number.isFinite(timeoutMs))throw Error("Timeout must be a finite number");if(timeoutMs<=0)throw Error("Timeout must be greater than 0");if(timeoutMs<MIN_CHECK_TIMEOUT_MS)throw Error(`Timeout must be at least ${MIN_CHECK_TIMEOUT_MS}ms (5 seconds)`);if(timeoutMs>MAX_CHECK_TIMEOUT_MS)throw Error(`Timeout must not exceed ${MAX_CHECK_TIMEOUT_MS}ms (5 minutes)`);return timeoutMs}function getPackageVersion(dir){try{let packagePath=path113.join(dir,"package.json");if(fs57.existsSync(packagePath)){let content=fs57.readFileSync(packagePath,"utf-8");return JSON.parse(content).version??null}}catch{}return null}function getChangelogVersion(dir){try{let changelogPath=path113.join(dir,"CHANGELOG.md");if(fs57.existsSync(changelogPath)){let match=fs57.readFileSync(changelogPath,"utf-8").match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);if(match)return match[1]}}catch{}return null}function getVersionFileVersion(dir){let possibleFiles=["VERSION.txt","version.txt","VERSION","version"];for(let file3 of possibleFiles){let filePath=path113.join(dir,file3);if(fs57.existsSync(filePath))try{let match=fs57.readFileSync(filePath,"utf-8").trim().match(/(\d+\.\d+\.\d+)/);if(match)return match[1]}catch{}}return null}async function runVersionCheck2(dir,_timeoutMs){let startTime=Date.now();try{let packageVersion=_internals76.getPackageVersion(dir),changelogVersion=_internals76.getChangelogVersion(dir),versionFileVersion=_internals76.getVersionFileVersion(dir),versions3=[];if(packageVersion)versions3.push(`package.json: ${packageVersion}`);if(changelogVersion)versions3.push(`CHANGELOG.md: ${changelogVersion}`);if(versionFileVersion)versions3.push(`version file: ${versionFileVersion}`);if(new Set([packageVersion,changelogVersion,versionFileVersion].filter(Boolean)).size<=1){if(versions3.length===0)return{type:"version",status:"skip",message:"No version information found to check",details:{},durationMs:Date.now()-startTime};return{type:"version",status:"pass",message:`Version consistent: ${versions3.join(", ")}`,details:{packageVersion,changelogVersion,versionFileVersion},durationMs:Date.now()-startTime}}return{type:"version",status:"fail",message:`Version mismatch: ${versions3.join("; ")}`,details:{packageVersion,changelogVersion,versionFileVersion},durationMs:Date.now()-startTime}}catch(error93){return{type:"version",status:"error",message:`Version check failed: ${error93 instanceof Error?error93.message:String(error93)}`,durationMs:Date.now()-startTime}}}async function runLintCheck(dir,linter,timeoutMs){let startTime=Date.now();try{let lintPromise=runLint(linter,"check",dir),timeoutId,timeoutPromise=new Promise((_,reject)=>{timeoutId=setTimeout(()=>{reject(Error(`Lint check timed out after ${timeoutMs}ms`))},timeoutMs)}),result=await Promise.race([lintPromise,timeoutPromise]).finally(()=>clearTimeout(timeoutId));if(!result.success)return{type:"lint",status:"error",message:result.error??"Lint check failed",details:{linter,success:result.success},durationMs:Date.now()-startTime};if(result.exitCode!==0){let issueMatch=result.output.match(/(\d+)\s+(issues?|errors?)/i),issueCount=issueMatch?parseInt(issueMatch[1],10):void 0;return{type:"lint",status:"fail",message:issueCount?`Lint found ${issueCount} issue(s)`:"Lint found issues",details:{linter,exitCode:result.exitCode,issueCount,hasOutput:result.output.length>0},durationMs:Date.now()-startTime}}return{type:"lint",status:"pass",message:"Lint check passed",details:{linter,exitCode:result.exitCode},durationMs:Date.now()-startTime}}catch(error93){if(error93 instanceof Error&&error93.message.includes("timed out"))return{type:"lint",status:"error",message:error93.message,details:{linter},durationMs:Date.now()-startTime};return{type:"lint",status:"error",message:`Lint check failed: ${error93 instanceof Error?error93.message:String(error93)}`,details:{linter},durationMs:Date.now()-startTime}}}async function runTestsCheck(_dir,scope,timeoutMs){let startTime=Date.now();try{let result=await runTests("none",scope,[],!1,timeoutMs,_dir,!1);if(!result.success)return{type:"tests",status:"error",message:result.error??"Tests check failed",details:{framework:result.framework,scope,success:result.success},durationMs:Date.now()-startTime};if(result.totals.failed>0)return{type:"tests",status:"fail",message:`Tests failed: ${result.totals.failed}/${result.totals.total} failed`,details:{framework:result.framework,scope,totals:result.totals},durationMs:Date.now()-startTime};if(result.totals.total===0)return{type:"tests",status:"skip",message:"No tests found to run",details:{framework:result.framework,scope},durationMs:Date.now()-startTime};return{type:"tests",status:"pass",message:`Tests passed: ${result.totals.passed} passed`,details:{framework:result.framework,scope,totals:result.totals},durationMs:Date.now()-startTime}}catch(error93){if(error93 instanceof Error&&(error93.message.includes("timeout")||error93.message.includes("ETIMEDOUT")))return{type:"tests",status:"error",message:`Tests check timed out after ${timeoutMs}ms`,durationMs:Date.now()-startTime};return{type:"tests",status:"error",message:`Tests check failed: ${error93 instanceof Error?error93.message:String(error93)}`,durationMs:Date.now()-startTime}}}async function runSecretsCheck(dir,timeoutMs){let startTime=Date.now();try{let secretsPromise=runSecretscan(dir),timeoutPromise=new Promise((_,reject)=>{setTimeout(()=>{reject(Error(`Secrets check timed out after ${timeoutMs}ms`))},timeoutMs)}),result=await Promise.race([secretsPromise,timeoutPromise]);if(result.findings&&result.findings.length>0){let critical=result.findings.filter((f)=>f.severity==="critical").length,high=result.findings.filter((f)=>f.severity==="high").length;return{type:"secrets",status:"fail",message:`Found ${result.findings.length} secret(s): ${critical} critical, ${high} high`,details:{count:result.count,critical,high,filesScanned:result.files_scanned},durationMs:Date.now()-startTime}}return{type:"secrets",status:"pass",message:"No secrets detected",details:{filesScanned:result.files_scanned},durationMs:Date.now()-startTime}}catch(error93){if(error93 instanceof Error&&error93.name==="AbortError")return{type:"secrets",status:"error",message:`Secrets check timed out after ${timeoutMs}ms`,durationMs:Date.now()-startTime};return{type:"secrets",status:"error",message:`Secrets check failed: ${error93 instanceof Error?error93.message:String(error93)}`,durationMs:Date.now()-startTime}}}async function runEvidenceCheck(dir){let startTime=Date.now();try{let plan=await loadPlan(dir);if(!plan)return{type:"evidence",status:"skip",message:"No plan found to check evidence against",details:{},durationMs:Date.now()-startTime};let completedTaskIds=[];for(let phase of plan.phases)for(let task of phase.tasks)if(task.status==="completed")completedTaskIds.push(task.id);if(completedTaskIds.length===0)return{type:"evidence",status:"skip",message:"No completed tasks yet",details:{completedTasks:0},durationMs:Date.now()-startTime};let evidenceTaskIds=new Set(await listEvidenceTaskIds(dir)),missingEvidence=[];for(let id of completedTaskIds){let gateStatus=await getDurableGateEvidenceStatusForTask(dir,id);if(gateStatus.isComplete)continue;if(gateStatus.evidenceExists&&gateStatus.missingGates.length>0){missingEvidence.push(id);continue}if(evidenceTaskIds.has(id))continue;missingEvidence.push(id)}let completedWithEvidence=completedTaskIds.length-missingEvidence.length;if(missingEvidence.length>0)return{type:"evidence",status:"fail",message:`${missingEvidence.length} completed task(s) missing evidence`,details:{totalCompleted:completedTaskIds.length,totalWithEvidence:completedWithEvidence,missingTasks:missingEvidence.slice(0,10),missingCount:missingEvidence.length},durationMs:Date.now()-startTime};return{type:"evidence",status:"pass",message:`All ${completedTaskIds.length} completed tasks have evidence`,details:{totalCompleted:completedTaskIds.length,totalWithEvidence:completedWithEvidence},durationMs:Date.now()-startTime}}catch(error93){return{type:"evidence",status:"error",message:`Evidence check failed: ${error93 instanceof Error?error93.message:String(error93)}`,durationMs:Date.now()-startTime}}}async function runRequirementCoverageCheck(dir,currentPhase){let startTime=Date.now();try{if(readEffectiveSpecSync(dir)===null)return{type:"req_coverage",status:"skip",message:"No effective spec found, requirement coverage not required",details:{},durationMs:Date.now()-startTime};let coverage=await checkRequirementCoverage(currentPhase,dir);if(coverage.exists)return{type:"req_coverage",status:"pass",message:"Requirement coverage report found",details:{path:coverage.path},durationMs:Date.now()-startTime};return{type:"req_coverage",status:"fail",message:"Requirement coverage report missing but effective spec exists",details:{expectedPath:coverage.path},durationMs:Date.now()-startTime}}catch(error93){return{type:"req_coverage",status:"error",message:`Requirement coverage check failed: ${error93 instanceof Error?error93.message:String(error93)}`,durationMs:Date.now()-startTime}}}async function runPreflight(dir,phase,config3){let startTime=Date.now(),reportId=`preflight-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,validatedDir;try{validatedDir=_internals76.validateDirectoryPath(dir)}catch(error93){return{id:reportId,timestamp:startTime,phase,overall:"fail",checks:[{type:"lint",status:"error",message:`Invalid directory: ${error93 instanceof Error?error93.message:String(error93)}`}],totalDurationMs:Date.now()-startTime,message:"Preflight aborted: invalid directory"}}let validatedTimeout;try{validatedTimeout=_internals76.validateTimeout(config3?.checkTimeoutMs,DEFAULT_CONFIG.checkTimeoutMs)}catch(error93){return{id:reportId,timestamp:startTime,phase,overall:"fail",checks:[{type:"lint",status:"error",message:`Invalid config: ${error93 instanceof Error?error93.message:String(error93)}`}],totalDurationMs:Date.now()-startTime,message:"Preflight aborted: invalid configuration"}}let cfg={checkTimeoutMs:validatedTimeout,skipTests:config3?.skipTests??DEFAULT_CONFIG.skipTests,skipSecrets:config3?.skipSecrets??DEFAULT_CONFIG.skipSecrets,skipEvidence:config3?.skipEvidence??DEFAULT_CONFIG.skipEvidence,skipVersion:config3?.skipVersion??DEFAULT_CONFIG.skipVersion,testScope:config3?.testScope??DEFAULT_CONFIG.testScope,linter:config3?.linter??DEFAULT_CONFIG.linter};log("[Preflight] Starting preflight checks",{reportId,phase,config:{skipTests:cfg.skipTests,skipSecrets:cfg.skipSecrets,skipEvidence:cfg.skipEvidence,skipVersion:cfg.skipVersion,testScope:cfg.testScope,linter:cfg.linter}});let checks5=[];log("[Preflight] Running lint check...");let lintResult=await _internals76.runLintCheck(validatedDir,cfg.linter,cfg.checkTimeoutMs);if(checks5.push(lintResult),log(`[Preflight] Lint check: ${lintResult.status} ${lintResult.message}`),!cfg.skipTests){log("[Preflight] Running tests check...");let testsResult=await _internals76.runTestsCheck(validatedDir,cfg.testScope,cfg.checkTimeoutMs);checks5.push(testsResult),log(`[Preflight] Tests check: ${testsResult.status} ${testsResult.message}`)}else checks5.push({type:"tests",status:"skip",message:"Tests check skipped by configuration"});if(!cfg.skipSecrets){log("[Preflight] Running secrets check...");let secretsResult=await _internals76.runSecretsCheck(validatedDir,cfg.checkTimeoutMs);checks5.push(secretsResult),log(`[Preflight] Secrets check: ${secretsResult.status} ${secretsResult.message}`)}else checks5.push({type:"secrets",status:"skip",message:"Secrets check skipped by configuration"});if(!cfg.skipEvidence){log("[Preflight] Running evidence check...");let evidenceResult=await _internals76.runEvidenceCheck(validatedDir);checks5.push(evidenceResult),log(`[Preflight] Evidence check: ${evidenceResult.status} ${evidenceResult.message}`)}else checks5.push({type:"evidence",status:"skip",message:"Evidence check skipped by configuration"});log("[Preflight] Running requirement coverage check...");let reqCoverageResult=await _internals76.runRequirementCoverageCheck(validatedDir,phase);if(checks5.push(reqCoverageResult),log(`[Preflight] Requirement coverage check: ${reqCoverageResult.status} ${reqCoverageResult.message}`),!cfg.skipVersion){log("[Preflight] Running version check...");let versionResult=await _internals76.runVersionCheck(validatedDir,cfg.checkTimeoutMs);checks5.push(versionResult),log(`[Preflight] Version check: ${versionResult.status} ${versionResult.message}`)}else checks5.push({type:"version",status:"skip",message:"Version check skipped by configuration"});let totalDurationMs=Date.now()-startTime,failedChecks=checks5.filter((c)=>c.status==="fail").length,errorChecks=checks5.filter((c)=>c.status==="error").length,skippedChecks=checks5.filter((c)=>c.status==="skip").length,overall,message;if(errorChecks>0)overall="fail",message=`Preflight failed with ${errorChecks} error(s)`;else if(failedChecks>0)overall="fail",message=`Preflight failed: ${failedChecks} check(s) failed`;else if(skippedChecks===checks5.length)overall="skipped",message="All checks were skipped";else overall="pass",message="Preflight passed all checks";return log(`[Preflight] Complete: ${overall} ${message}`),{id:reportId,timestamp:startTime,phase,overall,checks:checks5,totalDurationMs,message}}function formatPreflightMarkdown(report){let lines=["## Preflight Report","",`**Phase**: ${report.phase}`,`**Overall**: ${report.overall==="pass"?"✅ PASS":report.overall==="fail"?"❌ FAIL":"⏭️ SKIPPED"}`,`**Duration**: ${(report.totalDurationMs/1000).toFixed(2)}s`,"","### Checks",""];for(let check3 of report.checks){let icon=check3.status==="pass"?"✅":check3.status==="fail"?"❌":check3.status==="error"?"⚠️":"⏭️";lines.push(`- ${icon} **${check3.type}**: ${check3.message}`)}return lines.push(""),lines.push(report.message),lines.join(`
1713
1713
  `)}async function handlePreflightCommand(directory,_args){let phase=(await loadPlan(directory))?.current_phase??1,report=await _internals76.runPreflight(directory,phase);return _internals76.formatPreflightMarkdown(report)}var MIN_CHECK_TIMEOUT_MS=5000,MAX_CHECK_TIMEOUT_MS=300000,DEFAULT_CONFIG,_internals76;var init_preflight_service=__esm(()=>{init_gate_bridge();init_manager2();init_manager();init_effective_spec();init_lint();init_secretscan();init_test_runner();init_utils();DEFAULT_CONFIG={checkTimeoutMs:60000,skipTests:!1,skipSecrets:!1,skipEvidence:!1,skipVersion:!1,testScope:"convention",linter:"biome"};_internals76={runPreflight,formatPreflightMarkdown,handlePreflightCommand,validateDirectoryPath,validateTimeout,getPackageVersion,getChangelogVersion,getVersionFileVersion,runVersionCheck:runVersionCheck2,runLintCheck,runTestsCheck,runSecretsCheck,runEvidenceCheck,runRequirementCoverageCheck}});var init_preflight=__esm(()=>{init_preflight_service()});async function handlePromoteCommand(directory,args2){let category,lessonId,lessonText;for(let i=0;i<args2.length;i++){let arg=args2[i];if(arg==="--category"&&i+1<args2.length)category=args2[i+1],i++;else if(arg==="--from-swarm"&&i+1<args2.length)lessonId=args2[i+1],i++;else if(!arg.startsWith("--")){lessonText=args2.slice(i).join(" ");break}}if(!lessonText&&!lessonId)return'Usage: /swarm promote "<lesson text>" or /swarm promote --from-swarm <id>';if(lessonId)try{return await promoteFromSwarm(directory,lessonId)}catch(error93){if(error93 instanceof Error)return error93.message;return`Failed to promote lesson: ${error93 instanceof Error?error93.message:String(error93)}`}try{return await promoteToHive(directory,lessonText,category)}catch(error93){if(error93 instanceof Error)return error93.message;return`Failed to promote lesson: ${error93 instanceof Error?error93.message:String(error93)}`}}var init_promote=__esm(()=>{init_hive_promoter()});function isGateName(name){return ALL_GATE_NAMES.includes(name)}function formatGates(gates){return ALL_GATE_NAMES.map((g)=>` - ${g}: ${gates[g]?"on":"off"}`).join(`
1714
1714
  `)}async function handleQaGatesCommand(directory,args2,sessionID){let plan=await loadPlanJsonOnly(directory);if(!plan)return"Error: plan.json not found or invalid. Create a plan first (e.g. /swarm specify or save_plan).";let planId=derivePlanId(plan),subcommand=args2[0]?.toLowerCase(),gateArgs=args2.slice(1);if(!subcommand||subcommand==="show"||subcommand==="status"){let profile=getProfile(directory,planId),spec=profile?profile.gates:DEFAULT_QA_GATES,overrides=(sessionID?getAgentSession(sessionID):null)?.qaGateSessionOverrides??{},effective=profile?getEffectiveGates(profile,overrides):{...DEFAULT_QA_GATES,...overrides},lines=[];if(lines.push(`QA Gate Profile for plan_id=${planId}`),!profile)lines.push(" (no profile persisted yet — showing defaults)");else lines.push(` locked: ${profile.locked_at?`yes @ ${profile.locked_at} (seq ${profile.locked_by_snapshot_seq??"?"})`:"no"}`),lines.push(` profile_hash: ${computeProfileHash(profile)}`);if(lines.push("Spec-level gates:"),lines.push(formatGates(spec)),lines.push("Session overrides (ratchet-tighter only):"),Object.keys(overrides).length===0)lines.push(" (none)");else for(let k of ALL_GATE_NAMES)if(overrides[k]===!0)lines.push(` - ${k}: on (override)`);return lines.push("Effective gates:"),lines.push(formatGates(effective)),lines.join(`
1715
1715
  `)}if(subcommand==="enable"){if(gateArgs.length===0)return"Usage: /swarm qa-gates enable <gate> [<gate> ...]";let invalid=gateArgs.filter((g)=>!isGateName(g));if(invalid.length>0)return`Error: unknown gate(s): ${invalid.join(", ")}. Valid gates: ${ALL_GATE_NAMES.join(", ")}`;getOrCreateProfile(directory,planId);let patch={};for(let g of gateArgs)if(isGateName(g))patch[g]=!0;try{let updated=setGates(directory,planId,patch);return[`Enabled gates persisted for plan_id=${planId}:`,formatGates(updated.gates),`profile_hash: ${computeProfileHash(updated)}`].join(`
@@ -1932,7 +1932,7 @@ Subcommands:
1932
1932
  `+` concurrency status — Show effective concurrency (override, plan baseline, operational effective)
1933
1933
  `+` concurrency reset — Clear the session concurrency override
1934
1934
  `+`
1935
- `+"Session-scoped — resets on new session.",category:"utility",toolPolicy:"none"},simulate:{handler:(ctx)=>handleSimulateCommand(ctx.directory,ctx.args),description:"Dry-run hidden coupling analysis with configurable thresholds",args:"--threshold <number>, --min-commits <number>",category:"diagnostics",toolPolicy:"none"},sdd:{handler:(ctx)=>handleSddCommand(ctx.directory,ctx.args),description:"Manage OpenSpec-compatible SDD artifacts and effective spec projection",args:"status|validate|project [--json] [--change <id>] [--dry-run]",details:"Parent command for spec-driven development artifacts. Use sdd status to inspect .swarm/spec.md plus openspec/ artifacts, sdd validate to validate OpenSpec-compatible deltas, and sdd project to materialize the effective spec into .swarm/spec.md for planning.",category:"utility",toolPolicy:"agent"},"sdd status":{handler:(ctx)=>handleSddStatusCommand(ctx.directory,ctx.args),description:"Show OpenSpec-compatible SDD status and effective spec source",subcommandOf:"sdd",args:"[--json]",category:"utility",toolPolicy:"agent"},"sdd validate":{handler:(ctx)=>handleSddValidateCommand(ctx.directory,ctx.args),description:"Validate OpenSpec-compatible artifacts and effective spec projection",subcommandOf:"sdd",args:"[--json] [--change <id>]",category:"utility",toolPolicy:"agent"},"sdd project":{handler:(ctx)=>handleSddProjectCommand(ctx.directory,ctx.args),description:"Materialize the OpenSpec-compatible effective spec into .swarm/spec.md",subcommandOf:"sdd",args:"[--dry-run] [--overwrite] [--json] [--change <id>]",category:"utility",toolPolicy:"agent"},"sdd-status":{handler:(ctx)=>handleSddStatusCommand(ctx.directory,ctx.args),description:"Show OpenSpec-compatible SDD status and effective spec source",aliasOf:"sdd status",deprecated:!0},"sdd-validate":{handler:(ctx)=>handleSddValidateCommand(ctx.directory,ctx.args),description:"Validate OpenSpec-compatible artifacts and effective spec projection",aliasOf:"sdd validate",deprecated:!0},"sdd-project":{handler:(ctx)=>handleSddProjectCommand(ctx.directory,ctx.args),description:"Materialize the OpenSpec-compatible effective spec into .swarm/spec.md",aliasOf:"sdd project",deprecated:!0},analyze:{handler:(ctx)=>handleAnalyzeCommand(ctx.directory,ctx.args),description:"Analyze spec.md vs plan.md for requirement coverage gaps",args:"",category:"agent",toolPolicy:"none"},clarify:{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleClarifyCommand),description:"Clarify and refine an existing feature specification",args:"[description-text]",category:"agent",toolPolicy:"none"},specify:{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleSpecifyCommand),description:"Generate or import a feature specification [description]",args:"[description-text]",category:"agent",toolPolicy:"none"},brainstorm:{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleBrainstormCommand),description:"Enter architect MODE: BRAINSTORM — structured seven-phase planning workflow [topic]",args:"[topic-text]",details:"Triggers the architect to run the brainstorm workflow: CONTEXT SCAN, single-question DIALOGUE, APPROACHES, DESIGN SECTIONS, SPEC WRITE + SELF-REVIEW, QA GATE SELECTION, TRANSITION. Use for new plans where requirements need to be drawn out before writing spec.md / plan.md.",category:"agent",toolPolicy:"none"},loop:{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleLoopCommand),description:"Enter architect MODE: LOOP — compound-engineering loop: brainstorm → plan → build → review → improve, iterating until done [objective]",args:"<objective> [--max-cycles 1..5] [--autonomy checkpoint|auto] [--depth standard|exhaustive] [--resume]",details:`Triggers the architect to run the compound-engineering loop defined in ${BUNDLED_PROJECT_SKILL_ROOT}/loop/SKILL.md: BRAINSTORM (requirements) → PLAN (+ critic gate) → BUILD (execute) → REVIEW (independent reviewer + critic on the diff, report-only) → IMPROVE (phase-wrap retrospective + compounding learning capture), then evaluate stop conditions and loop for another improvement cycle if the objective is unmet and budget remains. Generator and reviewer/critic run in separate contexts; failing assertions must be fixed at the root cause, never weakened, mocked, or skipped. Defense-in-depth stop conditions: objective met, --max-cycles budget (default 3), no-progress/plateau, oscillation, unrecoverable error, or explicit user stop. --autonomy auto (default) runs unattended with hard stops still enforced; --autonomy checkpoint pauses at phase gates for user approval. --depth exhaustive widens exploration. --resume continues an existing loop run from durable .swarm/loop/ state. Distinct from full-auto (autonomous cross-phase oversight) and turbo (parallel lanes within a phase): loop is a user-initiated, gated, compounding workflow.`,category:"agent",toolPolicy:"none"},council:{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleCouncilCommand),description:"Enter architect MODE: COUNCIL — multi-model deliberation [question] [--preset <name>] [--spec-review]",args:"<question> [--preset <name>] [--spec-review]",details:"Triggers the architect to convene a three-agent General Council: Generalist (reviewer model), Skeptic (critic model), and Domain Expert (SME model). Use --preset <name> to choose a named member preset from council.general.presets. "+"The architect first runs 1–3 targeted web searches and passes a compiled RESEARCH CONTEXT "+"to all three agents before dispatching them in parallel. Agents deliberate using the NSED peer-review protocol (Round 1 independent analysis, Round 2 MAINTAIN/CONCEDE/NUANCE for disagreements). The architect synthesizes the final answer directly from convene_general_council output. --spec-review switches to single-pass advisory mode for spec review. Requires council.general.enabled: true and a search API key in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides.",category:"agent",toolPolicy:"none"},"pr-review":{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handlePrReviewCommand),description:"Launch deep PR review with multi-lane analysis [url] [--council]",args:"<pr-url|owner/repo#N|N> [--council]",details:"Launches a structured PR review: reconstructs PR intent via obligation extraction cascade, launches all 6 fixed base explorer lanes through dispatch_lanes_async while the architect keeps doing non-dependent work, polls collect_lane_results incrementally, runs every triggered micro-lane, validates findings through independent reviewer confirmation, applies critic challenge to HIGH/CRITICAL findings, then synthesizes only after coverage is closed. If lane tools cannot close coverage, Task-tool dispatch is the final verified-equivalent fallback; if equivalence cannot be proven, the review is BLOCKED rather than degraded. --council variant fires adversarial multi-model review. Supports full GitHub URL, owner/repo#N shorthand, or bare PR number (resolves against origin remote).",category:"agent",toolPolicy:"none"},"pr-feedback":{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handlePrFeedbackCommand),description:"Ingest and close known PR feedback (review comments, CI failures, conflicts) [pr] [instructions]",args:"[url|owner/repo#N|N] [instructions...]",details:"Triggers MODE: PR_FEEDBACK — ingests existing pull-request feedback (review threads, requested changes, CI/check failures, merge conflicts, stale branch state, pasted notes), verifies every claim against source, clusters related problems, fixes confirmed items, validates the branch, and reports closure status for every ledger item. Distinct from /swarm pr-review, which discovers new findings. The PR reference is optional: with none, the architect builds the ledger from the current PR/branch; text after the reference is forwarded as extra instructions. Supports full GitHub URL, owner/repo#N shorthand, or bare PR number (resolved against origin).",category:"agent",toolPolicy:"none"},"pr subscribe":{handler:(ctx)=>handlePrSubscribeCommand(ctx.directory,ctx.args,ctx.sessionID),description:"Subscribe the current session to PR state-change notifications",args:"<pr-url|owner/repo#N|N>",details:'Subscribes the current session to PR state-change events for the specified PR. When pr_monitor.enabled is true, the background polling worker detects CI failures, new comments, review state changes (changes requested / approved), merge conflicts and conflict resolutions, and merge/close events — each gated by its pr_monitor notify_* config flag (notify_ci_success defaults to false). Delivery follows pr_monitor.event_delivery: "prompt" (default) wakes the subscribed session with a structured <pr-activity> message; "advisory" queues session-scoped advisories with dedup tokens for the next turn. Subscriptions are idempotent, capped by pr_monitor.max_subscriptions, and agent-callable. Supports full GitHub URL, owner/repo#N shorthand, or bare PR number (resolved against origin). Requires pr_monitor.enabled: true in config.',category:"agent",toolPolicy:"agent"},"pr-subscribe":{handler:(ctx)=>handlePrSubscribeCommand(ctx.directory,ctx.args,ctx.sessionID),description:"Subscribe the current session to PR state-change notifications",aliasOf:"pr subscribe",deprecated:!0},"pr unsubscribe":{handler:(ctx)=>handlePrUnsubscribeCommand(ctx.directory,ctx.args,ctx.sessionID),description:"Unsubscribe the current session from PR state-change notifications",args:"<pr-url|owner/repo#N|N>",details:"Unsubscribes the current session from PR state-change events for the specified PR. Removes the active subscription record (idempotent; agent-callable). Supports full GitHub URL, owner/repo#N shorthand, or bare PR number (resolved against origin).",category:"agent",toolPolicy:"agent"},"pr-unsubscribe":{handler:(ctx)=>handlePrUnsubscribeCommand(ctx.directory,ctx.args,ctx.sessionID),description:"Unsubscribe the current session from PR state-change notifications",aliasOf:"pr unsubscribe",deprecated:!0},"pr status":{handler:(ctx)=>handlePrMonitorStatusCommand(ctx.directory,ctx.args,ctx.sessionID,ctx.source),description:"Show PR monitor subscription status for the current session",args:"",details:"Displays all active PR subscriptions for the current session. Shows PR URL, last checked time, watching status, and error count per subscription. Also shows total active subscriptions across all sessions.",category:"agent",toolPolicy:"agent",toolNoArgs:!0},"pr-status":{handler:(ctx)=>handlePrMonitorStatusCommand(ctx.directory,ctx.args,ctx.sessionID,ctx.source),description:"Show PR monitor subscription status for the current session",aliasOf:"pr status",deprecated:!0},"ci-simulate":{handler:(ctx)=>handleCiSimulateCommand(ctx.directory,ctx.args),description:"Create a temporary merge-result worktree and run CI before merge queue entry",args:"[--base origin/main] [--head <ref>]",details:"Creates a detached temporary worktree under .swarm/ci-simulate from the base ref, merges the current worktree HEAD (or --head ref), runs fixed local CI gates (typecheck, Biome CI, build, unit/integration/security/smoke tests, drift check), then removes the worktree and prunes metadata. Intended as a pre-queue merge_group simulation helper.",category:"agent",toolPolicy:"agent"},"deep-dive":{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleDeepDiveCommand),description:"Launch deep codebase audit with parallel explorer waves, dual reviewers, and critic challenge [scope]",args:"<scope> [--profile standard|security|ux|architecture|full] [--max-explorers 1..8] [--json] [--skip-update] [--allow-dirty]",details:"Runs a read-only deep audit of the specified scope using parallel explorer waves (8-file cap per mission, ~3500 line guardrail), always 2 parallel reviewers for verification, and sequential critic challenge on HIGH/CRITICAL findings. Profiles select explorer lanes: standard (5 lanes), security, ux, architecture, full (all 8 lanes). Emits a structured findings report without mutating source code.",category:"agent",toolPolicy:"none"},"deep dive":{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleDeepDiveCommand),description:"Alias for /swarm deep-dive — launch deep codebase audit",args:"<scope> [--profile standard|security|ux|architecture|full] [--max-explorers 1..8] [--json] [--skip-update] [--allow-dirty]",category:"agent",aliasOf:"deep-dive"},"deep-research":{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleDeepResearchCommand),description:"Launch a multi-source, fact-checked deep research pass and synthesize a cited report [question]",args:"<question> [--depth standard|exhaustive] [--max-researchers 1..6] [--rounds 1..4] [--brief]",details:"Runs the orchestrator-worker deep-research protocol: the architect decomposes the question into subtopics, gathers evidence with web_search and web_fetch across up to N iterative rounds, dispatches parallel sme synthesis workers, verifies every claim against cited sources with dual reviewers, challenges high-stakes claims with the critic, and presents a cited report in chat. Read-only — does not mutate source code, delegate to coder, or call declare_scope. Requires council.general.enabled and a search API key.",category:"agent",toolPolicy:"none"},"deep research":{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleDeepResearchCommand),description:"Alias for /swarm deep-research — launch a cited deep research pass",args:"<question> [--depth standard|exhaustive] [--max-researchers 1..6] [--rounds 1..4] [--brief]",category:"agent",aliasOf:"deep-research"},"codebase-review":{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleCodebaseReviewCommand),description:"Launch codebase-review-swarm for a quote-grounded full-repo or large-subsystem audit",args:"[scope] [--mode phase0|complete|defect|security|correctness|testing|ui|performance|ai-slop|enhancements|custom] [--tracks <list>] [--continue <run-id>] [--json] [--skip-update] [--allow-dirty]",details:"Runs the codebase-review-swarm workflow: Phase 0 inventory, selected-track depth planning, non-diluting review passes, coverage closure, reviewer validation, critic challenge, and .swarm/review-v8 artifacts. Materializes the bundled skill package if missing, then emits a MODE signal; the architect workflow must not mutate source files.",category:"agent",toolPolicy:"none"},"codebase review":{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleCodebaseReviewCommand),description:"Alias for /swarm codebase-review - launch codebase-review-swarm",args:"[scope] [--mode phase0|complete|defect|security|correctness|testing|ui|performance|ai-slop|enhancements|custom] [--tracks <list>] [--continue <run-id>] [--json] [--skip-update] [--allow-dirty]",category:"agent",aliasOf:"codebase-review"},"design-docs":{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleDesignDocsCommand),description:"Generate or sync language-agnostic design docs (domain, technical-spec, behavior-spec, reference/) for the project under build [description]",args:"<description> [--out <dir>] [--lang <name>] [--update]",details:"Triggers the architect to enter MODE: DESIGN_DOCS — delegates to the docs_design agent to author/sync docs/domain.md, docs/technical-spec.md, docs/behavior-spec.md, and docs/reference/* (plus reference/traceability.json and design-changelog.md). Normative docs are 100% language-agnostic; all framework-specific material is quarantined under reference/. --update syncs existing docs to current code/spec instead of generating fresh. Requires design_docs.enabled: true.",category:"agent",toolPolicy:"none"},"design docs":{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleDesignDocsCommand),description:"Alias for /swarm design-docs — generate or sync design docs",args:"<description> [--out <dir>] [--lang <name>] [--update]",category:"agent",aliasOf:"design-docs"},issue:{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleIssueCommand),description:"Ingest a GitHub issue into the swarm workflow [url] [--plan] [--trace] [--no-repro]",args:"<issue-url|owner/repo#N|N> [--plan] [--trace] [--no-repro]",details:"Triggers the architect to enter MODE: ISSUE_INGEST — ingests a GitHub issue, restructures it into a normalized intake note, localizes root cause through hypothesis-driven tracing, and outputs a resolution spec. --plan transitions to plan creation after spec generation. --trace runs the full fix-and-PR workflow (implies --plan). --no-repro skips the reproduction step. Supports full GitHub URL, owner/repo#N shorthand, or bare issue number (resolves against origin remote).",category:"agent",toolPolicy:"none"},"qa-gates":{handler:(ctx)=>handleQaGatesCommand(ctx.directory,ctx.args,ctx.sessionID),description:"View or modify QA gate profile for the current plan [enable|override <gate>...]",args:"[show|enable|override] <gate>...",details:"show: display spec-level, session-override, and effective QA gates for the current plan. enable: persist gate(s) into the locked-once profile (architect; rejected after critic approval lock). override: session-only ratchet-tighter enable. Valid gates: reviewer, test_engineer, council_mode, sme_enabled, critic_pre_plan, hallucination_guard, sast_enabled, mutation_test, phase_council, drift_check, final_council.",category:"config",toolPolicy:"none"},link:{handler:(ctx)=>handleLinkCommand(ctx.directory,ctx.args),description:"Tie this worktree to a shared swarm knowledge store [name]",details:"Links the current worktree to a shared knowledge store so multiple swarms working on the same project (e.g. separate git worktrees) pool their lessons instead of each keeping an isolated .swarm/knowledge.jsonl. With no name, ties all worktrees of the same repo via the project hash; with a name, ties any worktrees/repos that use the same name. Existing local lessons are merged (deduped) into the shared store. Use `/swarm link status` to inspect.",args:"[<name> | status]",category:"utility",toolPolicy:"none"},"link status":{handler:(ctx)=>handleLinkCommand(ctx.directory,["status"]),description:"Show whether this worktree shares knowledge via a link",subcommandOf:"link",category:"utility",toolPolicy:"none"},unlink:{handler:(ctx)=>handleUnlinkCommand(ctx.directory,ctx.args),description:"Stop sharing swarm knowledge for this worktree [--no-copy]",details:"Unlinks the current worktree from its shared knowledge store and returns it to a local .swarm/knowledge.jsonl. By default the shared lessons are copied back into the local store (deduped) so nothing is lost; pass --no-copy to skip the copy-back.",args:"[--no-copy]",category:"utility",toolPolicy:"none"},promote:{handler:(ctx)=>handlePromoteCommand(ctx.directory,ctx.args),description:"Manually promote lesson to hive knowledge",details:"Promotes a lesson directly to hive knowledge (--category flag sets category) or references an existing swarm lesson by ID (--from-swarm). Validates lesson text before promotion. Either direct text or --from-swarm ID is required.",args:"--category <category>, --from-swarm <lesson-id>, <lesson-text>",category:"utility",toolPolicy:"none"},reset:{handler:(ctx)=>handleResetCommand(ctx.directory,ctx.args),description:"Clear swarm state files [--confirm]",details:"DELETES plan.md, context.md, and summaries/ directory from .swarm/. Stops background automation and clears in-memory queues. SAFETY: requires --confirm flag — without it, displays a warning and tips to export first.",args:"--confirm (required)",category:"utility",clashesWithNativeCcCommand:"/reset",toolPolicy:"restricted"},"reset-session":{handler:(ctx)=>handleResetSessionCommand(ctx.directory,ctx.args),description:"Clear session state while preserving plan, evidence, and knowledge",details:"Deletes only .swarm/session/state.json and any other session files. Clears in-memory agent sessions and delegation chains. Preserves plan, evidence, and knowledge for cross-session continuity.",args:"",category:"utility",toolPolicy:"restricted"},rollback:{handler:(ctx)=>handleRollbackCommand(ctx.directory,ctx.args),description:"Restore swarm state or project files to a checkpoint",details:"Restores legacy .swarm/ phase checkpoints from checkpoints/phase-<N> when present. Otherwise restores named git checkpoints from .swarm/checkpoints.json by label or list number. Writes rollback event to events.jsonl. Without an argument, lists available checkpoints.",args:"<phase-number|label|list-number>",category:"utility",toolPolicy:"restricted"},retrieve:{handler:(ctx)=>handleRetrieveCommand(ctx.directory,ctx.args),description:"Retrieve full output from a summary <id>",args:"<summary-id>",details:"Loads the full tool output that was previously summarized (referenced by IDs like S1, S2). Use when you need the complete output instead of the truncated summary.",category:"utility",toolPolicy:"agent"},handoff:{handler:(ctx)=>handleHandoffCommand(ctx.directory,ctx.args,ctx.sessionID),description:"Prepare state for clean model switch (new session)",args:"",details:"Generates handoff.md with full session state snapshot, including plan progress, recent decisions, and agent delegation history. Prepended to the next session prompt for seamless model switches.",category:"core",toolPolicy:"none"},turbo:{handler:(ctx)=>handleTurboCommand(ctx.directory,ctx.args,ctx.sessionID),description:"Toggle Turbo Mode strategy for the active session [on|off|lean|standard|epic|status]",args:"on, off, lean, standard, epic, status",details:`Toggles Turbo Mode for the current session. Supports three strategies:
1935
+ `+"Session-scoped — resets on new session.",category:"utility",toolPolicy:"none"},simulate:{handler:(ctx)=>handleSimulateCommand(ctx.directory,ctx.args),description:"Dry-run hidden coupling analysis with configurable thresholds",args:"--threshold <number>, --min-commits <number>",category:"diagnostics",toolPolicy:"none"},sdd:{handler:(ctx)=>handleSddCommand(ctx.directory,ctx.args),description:"Manage OpenSpec-compatible SDD artifacts and effective spec projection",args:"status|validate|project [--json] [--change <id>] [--dry-run]",details:"Parent command for spec-driven development artifacts. Use sdd status to inspect .swarm/spec.md plus openspec/ artifacts, sdd validate to validate OpenSpec-compatible deltas, and sdd project to materialize the effective spec into .swarm/spec.md for planning.",category:"utility",toolPolicy:"agent"},"sdd status":{handler:(ctx)=>handleSddStatusCommand(ctx.directory,ctx.args),description:"Show OpenSpec-compatible SDD status and effective spec source",subcommandOf:"sdd",args:"[--json]",category:"utility",toolPolicy:"agent"},"sdd validate":{handler:(ctx)=>handleSddValidateCommand(ctx.directory,ctx.args),description:"Validate OpenSpec-compatible artifacts and effective spec projection",subcommandOf:"sdd",args:"[--json] [--change <id>]",category:"utility",toolPolicy:"agent"},"sdd project":{handler:(ctx)=>handleSddProjectCommand(ctx.directory,ctx.args),description:"Materialize the OpenSpec-compatible effective spec into .swarm/spec.md",subcommandOf:"sdd",args:"[--dry-run] [--overwrite] [--json] [--change <id>]",category:"utility",toolPolicy:"agent"},"sdd-status":{handler:(ctx)=>handleSddStatusCommand(ctx.directory,ctx.args),description:"Show OpenSpec-compatible SDD status and effective spec source",aliasOf:"sdd status",deprecated:!0},"sdd-validate":{handler:(ctx)=>handleSddValidateCommand(ctx.directory,ctx.args),description:"Validate OpenSpec-compatible artifacts and effective spec projection",aliasOf:"sdd validate",deprecated:!0},"sdd-project":{handler:(ctx)=>handleSddProjectCommand(ctx.directory,ctx.args),description:"Materialize the OpenSpec-compatible effective spec into .swarm/spec.md",aliasOf:"sdd project",deprecated:!0},analyze:{handler:(ctx)=>handleAnalyzeCommand(ctx.directory,ctx.args),description:"Analyze spec.md vs plan.md for requirement coverage gaps",args:"",category:"agent",toolPolicy:"none"},clarify:{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleClarifyCommand),description:"Clarify and refine an existing feature specification",args:"[description-text]",category:"agent",toolPolicy:"none"},specify:{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleSpecifyCommand),description:"Generate or import a feature specification [description]",args:"[description-text]",category:"agent",toolPolicy:"none"},brainstorm:{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleBrainstormCommand),description:"Enter architect MODE: BRAINSTORM — structured seven-phase planning workflow [topic]",args:"[topic-text]",details:"Triggers the architect to run the brainstorm workflow: CONTEXT SCAN, single-question DIALOGUE, APPROACHES, DESIGN SECTIONS, SPEC WRITE + SELF-REVIEW, QA GATE SELECTION, TRANSITION. Use for new plans where requirements need to be drawn out before writing spec.md / plan.md.",category:"agent",toolPolicy:"none"},loop:{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleLoopCommand),description:"Enter architect MODE: LOOP — compound-engineering loop: brainstorm → plan → build → review → improve, iterating until done [objective]",args:"<objective> [--max-cycles 1..5] [--autonomy checkpoint|auto] [--depth standard|exhaustive] [--resume]",details:`Triggers the architect to run the compound-engineering loop defined in ${BUNDLED_PROJECT_SKILL_ROOT}/loop/SKILL.md: BRAINSTORM (requirements) → PLAN (+ critic gate) → BUILD (execute) → REVIEW (independent reviewer + critic on the diff, report-only) → IMPROVE (phase-wrap retrospective + compounding learning capture), then evaluate stop conditions and loop for another improvement cycle if the objective is unmet and budget remains. Generator and reviewer/critic run in separate contexts; failing assertions must be fixed at the root cause, never weakened, mocked, or skipped. Defense-in-depth stop conditions: objective met, --max-cycles budget (default 3), no-progress/plateau, oscillation, unrecoverable error, or explicit user stop. --autonomy auto (default) runs unattended with hard stops still enforced; --autonomy checkpoint pauses at phase gates for user approval. --depth exhaustive widens exploration. --resume continues an existing loop run from durable .swarm/loop/ state. Distinct from full-auto (autonomous cross-phase oversight) and turbo (parallel lanes within a phase): loop is a user-initiated, gated, compounding workflow.`,category:"agent",toolPolicy:"none"},council:{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleCouncilCommand),description:"Enter architect MODE: COUNCIL — multi-model deliberation [question] [--spec-review]",args:"<question> [--spec-review]",details:"Triggers the architect to convene a three-agent General Council: Generalist (reviewer model), Skeptic (critic model), and Domain Expert (SME model). "+"The architect first runs 1–3 targeted web searches and passes a compiled RESEARCH CONTEXT "+"to all three agents before dispatching them in parallel. Agents deliberate using the NSED peer-review protocol (Round 1 independent analysis, Round 2 MAINTAIN/CONCEDE/NUANCE for disagreements). The architect synthesizes the final answer directly from convene_general_council output. --spec-review switches to single-pass advisory mode for spec review. Requires council.general.enabled: true and a search API key in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides.",category:"agent",toolPolicy:"none"},"pr-review":{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handlePrReviewCommand),description:"Launch deep PR review with multi-lane analysis [url] [--council]",args:"<pr-url|owner/repo#N|N> [--council]",details:"Launches a structured PR review: reconstructs PR intent via obligation extraction cascade, launches all 6 fixed base explorer lanes through dispatch_lanes_async while the architect keeps doing non-dependent work, polls collect_lane_results incrementally, runs every triggered micro-lane, validates findings through independent reviewer confirmation, applies critic challenge to HIGH/CRITICAL findings, then synthesizes only after coverage is closed. If lane tools cannot close coverage, Task-tool dispatch is the final verified-equivalent fallback; if equivalence cannot be proven, the review is BLOCKED rather than degraded. --council variant fires adversarial multi-model review. Supports full GitHub URL, owner/repo#N shorthand, or bare PR number (resolves against origin remote).",category:"agent",toolPolicy:"none"},"pr-feedback":{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handlePrFeedbackCommand),description:"Ingest and close known PR feedback (review comments, CI failures, conflicts) [pr] [instructions]",args:"[url|owner/repo#N|N] [instructions...]",details:"Triggers MODE: PR_FEEDBACK — ingests existing pull-request feedback (review threads, requested changes, CI/check failures, merge conflicts, stale branch state, pasted notes), verifies every claim against source, clusters related problems, fixes confirmed items, validates the branch, and reports closure status for every ledger item. Distinct from /swarm pr-review, which discovers new findings. The PR reference is optional: with none, the architect builds the ledger from the current PR/branch; text after the reference is forwarded as extra instructions. Supports full GitHub URL, owner/repo#N shorthand, or bare PR number (resolved against origin).",category:"agent",toolPolicy:"none"},"pr subscribe":{handler:(ctx)=>handlePrSubscribeCommand(ctx.directory,ctx.args,ctx.sessionID),description:"Subscribe the current session to PR state-change notifications",args:"<pr-url|owner/repo#N|N>",details:'Subscribes the current session to PR state-change events for the specified PR. When pr_monitor.enabled is true, the background polling worker detects CI failures, new comments, review state changes (changes requested / approved), merge conflicts and conflict resolutions, and merge/close events — each gated by its pr_monitor notify_* config flag (notify_ci_success defaults to false). Delivery follows pr_monitor.event_delivery: "prompt" (default) wakes the subscribed session with a structured <pr-activity> message; "advisory" queues session-scoped advisories with dedup tokens for the next turn. Subscriptions are idempotent, capped by pr_monitor.max_subscriptions, and agent-callable. Supports full GitHub URL, owner/repo#N shorthand, or bare PR number (resolved against origin). Requires pr_monitor.enabled: true in config.',category:"agent",toolPolicy:"agent"},"pr-subscribe":{handler:(ctx)=>handlePrSubscribeCommand(ctx.directory,ctx.args,ctx.sessionID),description:"Subscribe the current session to PR state-change notifications",aliasOf:"pr subscribe",deprecated:!0},"pr unsubscribe":{handler:(ctx)=>handlePrUnsubscribeCommand(ctx.directory,ctx.args,ctx.sessionID),description:"Unsubscribe the current session from PR state-change notifications",args:"<pr-url|owner/repo#N|N>",details:"Unsubscribes the current session from PR state-change events for the specified PR. Removes the active subscription record (idempotent; agent-callable). Supports full GitHub URL, owner/repo#N shorthand, or bare PR number (resolved against origin).",category:"agent",toolPolicy:"agent"},"pr-unsubscribe":{handler:(ctx)=>handlePrUnsubscribeCommand(ctx.directory,ctx.args,ctx.sessionID),description:"Unsubscribe the current session from PR state-change notifications",aliasOf:"pr unsubscribe",deprecated:!0},"pr status":{handler:(ctx)=>handlePrMonitorStatusCommand(ctx.directory,ctx.args,ctx.sessionID,ctx.source),description:"Show PR monitor subscription status for the current session",args:"",details:"Displays all active PR subscriptions for the current session. Shows PR URL, last checked time, watching status, and error count per subscription. Also shows total active subscriptions across all sessions.",category:"agent",toolPolicy:"agent",toolNoArgs:!0},"pr-status":{handler:(ctx)=>handlePrMonitorStatusCommand(ctx.directory,ctx.args,ctx.sessionID,ctx.source),description:"Show PR monitor subscription status for the current session",aliasOf:"pr status",deprecated:!0},"ci-simulate":{handler:(ctx)=>handleCiSimulateCommand(ctx.directory,ctx.args),description:"Create a temporary merge-result worktree and run CI before merge queue entry",args:"[--base origin/main] [--head <ref>]",details:"Creates a detached temporary worktree under .swarm/ci-simulate from the base ref, merges the current worktree HEAD (or --head ref), runs fixed local CI gates (typecheck, Biome CI, build, unit/integration/security/smoke tests, drift check), then removes the worktree and prunes metadata. Intended as a pre-queue merge_group simulation helper.",category:"agent",toolPolicy:"agent"},"deep-dive":{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleDeepDiveCommand),description:"Launch deep codebase audit with parallel explorer waves, dual reviewers, and critic challenge [scope]",args:"<scope> [--profile standard|security|ux|architecture|full] [--max-explorers 1..8] [--json] [--skip-update] [--allow-dirty]",details:"Runs a read-only deep audit of the specified scope using parallel explorer waves (8-file cap per mission, ~3500 line guardrail), always 2 parallel reviewers for verification, and sequential critic challenge on HIGH/CRITICAL findings. Profiles select explorer lanes: standard (5 lanes), security, ux, architecture, full (all 8 lanes). Emits a structured findings report without mutating source code.",category:"agent",toolPolicy:"none"},"deep dive":{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleDeepDiveCommand),description:"Alias for /swarm deep-dive — launch deep codebase audit",args:"<scope> [--profile standard|security|ux|architecture|full] [--max-explorers 1..8] [--json] [--skip-update] [--allow-dirty]",category:"agent",aliasOf:"deep-dive"},"deep-research":{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleDeepResearchCommand),description:"Launch a multi-source, fact-checked deep research pass and synthesize a cited report [question]",args:"<question> [--depth standard|exhaustive] [--max-researchers 1..6] [--rounds 1..4] [--brief]",details:"Runs the orchestrator-worker deep-research protocol: the architect decomposes the question into subtopics, gathers evidence with web_search and web_fetch across up to N iterative rounds, dispatches parallel sme synthesis workers, verifies every claim against cited sources with dual reviewers, challenges high-stakes claims with the critic, and presents a cited report in chat. Read-only — does not mutate source code, delegate to coder, or call declare_scope. Requires council.general.enabled and a search API key.",category:"agent",toolPolicy:"none"},"deep research":{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleDeepResearchCommand),description:"Alias for /swarm deep-research — launch a cited deep research pass",args:"<question> [--depth standard|exhaustive] [--max-researchers 1..6] [--rounds 1..4] [--brief]",category:"agent",aliasOf:"deep-research"},"codebase-review":{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleCodebaseReviewCommand),description:"Launch codebase-review-swarm for a quote-grounded full-repo or large-subsystem audit",args:"[scope] [--mode phase0|complete|defect|security|correctness|testing|ui|performance|ai-slop|enhancements|custom] [--tracks <list>] [--continue <run-id>] [--json] [--skip-update] [--allow-dirty]",details:"Runs the codebase-review-swarm workflow: Phase 0 inventory, selected-track depth planning, non-diluting review passes, coverage closure, reviewer validation, critic challenge, and .swarm/review-v8 artifacts. Materializes the bundled skill package if missing, then emits a MODE signal; the architect workflow must not mutate source files.",category:"agent",toolPolicy:"none"},"codebase review":{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleCodebaseReviewCommand),description:"Alias for /swarm codebase-review - launch codebase-review-swarm",args:"[scope] [--mode phase0|complete|defect|security|correctness|testing|ui|performance|ai-slop|enhancements|custom] [--tracks <list>] [--continue <run-id>] [--json] [--skip-update] [--allow-dirty]",category:"agent",aliasOf:"codebase-review"},"design-docs":{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleDesignDocsCommand),description:"Generate or sync language-agnostic design docs (domain, technical-spec, behavior-spec, reference/) for the project under build [description]",args:"<description> [--out <dir>] [--lang <name>] [--update]",details:"Triggers the architect to enter MODE: DESIGN_DOCS — delegates to the docs_design agent to author/sync docs/domain.md, docs/technical-spec.md, docs/behavior-spec.md, and docs/reference/* (plus reference/traceability.json and design-changelog.md). Normative docs are 100% language-agnostic; all framework-specific material is quarantined under reference/. --update syncs existing docs to current code/spec instead of generating fresh. Requires design_docs.enabled: true.",category:"agent",toolPolicy:"none"},"design docs":{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleDesignDocsCommand),description:"Alias for /swarm design-docs — generate or sync design docs",args:"<description> [--out <dir>] [--lang <name>] [--update]",category:"agent",aliasOf:"design-docs"},issue:{handler:(ctx)=>handleModeCommandWithBundledSkills(ctx,handleIssueCommand),description:"Ingest a GitHub issue into the swarm workflow [url] [--plan] [--trace] [--no-repro]",args:"<issue-url|owner/repo#N|N> [--plan] [--trace] [--no-repro]",details:"Triggers the architect to enter MODE: ISSUE_INGEST — ingests a GitHub issue, restructures it into a normalized intake note, localizes root cause through hypothesis-driven tracing, and outputs a resolution spec. --plan transitions to plan creation after spec generation. --trace runs the fix workflow end-to-end (implies --plan); compose commit-pr to publish. --no-repro skips the reproduction step. Supports full GitHub URL, owner/repo#N shorthand, or bare issue number (resolves against origin remote).",category:"agent",toolPolicy:"none"},"qa-gates":{handler:(ctx)=>handleQaGatesCommand(ctx.directory,ctx.args,ctx.sessionID),description:"View or modify QA gate profile for the current plan [enable|override <gate>...]",args:"[show|enable|override] <gate>...",details:"show: display spec-level, session-override, and effective QA gates for the current plan. enable: persist gate(s) into the locked-once profile (architect; rejected after critic approval lock). override: session-only ratchet-tighter enable. Valid gates: reviewer, test_engineer, council_mode, sme_enabled, critic_pre_plan, hallucination_guard, sast_enabled, mutation_test, phase_council, drift_check, final_council.",category:"config",toolPolicy:"none"},link:{handler:(ctx)=>handleLinkCommand(ctx.directory,ctx.args),description:"Tie this worktree to a shared swarm knowledge store [name]",details:"Links the current worktree to a shared knowledge store so multiple swarms working on the same project (e.g. separate git worktrees) pool their lessons instead of each keeping an isolated .swarm/knowledge.jsonl. With no name, ties all worktrees of the same repo via the project hash; with a name, ties any worktrees/repos that use the same name. Existing local lessons are merged (deduped) into the shared store. Use `/swarm link status` to inspect.",args:"[<name> | status]",category:"utility",toolPolicy:"none"},"link status":{handler:(ctx)=>handleLinkCommand(ctx.directory,["status"]),description:"Show whether this worktree shares knowledge via a link",subcommandOf:"link",category:"utility",toolPolicy:"none"},unlink:{handler:(ctx)=>handleUnlinkCommand(ctx.directory,ctx.args),description:"Stop sharing swarm knowledge for this worktree [--no-copy]",details:"Unlinks the current worktree from its shared knowledge store and returns it to a local .swarm/knowledge.jsonl. By default the shared lessons are copied back into the local store (deduped) so nothing is lost; pass --no-copy to skip the copy-back.",args:"[--no-copy]",category:"utility",toolPolicy:"none"},promote:{handler:(ctx)=>handlePromoteCommand(ctx.directory,ctx.args),description:"Manually promote lesson to hive knowledge",details:"Promotes a lesson directly to hive knowledge (--category flag sets category) or references an existing swarm lesson by ID (--from-swarm). Validates lesson text before promotion. Either direct text or --from-swarm ID is required.",args:"--category <category>, --from-swarm <lesson-id>, <lesson-text>",category:"utility",toolPolicy:"none"},reset:{handler:(ctx)=>handleResetCommand(ctx.directory,ctx.args),description:"Clear swarm state files [--confirm]",details:"DELETES plan.md, context.md, and summaries/ directory from .swarm/. Stops background automation and clears in-memory queues. SAFETY: requires --confirm flag — without it, displays a warning and tips to export first.",args:"--confirm (required)",category:"utility",clashesWithNativeCcCommand:"/reset",toolPolicy:"restricted"},"reset-session":{handler:(ctx)=>handleResetSessionCommand(ctx.directory,ctx.args),description:"Clear session state while preserving plan, evidence, and knowledge",details:"Deletes only .swarm/session/state.json and any other session files. Clears in-memory agent sessions and delegation chains. Preserves plan, evidence, and knowledge for cross-session continuity.",args:"",category:"utility",toolPolicy:"restricted"},rollback:{handler:(ctx)=>handleRollbackCommand(ctx.directory,ctx.args),description:"Restore swarm state or project files to a checkpoint",details:"Restores legacy .swarm/ phase checkpoints from checkpoints/phase-<N> when present. Otherwise restores named git checkpoints from .swarm/checkpoints.json by label or list number. Writes rollback event to events.jsonl. Without an argument, lists available checkpoints.",args:"<phase-number|label|list-number>",category:"utility",toolPolicy:"restricted"},retrieve:{handler:(ctx)=>handleRetrieveCommand(ctx.directory,ctx.args),description:"Retrieve full output from a summary <id>",args:"<summary-id>",details:"Loads the full tool output that was previously summarized (referenced by IDs like S1, S2). Use when you need the complete output instead of the truncated summary.",category:"utility",toolPolicy:"agent"},handoff:{handler:(ctx)=>handleHandoffCommand(ctx.directory,ctx.args,ctx.sessionID),description:"Prepare state for clean model switch (new session)",args:"",details:"Generates handoff.md with full session state snapshot, including plan progress, recent decisions, and agent delegation history. Prepended to the next session prompt for seamless model switches.",category:"core",toolPolicy:"none"},turbo:{handler:(ctx)=>handleTurboCommand(ctx.directory,ctx.args,ctx.sessionID),description:"Toggle Turbo Mode strategy for the active session [on|off|lean|standard|epic|status]",args:"on, off, lean, standard, epic, status",details:`Toggles Turbo Mode for the current session. Supports three strategies:
1936
1936
 
1937
1937
  `+`**Standard turbo** — skips non-critical QA gates for faster iteration.
1938
1938
  `+`**Lean turbo** — parallel lane execution with per-lane reviewer gates and file-lock conflict detection.
@@ -1990,7 +1990,7 @@ Present the eleven gates with their defaults (DEFAULT_QA_GATES) as a single user
1990
1990
  - drift_check (default: ON) — when enabled, mandatory per-phase drift verification via critic_drift_verifier at PHASE-WRAP; compares implemented changes against spec.md intent; hard-blocks phase_complete when spec.md exists and drift evidence is missing or REJECTED; advisory-only when no spec.md exists (recommended for all projects with a specification)
1991
1991
  - final_council (default: OFF) — when enabled, the full 5-member council (NOT the General Council) reviews the entire project after all phases complete. The architect dispatches the same five council members (\`critic\`, \`reviewer\`, \`sme\`, \`test_engineer\`, \`explorer\`) at project scope, collects \`CouncilMemberVerdict\` objects, and calls \`write_final_council_evidence\`. This is not General Council mode and does not require \`council.general.enabled\`.
1992
1992
 
1993
- Present all three items together in a single message. One message, defaults pre-stated. Wait for the user's answer to all three:
1993
+ Present all four items together in a single message. One message, defaults pre-stated. Wait for the user's answer to all four:
1994
1994
 
1995
1995
  **1. QA Gates** — accept defaults or customize (the eleven gates listed above).
1996
1996
 
@@ -1998,7 +1998,9 @@ Present all three items together in a single message. One message, defaults pre-
1998
1998
 
1999
1999
  **3. Commit Frequency** — "Commit frequency for completed tasks? (default: phase-level only; optional per-task checkpoint commit after each task completion)"
2000
2000
 
2001
- Wait for the user to answer all three in a single reply. Then apply:
2001
+ **4. Auto-proceed** "Auto-advance to the next phase without asking 'Ready for Phase N+1?'? (default: false; runtime toggle via \`/swarm auto-proceed on|off\`)"
2002
+
2003
+ Wait for the user to answer all four in a single reply. Then apply:
2002
2004
 
2003
2005
  - For gates: record the user's gate selections.
2004
2006
  - For parallel coders: if the user says a number > 1, write a \`## Pending Parallelization Config\` section to \`.swarm/context.md\` alongside the gate selection:
@@ -2018,7 +2020,9 @@ If the user accepts the default (1), skip writing this section entirely — seri
2018
2020
  - commit_after_each_completed_task: true
2019
2021
  - recorded_at: <ISO timestamp>
2020
2022
  \`\`\`
2021
- If the user keeps the default phase-level behavior, do not write this section.`}function buildAvailableToolsList(council,memoryEnabled=!1,externalSkillsEnabled=!1,turboEnabled=!1,skillsEnabled=!1){let qaCouncilEnabled=council?.enabled===!0,generalCouncilEnabled=council?.general?.enabled===!0;return[...[...AGENT_TOOL_MAP.architect??[],...memoryEnabled?MEMORY_AGENT_TOOL_MAP.architect??[]:[],...externalSkillsEnabled?EXTERNAL_SKILL_AGENT_TOOL_MAP.architect??[]:[],...qaCouncilEnabled?COUNCIL_AGENT_TOOL_MAP.architect??[]:[],...generalCouncilEnabled?GENERAL_COUNCIL_AGENT_TOOL_MAP.architect??[]:[],...turboEnabled?TURBO_AGENT_TOOL_MAP.architect??[]:[],...skillsEnabled?SKILL_AGENT_TOOL_MAP.architect??[]:[]]].sort().map((t)=>{let desc=TOOL_DESCRIPTIONS[t];return desc?`${t} (${desc})`:t}).join(", ")}function buildSlashCommandsList(){let SKIP_ALIASES=new Set(Object.entries(COMMAND_REGISTRY).filter(([,entry])=>entry.aliasOf).map(([name])=>name)),READ_ONLY_OBSERVATION=new Set(["status","history","agents","config","show-plan","benchmark","export","retrieve"]),CATEGORY_ORDER=["Session Lifecycle","Planning","Execution Modes","Observation","Knowledge","State Management","Diagnostics"],COMMANDS_BY_CATEGORY={"Session Lifecycle":["finalize","reset","reset-session","handoff","archive"],Planning:["specify","clarify","analyze","show-plan","sync-plan","acknowledge-spec-drift","council"],"Execution Modes":["turbo","full-auto","loop"],Observation:["status","history","agents","config","benchmark","export","evidence","evidence summary","retrieve"],Knowledge:["knowledge","knowledge migrate","knowledge quarantine","knowledge restore","promote","curate"],"State Management":["checkpoint","rollback","write-retro"],Diagnostics:["diagnose","preflight","doctor tools","config doctor","simulate","dark-matter"]},lines=[],subcommandMap={};for(let[cmdName,cmdEntry]of Object.entries(COMMAND_REGISTRY)){let entry=cmdEntry;if(entry.subcommandOf){if(!subcommandMap[entry.subcommandOf])subcommandMap[entry.subcommandOf]=[];subcommandMap[entry.subcommandOf].push(cmdName)}}let compoundsInValidCommands=new Set;for(let category of CATEGORY_ORDER){lines.push(`**${category}**`);let commandNames=COMMANDS_BY_CATEGORY[category];for(let name of commandNames){let entry=COMMAND_REGISTRY[name];if(!entry)continue;if(SKIP_ALIASES.has(name))continue;if(entry.subcommandOf&&!VALID_COMMANDS.includes(name))continue;if(lines.push(`- \`/swarm ${name}\` — ${entry.description}`),entry.subcommandOf&&VALID_COMMANDS.includes(name))compoundsInValidCommands.add(name);if(READ_ONLY_OBSERVATION.has(name))continue;if(entry.details)lines.push(` ${entry.details}`);if(entry.args)lines.push(` Args: ${entry.args}`)}for(let parent of commandNames){let subs=subcommandMap[parent];if(!subs)continue;for(let subName of subs){let subEntry=COMMAND_REGISTRY[subName];if(!subEntry)continue;if(compoundsInValidCommands.has(subName)||subEntry.subcommandOf&&VALID_COMMANDS.includes(subName)||SKIP_ALIASES.has(subName))continue;if(lines.push(` - \`/swarm ${subName}\` — ${subEntry.description}`),subEntry.details)lines.push(` ${subEntry.details}`);if(subEntry.args)lines.push(` Args: ${subEntry.args}`)}}}return lines.join(`
2023
+ If the user keeps the default phase-level behavior, do not write this section.
2024
+
2025
+ - For auto-proceed: record the user's choice in the \`## Pending QA Gate Selection\` section of \`.swarm/context.md\` as \`- auto_proceed: <true|false>\` so it is persisted into the plan's \`execution_profile\` on save_plan.`}function buildAvailableToolsList(council,memoryEnabled=!1,externalSkillsEnabled=!1,turboEnabled=!1,skillsEnabled=!1){let qaCouncilEnabled=council?.enabled===!0,generalCouncilEnabled=council?.general?.enabled===!0;return[...[...AGENT_TOOL_MAP.architect??[],...memoryEnabled?MEMORY_AGENT_TOOL_MAP.architect??[]:[],...externalSkillsEnabled?EXTERNAL_SKILL_AGENT_TOOL_MAP.architect??[]:[],...qaCouncilEnabled?COUNCIL_AGENT_TOOL_MAP.architect??[]:[],...generalCouncilEnabled?GENERAL_COUNCIL_AGENT_TOOL_MAP.architect??[]:[],...turboEnabled?TURBO_AGENT_TOOL_MAP.architect??[]:[],...skillsEnabled?SKILL_AGENT_TOOL_MAP.architect??[]:[]]].sort().map((t)=>{let desc=TOOL_DESCRIPTIONS[t];return desc?`${t} (${desc})`:t}).join(", ")}function buildSlashCommandsList(){let SKIP_ALIASES=new Set(Object.entries(COMMAND_REGISTRY).filter(([,entry])=>entry.aliasOf).map(([name])=>name)),READ_ONLY_OBSERVATION=new Set(["status","history","agents","config","show-plan","benchmark","export","retrieve"]),CATEGORY_ORDER=["Session Lifecycle","Planning","Execution Modes","Observation","Knowledge","State Management","Diagnostics"],COMMANDS_BY_CATEGORY={"Session Lifecycle":["finalize","reset","reset-session","handoff","archive"],Planning:["specify","clarify","analyze","show-plan","sync-plan","acknowledge-spec-drift","council"],"Execution Modes":["turbo","full-auto","loop"],Observation:["status","history","agents","config","benchmark","export","evidence","evidence summary","retrieve"],Knowledge:["knowledge","knowledge migrate","knowledge quarantine","knowledge restore","promote","curate"],"State Management":["checkpoint","rollback","write-retro"],Diagnostics:["diagnose","preflight","doctor tools","config doctor","simulate","dark-matter"]},lines=[],subcommandMap={};for(let[cmdName,cmdEntry]of Object.entries(COMMAND_REGISTRY)){let entry=cmdEntry;if(entry.subcommandOf){if(!subcommandMap[entry.subcommandOf])subcommandMap[entry.subcommandOf]=[];subcommandMap[entry.subcommandOf].push(cmdName)}}let compoundsInValidCommands=new Set;for(let category of CATEGORY_ORDER){lines.push(`**${category}**`);let commandNames=COMMANDS_BY_CATEGORY[category];for(let name of commandNames){let entry=COMMAND_REGISTRY[name];if(!entry)continue;if(SKIP_ALIASES.has(name))continue;if(entry.subcommandOf&&!VALID_COMMANDS.includes(name))continue;if(lines.push(`- \`/swarm ${name}\` — ${entry.description}`),entry.subcommandOf&&VALID_COMMANDS.includes(name))compoundsInValidCommands.add(name);if(READ_ONLY_OBSERVATION.has(name))continue;if(entry.details)lines.push(` ${entry.details}`);if(entry.args)lines.push(` Args: ${entry.args}`)}for(let parent of commandNames){let subs=subcommandMap[parent];if(!subs)continue;for(let subName of subs){let subEntry=COMMAND_REGISTRY[subName];if(!subEntry)continue;if(compoundsInValidCommands.has(subName)||subEntry.subcommandOf&&VALID_COMMANDS.includes(subName)||SKIP_ALIASES.has(subName))continue;if(lines.push(` - \`/swarm ${subName}\` — ${subEntry.description}`),subEntry.details)lines.push(` ${subEntry.details}`);if(subEntry.args)lines.push(` Args: ${subEntry.args}`)}}}return lines.join(`
2022
2026
  `)}function createArchitectAgent(model,customPrompt,customAppendPrompt,adversarialTesting,council,uiReview,memoryEnabled=!1,architecturalSupervision,designDocsEnabled=!1,externalSkillsEnabled=!1,turboEnabled=!1,skillsEnabled=!1){let prompt=ARCHITECT_PROMPT;prompt=resolvePrompt(prompt,customPrompt,customAppendPrompt),prompt=prompt?.replace("{{YOUR_TOOLS}}",buildYourToolsList(council,memoryEnabled,externalSkillsEnabled,turboEnabled,skillsEnabled))?.replace("{{AVAILABLE_TOOLS}}",buildAvailableToolsList(council,memoryEnabled,externalSkillsEnabled,turboEnabled,skillsEnabled))?.replace("{{SLASH_COMMANDS}}",buildSlashCommandsList()),prompt=prompt?.replace(/\{\{QA_GATE_DIALOGUE_SPECIFY\}\}/g,buildQaGateSelectionDialogue("SPECIFY"))?.replace(/\{\{QA_GATE_DIALOGUE_BRAINSTORM\}\}/g,buildQaGateSelectionDialogue("BRAINSTORM"))?.replace(/\{\{QA_GATE_DIALOGUE_PLAN\}\}/g,buildQaGateSelectionDialogue("PLAN"));let councilBlock=buildCouncilWorkflow(council),hasPlaceholder=prompt?.includes("{{COUNCIL_WORKFLOW}}")===!0;if(councilBlock==="")prompt=prompt?.replace(/\n\n\{\{COUNCIL_WORKFLOW\}\}\n\n/g,`
2023
2027
 
2024
2028
  `);else if(hasPlaceholder)prompt=prompt?.replace(/\{\{COUNCIL_WORKFLOW\}\}/g,councilBlock);else prompt=`${prompt??""}
@@ -2893,7 +2897,7 @@ HARD CONSTRAINTS (apply regardless of skill load success):
2893
2897
  ### MODE: ISSUE_INGEST
2894
2898
  Activates when the user invokes /swarm issue <url> or the architect receives an ISSUE_INGEST signal.
2895
2899
 
2896
- Purpose: Ingest issue evidence, trace impact, and transition to planning or tracing.
2900
+ Purpose: Ingest issue evidence, trace impact, and transition to the full fix workflow.
2897
2901
 
2898
2902
  ACTION: Load skill ${bundledProjectSkillFileReference("issue-ingest")} immediately. Follow the protocol defined there.
2899
2903
 
@@ -4310,7 +4314,7 @@ CHANGELOG (design-changelog.md):
4310
4314
  - This is SEPARATE from CHANGELOG.md and docs/releases/pending/* (release-please owns those). NEVER touch release files here.
4311
4315
  - Append an entry per generate/sync: \`- <ISO date> phase <N>: <sections touched> (<FR refs>)\` under \`## [Unreleased]\` using Keep a Changelog headings (Added/Changed/Removed).
4312
4316
 
4313
- GUARDRAIL NOTE: if a spec-staleness block is reported when you try to write, surface it (SPEC_STALENESS_BLOCK) rather than retrying blindly — the architect resolves spec staleness first.
4317
+ GUARDRAIL NOTE: if a spec-staleness block is reported when you try to write, surface it (SPEC_DRIFT_BLOCK) rather than retrying blindly — the architect resolves spec staleness first.
4314
4318
 
4315
4319
  ## QUALITY RULES
4316
4320
  - Normative docs (domain/technical-spec/behavior-spec) describe WHAT each boundary guarantees, not which library provides it.
@@ -6070,7 +6074,7 @@ ${tailContent.join(`
6070
6074
  `)}
6071
6075
  ${footerLines.join(`
6072
6076
  `)}`}init_warning_buffer();var _heartbeatTimers=new Map,SWARM_COMMAND_SYSTEM_RULE_TAG="[opencode-swarm:swarm-command-rule]",PACKAGE_ROOT2=path237.resolve(path237.dirname(fileURLToPath5(import.meta.url)),".."),SYNC_BUNDLED_SKILLS_TIMEOUT_MS=2000;function createSwarmCommandSystemRuleHook(agentDefinitions,registeredAgents){return async(input,output)=>{let{sessionID}=input,activeAgentName=sessionID?swarmState.activeAgent.get(sessionID):void 0;if(!agentHasSwarmCommandTool(activeAgentName,agentDefinitions,registeredAgents))return;let system=Array.isArray(output.system)?output.system:[];if(system.some((entry)=>entry.includes(SWARM_COMMAND_SYSTEM_RULE_TAG))){output.system=system;return}system.push([SWARM_COMMAND_SYSTEM_RULE_TAG,"When a user asks for a supported /swarm command and the message instructs you to call the `swarm_command` tool, call that tool exactly once with the provided JSON arguments. After the tool returns, show the tool output verbatim and do not add extra swarm state, summaries, or invented command output."].join(`
6073
- `)),output.system=system}}var OpenCodeSwarm=async(ctx)=>{try{return await initializeOpenCodeSwarm(ctx)}catch(err2){let stack=err2 instanceof Error?err2.stack??err2.message:String(err2);throw console.error("[opencode-swarm] FATAL: plugin initialization failed. Plugin will not be available."),console.error(stack),err2}},MAX_TRACKED_ASSISTANT_USAGE_EVENTS=200,latestAssistantUsageBySession=new Map;function rememberAssistantUsageEvent(input){let event=isPlainRecord(input)?input.event:void 0;if(!isPlainRecord(event))return;if(event.type==="message.updated"){let properties=isPlainRecord(event.properties)?event.properties:void 0,info=isPlainRecord(properties?.info)?properties.info:void 0;if(info?.role==="assistant")rememberAssistantUsage(info.sessionID,info);return}if(event.type==="message.part.updated"){let properties=isPlainRecord(event.properties)?event.properties:void 0,part=isPlainRecord(properties?.part)?properties.part:void 0;if(part?.type==="step-finish")rememberAssistantUsage(part.sessionID,part)}}function rememberAssistantUsage(sessionID,raw){if(typeof sessionID!=="string"||sessionID.trim()==="")return;latestAssistantUsageBySession.set(sessionID,raw);while(latestAssistantUsageBySession.size>MAX_TRACKED_ASSISTANT_USAGE_EVENTS){let oldest=latestAssistantUsageBySession.keys().next().value;if(oldest===void 0)break;latestAssistantUsageBySession.delete(oldest)}}function consumeAssistantUsageForTask(parentSessionID,taskOutput){let sessionIDs=[parentSessionID,...collectSessionIDs(taskOutput)];for(let sessionID of sessionIDs){let usage=latestAssistantUsageBySession.get(sessionID);if(usage!==void 0)return latestAssistantUsageBySession.delete(sessionID),usage}return}function collectSessionIDs(raw){let found=[],seen=new Set,visit=(value,depth)=>{if(depth>3||!isPlainRecord(value)||seen.has(value))return;seen.add(value);for(let key of["sessionID","sessionId","session_id"]){let candidate=value[key];if(typeof candidate==="string"&&candidate.trim()!=="")found.push(candidate)}for(let key of["metadata","data","info","message","response","output"])visit(value[key],depth+1)};return visit(raw,0),[...new Set(found)]}function resolveDelegationModel(config3,agentName,baseAgentName){let topLevelModel=config3.agents?.[agentName]?.model??config3.agents?.[baseAgentName]?.model;if(topLevelModel)return topLevelModel;let swarmID=inferSwarmID(agentName,baseAgentName),swarmAgents=swarmID?config3.swarms?.[swarmID]?.agents:void 0;return swarmAgents?.[agentName]?.model??swarmAgents?.[baseAgentName]?.model??DEFAULT_MODELS[baseAgentName]??DEFAULT_MODELS.default}function inferSwarmID(agentName,baseAgentName){if(!agentName||agentName===baseAgentName)return;for(let separator of["_","-"," "]){let suffix=`${separator}${baseAgentName}`;if(agentName.endsWith(suffix)&&agentName.length>suffix.length)return agentName.slice(0,-suffix.length)}return}function isPlainRecord(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}async function initializeOpenCodeSwarm(ctx){clearDeferredWarnings();let{config:config3,loadedFromFile}=await loadPluginConfigWithMetaAsync(ctx.directory);if(config3.full_auto?.enabled===!0){let criticModel=config3.full_auto.critic_model??config3.agents?.critic?.model??DEFAULT_MODELS.critic,architectModel=config3.agents?.architect?.model??DEFAULT_MODELS.default;if(criticModel===architectModel)if(!config3.quiet)console.warn("[opencode-swarm] Full-auto mode warning: critic model matches architect model. Model validation is advisory-only; full-auto remains enabled. (Runtime architect model is determined by the orchestrator)");else addDeferredWarning("[opencode-swarm] Full-auto mode warning: critic model matches architect model. Model validation is advisory-only; full-auto remains enabled. (Runtime architect model is determined by the orchestrator)")}{let noFallback=[],hasNoFallback=(cfg)=>cfg.model&&(!cfg.fallback_models||cfg.fallback_models.length===0);if(config3.agents){for(let[name,cfg]of Object.entries(config3.agents))if(hasNoFallback(cfg))noFallback.push(`${name}(${cfg.model})`)}if(config3.swarms){for(let[swarmId,swarm]of Object.entries(config3.swarms))if(swarm.agents){for(let[name,cfg]of Object.entries(swarm.agents))if(hasNoFallback(cfg))noFallback.push(`${swarmId}/${name}(${cfg.model})`)}}if(noFallback.length>0){let msg=`[opencode-swarm] WARNING: ${noFallback.length} agent(s) use a custom model without fallback_models: `+noFallback.join(", ")+'. Add "fallback_models": ["model-a"] to each agent config for reliability.';if(!config3.quiet)console.warn(msg);else addDeferredWarning(msg)}}swarmState.fullAutoEnabledInConfig=config3.full_auto?.enabled===!0,swarmState.opencodeClient=ctx.client,await withTimeout(loadSnapshot(ctx.directory),5000,Error("loadSnapshot exceeded 5s budget; continuing without snapshot rehydration")).catch((err2)=>{let msg=err2 instanceof Error?err2.message:String(err2);log("loadSnapshot timed out or failed (non-fatal)",{error:msg})}),initTelemetry(ctx.directory);let repoGraphHook=createRepoGraphBuilderHook(ctx.directory,void 0,{excludeDirs:config3.repo_graph?.exclude_dirs});if(queueMicrotask(()=>{let watchdog=setTimeout(()=>{log("[repo-graph] init exceeded 30s budget; scan will continue but is overdue")},30000);if(typeof watchdog.unref==="function")watchdog.unref();repoGraphHook.init().catch(()=>{}).finally(()=>clearTimeout(watchdog))}),await withTimeout(ensureSwarmGitExcluded(ctx.directory,{quiet:config3.quiet}),ENSURE_SWARM_GIT_EXCLUDED_OUTER_TIMEOUT_MS,Error(`ensureSwarmGitExcluded exceeded ${ENSURE_SWARM_GIT_EXCLUDED_OUTER_TIMEOUT_MS}ms budget; continuing without git-hygiene check`)).catch((err2)=>{let msg=err2 instanceof Error?err2.message:String(err2);log("ensureSwarmGitExcluded timed out or failed (non-fatal)",{error:msg})}),queueMicrotask(()=>{runInitOrphanRecovery(ctx.directory).catch((err2)=>{let msg=err2 instanceof Error?err2.message:String(err2);log("initOrphanRecovery failed (non-fatal)",{error:msg})})}),writeSwarmConfigExampleIfNew(ctx.directory),writeProjectConfigIfNew(ctx.directory,config3.quiet),queueMicrotask(()=>{withTimeout(syncBundledProjectSkillsIfMissingAsync(ctx.directory,PACKAGE_ROOT2,config3.quiet),SYNC_BUNDLED_SKILLS_TIMEOUT_MS,Error(`syncBundledProjectSkillsIfMissingAsync exceeded ${SYNC_BUNDLED_SKILLS_TIMEOUT_MS}ms budget; continuing without skill materialization (command-path sync remains a backstop)`)).catch((err2)=>{let msg=err2 instanceof Error?err2.message:String(err2);log("bundled skill materialization timed out or failed (non-fatal)",{error:msg})})}),config3.version_check!==!1)scheduleVersionCheck(package_default.version,(msg)=>{if(config3.quiet)addDeferredWarning(msg);else console.warn(msg)});let projectContext=await withTimeout((async()=>{return(await Promise.resolve().then(() => (init_project_context(),exports_project_context))).buildProjectContext(ctx.directory)})(),300,Error("language-backend detection exceeded 300ms; continuing with unresolved sentinels")).catch((err2)=>{let msg=err2 instanceof Error?err2.message:String(err2);return log("language-backend detection timed out or failed (non-fatal)",{error:msg}),null}),agents=getAgentConfigs(config3,ctx.directory,void 0,projectContext??void 0),agentDefinitions=createAgents(config3,projectContext??void 0),agentDefinitionMap=Object.fromEntries(agentDefinitions.map((agent)=>[agent.name,agent]));swarmState.curatorInitAgentNames=Object.keys(agents).filter((k)=>k==="curator_init"||k.endsWith("_curator_init")),swarmState.curatorPhaseAgentNames=Object.keys(agents).filter((k)=>k==="curator_phase"||k.endsWith("_curator_phase")),swarmState.curatorPostmortemAgentNames=Object.keys(agents).filter((k)=>k==="curator_postmortem"||k.endsWith("_curator_postmortem")),swarmState.curatorConsolidationAgentNames=Object.keys(agents).filter((k)=>k==="curator_consolidation"||k.endsWith("_curator_consolidation")),swarmState.skillImproverAgentNames=Object.keys(agents).filter((k)=>k==="skill_improver"||k.endsWith("_skill_improver")),swarmState.specWriterAgentNames=Object.keys(agents).filter((k)=>k==="spec_writer"||k.endsWith("_spec_writer")),swarmState.generatedAgentNames=Object.keys(agents);let pipelineHook=createPipelineTrackerHook(config3,ctx.directory),systemEnhancerHook=createSystemEnhancerHook(config3,ctx.directory),contextCapsuleInjectHook=createContextCapsuleInjectHook(config3,ctx.directory),compactionHook=createCompactionCustomizerHook(config3,ctx.directory),contextBudgetHandler=createContextBudgetHandler(config3),commandHandler=createSwarmCommandHandler(ctx.directory,agentDefinitionMap,{getActiveAgentName:(sessionID)=>swarmState.activeAgent.get(sessionID),packageRoot:PACKAGE_ROOT2,registeredAgents:agents}),swarmCommandSystemRuleHook=createSwarmCommandSystemRuleHook(agentDefinitionMap,agents),activityHooks=createAgentActivityHooks(config3,ctx.directory),prmHook=createPrmHook(config3.prm??PrmConfigSchema.parse({}),ctx.directory),trajectoryLoggerHook=createTrajectoryLoggerHook({enabled:!0,max_lines:1000},ctx.directory),delegationGateHooks=createDelegationGateHook(config3,ctx.directory),backgroundCompletionObserver=createBackgroundCompletionObserver({config:{enabled:config3.hooks?.background_subagents===!0},directory:ctx.directory}),delegationSanitizerHook=createDelegationSanitizerHook(ctx.directory),memoryLifecycleHooks=createMemoryLifecycleHooks({directory:ctx.directory,config:config3.memory,getActiveAgentName:(sessionID)=>sessionID?swarmState.activeAgent.get(sessionID):void 0,getActiveTaskId:(sessionID)=>sessionID?swarmState.agentSessions.get(sessionID)?.currentTaskId??void 0:void 0}),guardrailsFallback=config3.guardrails?.enabled===!1?{...config3.guardrails,enabled:!1}:config3.guardrails??{},guardrailsConfig=GuardrailsConfigSchema.parse(guardrailsFallback);if(loadedFromFile&&guardrailsConfig.enabled===!1)warn(""),warn("══════════════════════════════════════════════════════════════"),warn("[opencode-swarm] \uD83D\uDD34 SECURITY WARNING: GUARDRAILS ARE DISABLED"),warn("══════════════════════════════════════════════════════════════"),warn("Guardrails have been explicitly disabled in user configuration."),warn("This disables safety measures including:"),warn(" - Tool call limits"),warn(" - Duration limits"),warn(" - Repetition detection"),warn(" - Error rate limits"),warn(" - Idle timeouts"),warn(""),warn("Only disable guardrails if you fully understand the security implications."),warn('To re-enable guardrails, set "guardrails.enabled" to true in your config.'),warn("══════════════════════════════════════════════════════════════"),warn("");let delegationHandler=createDelegationTrackerHook(config3,guardrailsConfig.enabled),authorityConfig=AuthorityConfigSchema.parse(config3.authority??{}),worktreeDirOverride=resolveWorktreeIsolationConfig(config3).worktree_dir,worktreeBaseDirOverrides=worktreeDirOverride?[worktreeDirOverride]:[],guardrailsHooks=createGuardrailsHooks(ctx.directory,void 0,guardrailsConfig,authorityConfig,worktreeBaseDirOverrides),fullAutoInterceptHook=createFullAutoInterceptHook(config3,ctx.directory),fullAutoPermissionHook=createFullAutoPermissionHook({config:config3,directory:ctx.directory}),fullAutoInputProbeHook=createFullAutoInputProbeHook({config:config3,directory:ctx.directory}),fullAutoDelegationHook=createFullAutoDelegationHook({config:config3,directory:ctx.directory}),ccCommandInterceptHook=createCcCommandInterceptHook({}),watchdogConfig=WatchdogConfigSchema.parse(config3.watchdog??{}),advisoryInjector=(sessionId,message)=>{let s=swarmState.agentSessions.get(sessionId);if(s)s.pendingAdvisoryMessages??=[],s.pendingAdvisoryMessages.push(message)},scopeGuardHook=createScopeGuardHook({enabled:watchdogConfig.scope_guard,skip_in_turbo:watchdogConfig.skip_in_turbo},ctx.directory,advisoryInjector),delegationLedgerHook=createDelegationLedgerHook({enabled:watchdogConfig.delegation_ledger},ctx.directory,advisoryInjector),initOrphanRecoveryAdvisoryHook=createInitOrphanRecoveryAdvisoryHook(ctx.directory),selfReviewConfig=SelfReviewConfigSchema.parse(config3.self_review??{}),selfReviewHook=createSelfReviewHook({enabled:selfReviewConfig.enabled,skip_in_turbo:selfReviewConfig.skip_in_turbo},advisoryInjector),autoReviewHook=createAutoReviewHook({config:AutoReviewConfigSchema.parse(config3.auto_review??{}),directory:ctx.directory,injectAdvisory:advisoryInjector}),summaryConfig=SummaryConfigSchema.parse(config3.summaries??{}),toolSummarizerHook=createToolSummarizerHook(summaryConfig,ctx.directory),knowledgeConfigBase=config3.knowledge??{},knowledgeConfig=KnowledgeConfigSchema.parse(knowledgeConfigBase),skillImproverConfig=SkillImproverConfigSchema.parse(config3.skill_improver??{}),skillPropagationConfig=SkillPropagationConfigSchema.parse(config3.skillPropagation??{});if(skillImproverConfig.enabled&&skillImproverConfig.trigger==="scheduled")queueMicrotask(()=>{Promise.resolve().then(() => (init_skill_consolidation(),exports_skill_consolidation)).then(({runSkillConsolidationFireAndForget:runSkillConsolidationFireAndForget2})=>{runSkillConsolidationFireAndForget2({directory:ctx.directory,config:skillImproverConfig,source:"startup",enrichmentQuota:{maxCalls:knowledgeConfig.enrichment.max_calls_per_day,window:knowledgeConfig.enrichment.quota_window},evaluateDrafts:!0},void 0,(err2)=>{let msg=err2 instanceof Error?err2.message:String(err2);log("scheduled skill consolidation failed (non-fatal)",{error:msg})})}).catch((err2)=>{let msg=err2 instanceof Error?err2.message:String(err2);log("failed to schedule skill consolidation (non-fatal)",{error:msg})})});let knowledgeCuratorHook=knowledgeConfig.enabled?createKnowledgeCuratorHook(ctx.directory,knowledgeConfig,{llmDelegateFactory:(sessionID)=>createCuratorLLMDelegate(ctx.directory,"phase",sessionID),enrichmentQuota:{maxCalls:knowledgeConfig.enrichment.max_calls_per_day,window:knowledgeConfig.enrichment.quota_window}}):void 0,hivePromoterHook=knowledgeConfig.enabled&&knowledgeConfig.hive_enabled?createHivePromoterHook(ctx.directory,knowledgeConfig):void 0,knowledgeInjectorHook=knowledgeConfig.enabled?createKnowledgeInjectorHook(ctx.directory,knowledgeConfig,config3.context_budget?.model_limits??{},config3.context_budget?.unified_injection_tokens):void 0,steeringConsumedHook=createSteeringConsumedHook(ctx.directory),coChangeSuggesterHook=createCoChangeSuggesterHook(ctx.directory),darkMatterDetectorHook=createDarkMatterDetectorHook(ctx.directory),slopDetectorHook=config3.slop_detector?.enabled!==!1?createSlopDetectorHook(config3.slop_detector??{enabled:!0,classThreshold:3,commentStripThreshold:5,diffLineThreshold:200,importHygieneThreshold:2},ctx.directory,(sessionId,message)=>{let s=swarmState.agentSessions.get(sessionId);if(s)s.pendingAdvisoryMessages??=[],s.pendingAdvisoryMessages.push(message)}):null,incrementalVerifyHook=config3.incremental_verify?.enabled!==!1?createIncrementalVerifyHook(config3.incremental_verify??{enabled:!0,command:null,timeoutMs:30000,triggerAgents:["coder"]},ctx.directory,(sessionId,message)=>{let s=swarmState.agentSessions.get(sessionId);if(s)s.pendingAdvisoryMessages??=[],s.pendingAdvisoryMessages.push(message)}):null,compactionServiceHook=config3.compaction_service?.enabled!==!1?createCompactionService(config3.compaction_service??{enabled:!0,observationThreshold:40,reflectionThreshold:60,emergencyThreshold:80,preserveLastNTurns:5},ctx.directory,(sessionId,message)=>{let s=swarmState.agentSessions.get(sessionId);if(s)s.pendingAdvisoryMessages??=[],s.pendingAdvisoryMessages.push(message)}):null,snapshotWriterHook=createSnapshotWriterHook(ctx.directory),automationConfig=AutomationConfigSchema.parse(config3.automation??{}),automationManager,preflightTriggerManager,statusArtifact,prMonitorWorker=null;if(automationConfig.mode!=="manual"){automationManager=createAutomationManager(automationConfig),automationManager.start();let{PreflightTriggerManager:PTM}=await Promise.resolve().then(() => (init_trigger(),exports_trigger));preflightTriggerManager=new PTM(automationConfig);let{AutomationStatusArtifact:ASA}=await Promise.resolve().then(() => (init_status_artifact(),exports_status_artifact)),swarmDir=path237.resolve(ctx.directory,".swarm");if(statusArtifact=new ASA(swarmDir),statusArtifact.updateConfig(automationConfig.mode,automationConfig.capabilities),automationConfig.capabilities?.evidence_auto_summaries===!0){let{createEvidenceSummaryIntegration:createEvidenceSummaryIntegration2}=await Promise.resolve().then(() => (init_evidence_summary_integration(),exports_evidence_summary_integration));createEvidenceSummaryIntegration2({automationConfig,directory:ctx.directory,projectDir:ctx.directory,summaryFilename:"evidence-summary.json"}),log("Evidence summary integration initialized",{directory:ctx.directory})}if(automationConfig.capabilities?.phase_preflight===!0){let{createPreflightIntegration:createPreflightIntegration2}=await Promise.resolve().then(() => (init_preflight_integration(),exports_preflight_integration));try{let{manager}=createPreflightIntegration2({automationConfig,directory:ctx.directory,swarmDir});preflightTriggerManager=manager,log("Preflight integration initialized",{directory:ctx.directory})}catch(err2){log("Preflight integration failed to initialize (non-fatal)",{error:err2 instanceof Error?err2.message:String(err2)})}}if(automationConfig.capabilities?.plan_sync===!0)try{new PlanSyncWorker({directory:ctx.directory}).start(),log("PlanSyncWorker initialized",{directory:ctx.directory})}catch(err2){log("PlanSyncWorker failed to initialize (non-fatal)",{error:err2 instanceof Error?err2.message:String(err2)})}log("Automation framework initialized",{mode:automationConfig.mode,enabled:automationManager?.isEnabled(),running:automationManager?.isActive(),preflightEnabled:preflightTriggerManager?.isEnabled()})}let prMonitorConfig=PrMonitorConfigSchema.parse(config3.pr_monitor??{});function ensurePrMonitorWorkerRunning(directory){try{if(!prMonitorConfig.enabled)return;if(!prMonitorWorker)prMonitorWorker=new PrMonitorWorker({directory,config:prMonitorConfig});if(!prMonitorWorker.isRunning())prMonitorWorker.start(),log("PR Monitor Worker started",{directory})}catch(err2){error48("[pr-monitor] Worker failed to start (non-fatal)",{error:err2 instanceof Error?err2.message:String(err2)})}}setOnSubscriptionCreated((directory,_record3)=>{ensurePrMonitorWorkerRunning(directory)});let prEventCleanup=null,prEventDelivery=null;if(prMonitorConfig.enabled){try{let{registerPrEventSubscribers:registerPrEventSubscribers2}=await Promise.resolve().then(() => (init_pr_event_subscribers(),exports_pr_event_subscribers));prEventCleanup=registerPrEventSubscribers2({directory:ctx.directory,config:prMonitorConfig})}catch(err2){log("[pr-monitor] Failed to register PR event subscribers (non-fatal)",{error:err2 instanceof Error?err2.message:String(err2)})}if(prMonitorConfig.event_delivery==="prompt")try{let deliveryModule=await Promise.resolve().then(() => (init_pr_event_delivery(),exports_pr_event_delivery));deliveryModule.registerPrEventDelivery({client:ctx.client,directory:ctx.directory,config:prMonitorConfig}),prEventDelivery={noteSessionIdle:deliveryModule.noteSessionIdle,unregisterPrEventDelivery:deliveryModule.unregisterPrEventDelivery}}catch(err2){log("[pr-monitor] Failed to register wake delivery (non-fatal)",{error:err2 instanceof Error?err2.message:String(err2)})}}let prAutoSubscribeHook=createPrAutoSubscribeHook(ctx.directory,prMonitorConfig);if(prMonitorConfig.enabled)queueMicrotask(()=>{listActive(ctx.directory).then((active)=>{if(active.length>0)ensurePrMonitorWorkerRunning(ctx.directory)}).catch((err2)=>{error48("[pr-monitor] Startup scan failed (non-fatal)",{error:err2 instanceof Error?err2.message:String(err2)})})});let cleanupAutomation=()=>{automationManager?.stop(),prMonitorWorker?.stop(),prEventCleanup?.(),prEventDelivery?.unregisterPrEventDelivery()};if(process.on("exit",cleanupAutomation),shouldRunOnStartup(automationConfig)){let enableAutofix=automationConfig.capabilities?.config_doctor_autofix===!0;Promise.resolve().then(() => (init_config_doctor(),exports_config_doctor)).then(({runConfigDoctorWithFixes:runConfigDoctorWithFixes2})=>{runConfigDoctorWithFixes2(ctx.directory,config3,enableAutofix).then((doctorResult)=>{if(doctorResult.result.findings.length>0){log("Config Doctor ran on startup",{findings:doctorResult.result.findings.length,errors:doctorResult.result.summary.error,warnings:doctorResult.result.summary.warn,appliedFixes:doctorResult.appliedFixes.length,autofixEnabled:enableAutofix});try{let autoFixableCount=doctorResult.result.findings.filter((f)=>f.autoFixable).length;if(!enableAutofix&&autoFixableCount>0){let msg=`[opencode-swarm] Config Doctor found ${autoFixableCount} auto-fixable issue(s). Run /swarm config doctor --fix to apply.`;if(!config3.quiet)console.warn(msg);else addDeferredWarning(msg)}else if(enableAutofix&&doctorResult.appliedFixes.length>0){let msg=`[opencode-swarm] Config Doctor applied ${doctorResult.appliedFixes.length} fix(es) automatically.`;if(!config3.quiet)console.warn(msg);else addDeferredWarning(msg)}}catch{}}}).catch((err2)=>{log("Config Doctor error (non-fatal)",{error:err2 instanceof Error?err2.message:String(err2)})})})}return log("Plugin initialized",{maxIterations:config3.max_iterations,agentCount:Object.keys(agents).length,hooks:{pipeline:!!pipelineHook["experimental.chat.messages.transform"],systemEnhancer:!!systemEnhancerHook["experimental.chat.system.transform"],compaction:!!compactionHook["experimental.session.compacting"],contextBudget:!!contextBudgetHandler,commands:!0,agentActivity:config3.hooks?.agent_activity!==!1,delegationTracker:config3.hooks?.delegation_tracker===!0,guardrails:guardrailsConfig.enabled,toolSummarizer:summaryConfig.enabled,knowledge:knowledgeConfig.enabled},automation:{mode:automationConfig.mode,capabilities:automationConfig.capabilities}}),{name:"opencode-swarm",agent:agents,tool:buildPluginToolObject(agentDefinitionMap,config3),event:async(input)=>{try{if(rememberAssistantUsageEvent(input),prEventDelivery){let evt=input.event;if(evt?.type==="session.idle"&&typeof evt.properties?.sessionID==="string")prEventDelivery.noteSessionIdle(evt.properties.sessionID)}await backgroundCompletionObserver.event(input)}catch(err2){warn(`[swarm] event hook error: ${err2 instanceof Error?err2.message:String(err2)}`)}},config:async(opencodeConfig)=>{let isObjectRecord=(value)=>typeof value==="object"&&value!==null,pluginConfig=opencodeConfig;if(!isObjectRecord(pluginConfig.agent))pluginConfig.agent={};let agentConfig=pluginConfig.agent;Object.assign(agentConfig,agents);let autoSelect=config3?.auto_select_architect;if(autoSelect)if(Object.keys(agents).some((name)=>stripKnownSwarmPrefix(name)==="architect")){for(let builtin of["build","plan"]){let existing=agentConfig[builtin];if(isObjectRecord(existing)&&existing.disable===!0)continue;agentConfig[builtin]={...isObjectRecord(existing)?existing:{},disable:!0}}if(autoSelect===!0){let primaryArchitects=Object.entries(agents).filter(([name,cfg])=>stripKnownSwarmPrefix(name)==="architect"&&isObjectRecord(cfg)&&cfg.mode==="primary");if(primaryArchitects.length>1){let names=primaryArchitects.map(([n])=>n).join(", ");addDeferredWarning(`[swarm] auto_select_architect is true but ${primaryArchitects.length} architect agents are primary (${names}). Consider setting auto_select_architect to a specific agent name.`)}}if(typeof autoSelect==="string"&&autoSelect!==""){let targetName=autoSelect;if(Object.hasOwn(agents,targetName)&&stripKnownSwarmPrefix(targetName)==="architect"){for(let[name,cfg]of Object.entries(agents))if(stripKnownSwarmPrefix(name)==="architect"&&name!==targetName)agentConfig[name]={...isObjectRecord(cfg)?cfg:{},mode:"subagent"};let targetExisting=agentConfig[targetName],targetAgent=agents[targetName];agentConfig[targetName]={...isObjectRecord(targetExisting)?targetExisting:{},...isObjectRecord(targetAgent)?targetAgent:{},mode:"primary"}}else addDeferredWarning(`[swarm] auto_select_architect is set to "${targetName}" but that is not a known architect agent. No architect demotion applied.`)}}else addDeferredWarning("[swarm] auto_select_architect is enabled but no architect agents were found in the generated set. The option has no effect.");let shortcutDescription=(cmd)=>{let entry=COMMAND_REGISTRY[cmd];if(!entry?.description)return`Use /swarm ${cmd}`;let desc=entry.description.charAt(0).toLowerCase()+entry.description.slice(1);return`Use /swarm ${cmd} to ${desc}`};opencodeConfig.command={...opencodeConfig.command||{},swarm:{template:"/swarm $ARGUMENTS",description:(()=>{return`Swarm management commands: /swarm [${VALID_COMMANDS.filter((cmd)=>{let entry=COMMAND_REGISTRY[cmd];return!entry.aliasOf&&!entry.deprecated&&!entry.subcommandOf}).join("|")}]`})()},"swarm-status":{template:"/swarm status",description:"Use /swarm status to show current swarm status and active phase"},"swarm-show-plan":{template:"/swarm show-plan $ARGUMENTS",description:"Use /swarm show-plan to view or filter the current execution plan"},"swarm-plan":{template:"/swarm plan $ARGUMENTS",description:"Deprecated alias for /swarm show-plan"},"swarm-agents":{template:"/swarm agents",description:"Use /swarm agents to list registered swarm agents"},"swarm-history":{template:"/swarm history",description:"Use /swarm history to show completed phases summary"},"swarm-config":{template:"/swarm config $ARGUMENTS",description:"Use /swarm config to show or validate configuration"},"swarm-evidence":{template:"/swarm evidence $ARGUMENTS",description:"Use /swarm evidence to view evidence bundles and summaries"},"swarm-handoff":{template:"/swarm handoff",description:"Use /swarm handoff to prepare handoff brief for switching models mid-task"},"swarm-archive":{template:"/swarm archive",description:"Use /swarm archive to archive old evidence bundles"},"swarm-diagnose":{template:"/swarm diagnose",description:"Use /swarm diagnose to run health checks on swarm state"},"swarm-diagnosis":{template:"/swarm diagnosis",description:"Use /swarm diagnosis to run health checks on swarm state"},"swarm-preflight":{template:"/swarm preflight",description:"Use /swarm preflight to run preflight automation checks"},"swarm-sync-plan":{template:"/swarm sync-plan",description:"Use /swarm sync-plan to sync plan.json with plan.md"},"swarm-benchmark":{template:"/swarm benchmark",description:"Use /swarm benchmark to show performance metrics"},"swarm-costs":{template:"/swarm costs $ARGUMENTS",description:"Use /swarm costs to show per-agent, task, gate, and retry token/cost totals"},"swarm-export":{template:"/swarm export",description:"Use /swarm export to export plan and context as JSON"},"swarm-reset":{template:"/swarm reset --confirm",description:"Use /swarm reset --confirm to clear swarm state (requires --confirm)"},"swarm-rollback":{template:"/swarm rollback $ARGUMENTS",description:"Use /swarm rollback to restore swarm state to a checkpoint"},"swarm-retrieve":{template:"/swarm retrieve $ARGUMENTS",description:"Use /swarm retrieve to retrieve full output from summary"},"swarm-clarify":{template:"/swarm clarify $ARGUMENTS",description:"Use /swarm clarify to clarify and refine a feature specification"},"swarm-analyze":{template:"/swarm analyze",description:"Use /swarm analyze to analyze spec vs plan for coverage gaps"},"swarm-specify":{template:"/swarm specify $ARGUMENTS",description:"Use /swarm specify to generate or import a feature specification"},"swarm-brainstorm":{template:"/swarm brainstorm $ARGUMENTS",description:"Use /swarm brainstorm to enter the architect MODE: BRAINSTORM planning workflow"},"swarm-loop":{template:"/swarm loop $ARGUMENTS",description:"Use /swarm loop <objective> to run a compound-engineering loop: brainstorm → plan → build → review → improve, iterating until done [--max-cycles 1..5] [--autonomy checkpoint|auto] [--depth standard|exhaustive] [--resume]"},"swarm-council":{template:"/swarm council $ARGUMENTS",description:"Use /swarm council <question> to convene a multi-model General Council deliberation (generalist / skeptic / domain expert) [--preset <name>] [--spec-review]"},"swarm-pr-review":{template:"/swarm pr-review $ARGUMENTS",description:"Use /swarm pr-review to launch deep PR review with multi-lane analysis"},"swarm-pr-feedback":{template:"/swarm pr-feedback $ARGUMENTS",description:"Use /swarm pr-feedback to ingest and close known PR feedback (review comments, CI failures, conflicts) without a fresh broad review"},"swarm-pr-subscribe":{template:"/swarm pr subscribe $ARGUMENTS",description:shortcutDescription("pr subscribe")},"swarm-pr-unsubscribe":{template:"/swarm pr unsubscribe $ARGUMENTS",description:shortcutDescription("pr unsubscribe")},"swarm-pr-status":{template:"/swarm pr status",description:shortcutDescription("pr status")},"swarm-ci-simulate":{template:"/swarm ci-simulate $ARGUMENTS",description:shortcutDescription("ci-simulate")},"swarm-learning":{template:"/swarm learning",description:shortcutDescription("learning")},"swarm-post-mortem":{template:"/swarm post-mortem $ARGUMENTS",description:shortcutDescription("post-mortem")},"swarm-deep-dive":{template:"/swarm deep-dive $ARGUMENTS",description:"Use /swarm deep-dive to launch a read-only deep audit with parallel explorer waves, dual reviewers, and critic challenge"},"swarm-deep-research":{template:"/swarm deep-research $ARGUMENTS",description:"Use /swarm deep-research <question> to run a multi-source, fact-checked deep research pass and synthesize a cited report [--depth standard|exhaustive] [--max-researchers 1..6] [--rounds 1..4] [--brief]"},"swarm-codebase-review":{template:"/swarm codebase-review $ARGUMENTS",description:"Use /swarm codebase-review to launch codebase-review-swarm for a quote-grounded full-repo or large-subsystem audit"},"swarm-design-docs":{template:"/swarm design-docs $ARGUMENTS",description:"Use /swarm design-docs to generate or sync language-agnostic design docs for the project under build"},"swarm-sdd":{template:"/swarm sdd $ARGUMENTS",description:"Use /swarm sdd to inspect OpenSpec-compatible SDD artifacts"},"swarm-sdd-status":{template:"/swarm sdd status",description:"Use /swarm sdd status to show effective spec and OpenSpec artifact status"},"swarm-sdd-validate":{template:"/swarm sdd validate $ARGUMENTS",description:"Use /swarm sdd validate to validate OpenSpec-compatible SDD artifacts"},"swarm-sdd-project":{template:"/swarm sdd project $ARGUMENTS",description:"Use /swarm sdd project to materialize OpenSpec artifacts into .swarm/spec.md"},"swarm-issue":{template:"/swarm issue $ARGUMENTS",description:"Use /swarm issue to ingest a GitHub issue into the swarm workflow"},"swarm-qa-gates":{template:"/swarm qa-gates $ARGUMENTS",description:"Use /swarm qa-gates to view or modify QA gate profile for the current plan"},"swarm-dark-matter":{template:"/swarm dark-matter",description:"Use /swarm dark-matter to detect hidden file couplings"},"swarm-knowledge":{template:"/swarm knowledge $ARGUMENTS",description:"Use /swarm knowledge for knowledge management (quarantine/restore/migrate)"},"swarm-memory":{template:"/swarm memory $ARGUMENTS",description:"Use /swarm memory for memory status, JSONL export/import, and SQLite migration"},"swarm-memory-status":{template:"/swarm memory status",description:"Use /swarm memory status to show provider and migration status"},"swarm-memory-export":{template:"/swarm memory export",description:"Use /swarm memory export to write current memory to JSONL"},"swarm-memory-import":{template:"/swarm memory import",description:"Use /swarm memory import to import legacy JSONL into SQLite"},"swarm-memory-migrate":{template:"/swarm memory migrate",description:"Use /swarm memory migrate to run the one-time SQLite migration"},"swarm-curate":{template:"/swarm curate",description:"Use /swarm curate to curate knowledge artifacts and entries"},"swarm-consolidate":{template:"/swarm consolidate $ARGUMENTS",description:"Use /swarm consolidate to run quota-bounded skill-improver consolidation"},"swarm-concurrency":{template:"/swarm concurrency $ARGUMENTS",description:"Use /swarm concurrency to manage runtime concurrency override for plan execution"},"swarm-turbo":{template:"/swarm turbo",description:"Use /swarm turbo to enable turbo mode for faster execution"},"swarm-epic":{template:"/swarm epic $ARGUMENTS",description:shortcutDescription("epic")},"swarm-coupling":{template:"/swarm coupling $ARGUMENTS",description:shortcutDescription("coupling")},"swarm-lanes":{template:"/swarm lanes",description:shortcutDescription("lanes")},"swarm-guardrail-explain":{template:"/swarm guardrail explain $ARGUMENTS",description:shortcutDescription("guardrail explain")},"swarm-guardrail-log":{template:"/swarm guardrail-log $ARGUMENTS",description:shortcutDescription("guardrail-log")},"swarm-full-auto":{template:"/swarm full-auto $ARGUMENTS",description:"Toggle Full-Auto Mode for the active session [on|off]"},"swarm-auto-proceed":{template:"/swarm auto-proceed $ARGUMENTS",description:"Toggle auto-proceed mode for automatic phase advancement"},"swarm-write-retro":{template:"/swarm write-retro $ARGUMENTS",description:"Use /swarm write-retro to manually write a phase retrospective"},"swarm-reset-session":{template:"/swarm reset-session",description:"Use /swarm reset-session to clear session state and delegation chains"},"swarm-simulate":{template:"/swarm simulate $ARGUMENTS",description:"Use /swarm simulate to run a simulated agent session"},"swarm-promote":{template:"/swarm promote $ARGUMENTS",description:"Use /swarm promote to promote knowledge entries to production"},"swarm-checkpoint":{template:"/swarm checkpoint $ARGUMENTS",description:"Use /swarm checkpoint to save or restore git checkpoints"},"swarm-config-doctor":{template:"/swarm config doctor",description:"Use /swarm config doctor to diagnose configuration issues"},"swarm-evidence-summary":{template:"/swarm evidence summary",description:"Use /swarm evidence summary to generate evidence summaries"},"swarm-finalize":{template:"/swarm finalize",description:"Use /swarm finalize to archive the swarm project and close active state"},"swarm-close":{template:"/swarm close",description:"Deprecated alias for /swarm finalize"},"swarm-acknowledge-spec-drift":{template:"/swarm acknowledge-spec-drift",description:"Use /swarm acknowledge-spec-drift to acknowledge spec drift and suppress further warnings"},"swarm-doctor-tools":{template:"/swarm doctor tools",description:"Use /swarm doctor tools to run tool registration coherence check"},"swarm-link":{template:"/swarm link $ARGUMENTS",description:"Use /swarm link to link this worktree to a shared knowledge store [name|status]"},"swarm-unlink":{template:"/swarm unlink $ARGUMENTS",description:"Use /swarm unlink to unlink this worktree from the shared knowledge store [--no-copy]"}},log("Config applied",{agents:Object.keys(agents),commands:["swarm"]})},"experimental.chat.messages.transform":composeHandlers(...[(input,_output)=>{if(process.env.DEBUG_SWARM)console.error("[DIAG] messagesTransform START");let p=input;if(p.sessionID){let archAgent=swarmState.activeAgent.get(p.sessionID),archSession=swarmState.agentSessions.get(p.sessionID),agentName=archAgent??archSession?.agentName??"";if(stripKnownSwarmPrefix(agentName)===ORCHESTRATOR_NAME)try{delegationLedgerHook.onArchitectResume(p.sessionID)}catch{}}return Promise.resolve()},pipelineHook["experimental.chat.messages.transform"],contextBudgetHandler,initOrphanRecoveryAdvisoryHook.messagesTransform,guardrailsHooks.messagesTransform,fullAutoInterceptHook?.messagesTransform,ccCommandInterceptHook?.messagesTransform,delegationGateHooks.messagesTransform,delegationSanitizerHook,memoryLifecycleHooks.messagesTransform,knowledgeInjectorHook,(input,output)=>{try{let p=input;return knowledgeApplicationTransformScan(ctx.directory,output,p.sessionID)}catch{return Promise.resolve()}},(input,output)=>{try{if(!skillPropagationConfig.enabled)return Promise.resolve();let p=input;return skillPropagationTransformScan(ctx.directory,output,p.sessionID,skillPropagationConfig)}catch{return Promise.resolve()}},(_input,output)=>{if(output.messages)output.messages=consolidateSystemMessages(output.messages);if(process.env.DEBUG_SWARM)console.error("[DIAG] messagesTransform DONE");return Promise.resolve()}].filter((fn2)=>Boolean(fn2))),"experimental.chat.system.transform":composeHandlers(...[async(_input,_output)=>{if(process.env.DEBUG_SWARM)console.error("[DIAG] systemTransform START")},systemEnhancerHook["experimental.chat.system.transform"],async(_input,_output)=>{if(process.env.DEBUG_SWARM)console.error("[DIAG] systemTransform enhancer DONE")},contextCapsuleInjectHook["experimental.chat.system.transform"],(input,_output)=>{try{let{sessionID}=input;if(!sessionID)return Promise.resolve();let lastTime=_heartbeatTimers.get(sessionID);if(Date.now()-(lastTime??0)>30000)_heartbeatTimers.set(sessionID,Date.now()),telemetry.heartbeat(sessionID)}catch{}return Promise.resolve()},automationConfig.capabilities?.phase_preflight===!0&&preflightTriggerManager?createPhaseMonitorHook(ctx.directory,preflightTriggerManager,void 0,(sessionId)=>createCuratorLLMDelegate(ctx.directory,"init",sessionId)):knowledgeConfig.enabled?createPhaseMonitorHook(ctx.directory,void 0,void 0,(sessionId)=>createCuratorLLMDelegate(ctx.directory,"init",sessionId)):void 0,swarmCommandSystemRuleHook,(_input,output)=>{if(Array.isArray(output.system)&&output.system.length>1)output.system=[output.system.join(`
6077
+ `)),output.system=system}}var OpenCodeSwarm=async(ctx)=>{try{return await initializeOpenCodeSwarm(ctx)}catch(err2){let stack=err2 instanceof Error?err2.stack??err2.message:String(err2);throw console.error("[opencode-swarm] FATAL: plugin initialization failed. Plugin will not be available."),console.error(stack),err2}},MAX_TRACKED_ASSISTANT_USAGE_EVENTS=200,latestAssistantUsageBySession=new Map;function rememberAssistantUsageEvent(input){let event=isPlainRecord(input)?input.event:void 0;if(!isPlainRecord(event))return;if(event.type==="message.updated"){let properties=isPlainRecord(event.properties)?event.properties:void 0,info=isPlainRecord(properties?.info)?properties.info:void 0;if(info?.role==="assistant")rememberAssistantUsage(info.sessionID,info);return}if(event.type==="message.part.updated"){let properties=isPlainRecord(event.properties)?event.properties:void 0,part=isPlainRecord(properties?.part)?properties.part:void 0;if(part?.type==="step-finish")rememberAssistantUsage(part.sessionID,part)}}function rememberAssistantUsage(sessionID,raw){if(typeof sessionID!=="string"||sessionID.trim()==="")return;latestAssistantUsageBySession.set(sessionID,raw);while(latestAssistantUsageBySession.size>MAX_TRACKED_ASSISTANT_USAGE_EVENTS){let oldest=latestAssistantUsageBySession.keys().next().value;if(oldest===void 0)break;latestAssistantUsageBySession.delete(oldest)}}function consumeAssistantUsageForTask(parentSessionID,taskOutput){let sessionIDs=[parentSessionID,...collectSessionIDs(taskOutput)];for(let sessionID of sessionIDs){let usage=latestAssistantUsageBySession.get(sessionID);if(usage!==void 0)return latestAssistantUsageBySession.delete(sessionID),usage}return}function collectSessionIDs(raw){let found=[],seen=new Set,visit=(value,depth)=>{if(depth>3||!isPlainRecord(value)||seen.has(value))return;seen.add(value);for(let key of["sessionID","sessionId","session_id"]){let candidate=value[key];if(typeof candidate==="string"&&candidate.trim()!=="")found.push(candidate)}for(let key of["metadata","data","info","message","response","output"])visit(value[key],depth+1)};return visit(raw,0),[...new Set(found)]}function resolveDelegationModel(config3,agentName,baseAgentName){let topLevelModel=config3.agents?.[agentName]?.model??config3.agents?.[baseAgentName]?.model;if(topLevelModel)return topLevelModel;let swarmID=inferSwarmID(agentName,baseAgentName),swarmAgents=swarmID?config3.swarms?.[swarmID]?.agents:void 0;return swarmAgents?.[agentName]?.model??swarmAgents?.[baseAgentName]?.model??DEFAULT_MODELS[baseAgentName]??DEFAULT_MODELS.default}function inferSwarmID(agentName,baseAgentName){if(!agentName||agentName===baseAgentName)return;for(let separator of["_","-"," "]){let suffix=`${separator}${baseAgentName}`;if(agentName.endsWith(suffix)&&agentName.length>suffix.length)return agentName.slice(0,-suffix.length)}return}function isPlainRecord(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}async function initializeOpenCodeSwarm(ctx){clearDeferredWarnings();let{config:config3,loadedFromFile}=await loadPluginConfigWithMetaAsync(ctx.directory);if(config3.full_auto?.enabled===!0){let criticModel=config3.full_auto.critic_model??config3.agents?.critic?.model??DEFAULT_MODELS.critic,architectModel=config3.agents?.architect?.model??DEFAULT_MODELS.default;if(criticModel===architectModel)if(!config3.quiet)console.warn("[opencode-swarm] Full-auto mode warning: critic model matches architect model. Model validation is advisory-only; full-auto remains enabled. (Runtime architect model is determined by the orchestrator)");else addDeferredWarning("[opencode-swarm] Full-auto mode warning: critic model matches architect model. Model validation is advisory-only; full-auto remains enabled. (Runtime architect model is determined by the orchestrator)")}{let noFallback=[],hasNoFallback=(cfg)=>cfg.model&&(!cfg.fallback_models||cfg.fallback_models.length===0);if(config3.agents){for(let[name,cfg]of Object.entries(config3.agents))if(hasNoFallback(cfg))noFallback.push(`${name}(${cfg.model})`)}if(config3.swarms){for(let[swarmId,swarm]of Object.entries(config3.swarms))if(swarm.agents){for(let[name,cfg]of Object.entries(swarm.agents))if(hasNoFallback(cfg))noFallback.push(`${swarmId}/${name}(${cfg.model})`)}}if(noFallback.length>0){let msg=`[opencode-swarm] WARNING: ${noFallback.length} agent(s) use a custom model without fallback_models: `+noFallback.join(", ")+'. Add "fallback_models": ["model-a"] to each agent config for reliability.';if(!config3.quiet)console.warn(msg);else addDeferredWarning(msg)}}swarmState.fullAutoEnabledInConfig=config3.full_auto?.enabled===!0,swarmState.opencodeClient=ctx.client,await withTimeout(loadSnapshot(ctx.directory),5000,Error("loadSnapshot exceeded 5s budget; continuing without snapshot rehydration")).catch((err2)=>{let msg=err2 instanceof Error?err2.message:String(err2);log("loadSnapshot timed out or failed (non-fatal)",{error:msg})}),initTelemetry(ctx.directory);let repoGraphHook=createRepoGraphBuilderHook(ctx.directory,void 0,{excludeDirs:config3.repo_graph?.exclude_dirs});if(queueMicrotask(()=>{let watchdog=setTimeout(()=>{log("[repo-graph] init exceeded 30s budget; scan will continue but is overdue")},30000);if(typeof watchdog.unref==="function")watchdog.unref();repoGraphHook.init().catch(()=>{}).finally(()=>clearTimeout(watchdog))}),await withTimeout(ensureSwarmGitExcluded(ctx.directory,{quiet:config3.quiet}),ENSURE_SWARM_GIT_EXCLUDED_OUTER_TIMEOUT_MS,Error(`ensureSwarmGitExcluded exceeded ${ENSURE_SWARM_GIT_EXCLUDED_OUTER_TIMEOUT_MS}ms budget; continuing without git-hygiene check`)).catch((err2)=>{let msg=err2 instanceof Error?err2.message:String(err2);log("ensureSwarmGitExcluded timed out or failed (non-fatal)",{error:msg})}),queueMicrotask(()=>{runInitOrphanRecovery(ctx.directory).catch((err2)=>{let msg=err2 instanceof Error?err2.message:String(err2);log("initOrphanRecovery failed (non-fatal)",{error:msg})})}),writeSwarmConfigExampleIfNew(ctx.directory),writeProjectConfigIfNew(ctx.directory,config3.quiet),queueMicrotask(()=>{withTimeout(syncBundledProjectSkillsIfMissingAsync(ctx.directory,PACKAGE_ROOT2,config3.quiet),SYNC_BUNDLED_SKILLS_TIMEOUT_MS,Error(`syncBundledProjectSkillsIfMissingAsync exceeded ${SYNC_BUNDLED_SKILLS_TIMEOUT_MS}ms budget; continuing without skill materialization (command-path sync remains a backstop)`)).catch((err2)=>{let msg=err2 instanceof Error?err2.message:String(err2);log("bundled skill materialization timed out or failed (non-fatal)",{error:msg})})}),config3.version_check!==!1)scheduleVersionCheck(package_default.version,(msg)=>{if(config3.quiet)addDeferredWarning(msg);else console.warn(msg)});let projectContext=await withTimeout((async()=>{return(await Promise.resolve().then(() => (init_project_context(),exports_project_context))).buildProjectContext(ctx.directory)})(),300,Error("language-backend detection exceeded 300ms; continuing with unresolved sentinels")).catch((err2)=>{let msg=err2 instanceof Error?err2.message:String(err2);return log("language-backend detection timed out or failed (non-fatal)",{error:msg}),null}),agents=getAgentConfigs(config3,ctx.directory,void 0,projectContext??void 0),agentDefinitions=createAgents(config3,projectContext??void 0),agentDefinitionMap=Object.fromEntries(agentDefinitions.map((agent)=>[agent.name,agent]));swarmState.curatorInitAgentNames=Object.keys(agents).filter((k)=>k==="curator_init"||k.endsWith("_curator_init")),swarmState.curatorPhaseAgentNames=Object.keys(agents).filter((k)=>k==="curator_phase"||k.endsWith("_curator_phase")),swarmState.curatorPostmortemAgentNames=Object.keys(agents).filter((k)=>k==="curator_postmortem"||k.endsWith("_curator_postmortem")),swarmState.curatorConsolidationAgentNames=Object.keys(agents).filter((k)=>k==="curator_consolidation"||k.endsWith("_curator_consolidation")),swarmState.skillImproverAgentNames=Object.keys(agents).filter((k)=>k==="skill_improver"||k.endsWith("_skill_improver")),swarmState.specWriterAgentNames=Object.keys(agents).filter((k)=>k==="spec_writer"||k.endsWith("_spec_writer")),swarmState.generatedAgentNames=Object.keys(agents);let pipelineHook=createPipelineTrackerHook(config3,ctx.directory),systemEnhancerHook=createSystemEnhancerHook(config3,ctx.directory),contextCapsuleInjectHook=createContextCapsuleInjectHook(config3,ctx.directory),compactionHook=createCompactionCustomizerHook(config3,ctx.directory),contextBudgetHandler=createContextBudgetHandler(config3),commandHandler=createSwarmCommandHandler(ctx.directory,agentDefinitionMap,{getActiveAgentName:(sessionID)=>swarmState.activeAgent.get(sessionID),packageRoot:PACKAGE_ROOT2,registeredAgents:agents}),swarmCommandSystemRuleHook=createSwarmCommandSystemRuleHook(agentDefinitionMap,agents),activityHooks=createAgentActivityHooks(config3,ctx.directory),prmHook=createPrmHook(config3.prm??PrmConfigSchema.parse({}),ctx.directory),trajectoryLoggerHook=createTrajectoryLoggerHook({enabled:!0,max_lines:1000},ctx.directory),delegationGateHooks=createDelegationGateHook(config3,ctx.directory),backgroundCompletionObserver=createBackgroundCompletionObserver({config:{enabled:config3.hooks?.background_subagents===!0},directory:ctx.directory}),delegationSanitizerHook=createDelegationSanitizerHook(ctx.directory),memoryLifecycleHooks=createMemoryLifecycleHooks({directory:ctx.directory,config:config3.memory,getActiveAgentName:(sessionID)=>sessionID?swarmState.activeAgent.get(sessionID):void 0,getActiveTaskId:(sessionID)=>sessionID?swarmState.agentSessions.get(sessionID)?.currentTaskId??void 0:void 0}),guardrailsFallback=config3.guardrails?.enabled===!1?{...config3.guardrails,enabled:!1}:config3.guardrails??{},guardrailsConfig=GuardrailsConfigSchema.parse(guardrailsFallback);if(loadedFromFile&&guardrailsConfig.enabled===!1)warn(""),warn("══════════════════════════════════════════════════════════════"),warn("[opencode-swarm] \uD83D\uDD34 SECURITY WARNING: GUARDRAILS ARE DISABLED"),warn("══════════════════════════════════════════════════════════════"),warn("Guardrails have been explicitly disabled in user configuration."),warn("This disables safety measures including:"),warn(" - Tool call limits"),warn(" - Duration limits"),warn(" - Repetition detection"),warn(" - Error rate limits"),warn(" - Idle timeouts"),warn(""),warn("Only disable guardrails if you fully understand the security implications."),warn('To re-enable guardrails, set "guardrails.enabled" to true in your config.'),warn("══════════════════════════════════════════════════════════════"),warn("");let delegationHandler=createDelegationTrackerHook(config3,guardrailsConfig.enabled),authorityConfig=AuthorityConfigSchema.parse(config3.authority??{}),worktreeDirOverride=resolveWorktreeIsolationConfig(config3).worktree_dir,worktreeBaseDirOverrides=worktreeDirOverride?[worktreeDirOverride]:[],guardrailsHooks=createGuardrailsHooks(ctx.directory,void 0,guardrailsConfig,authorityConfig,worktreeBaseDirOverrides),fullAutoInterceptHook=createFullAutoInterceptHook(config3,ctx.directory),fullAutoPermissionHook=createFullAutoPermissionHook({config:config3,directory:ctx.directory}),fullAutoInputProbeHook=createFullAutoInputProbeHook({config:config3,directory:ctx.directory}),fullAutoDelegationHook=createFullAutoDelegationHook({config:config3,directory:ctx.directory}),ccCommandInterceptHook=createCcCommandInterceptHook({}),watchdogConfig=WatchdogConfigSchema.parse(config3.watchdog??{}),advisoryInjector=(sessionId,message)=>{let s=swarmState.agentSessions.get(sessionId);if(s)s.pendingAdvisoryMessages??=[],s.pendingAdvisoryMessages.push(message)},scopeGuardHook=createScopeGuardHook({enabled:watchdogConfig.scope_guard,skip_in_turbo:watchdogConfig.skip_in_turbo},ctx.directory,advisoryInjector),delegationLedgerHook=createDelegationLedgerHook({enabled:watchdogConfig.delegation_ledger},ctx.directory,advisoryInjector),initOrphanRecoveryAdvisoryHook=createInitOrphanRecoveryAdvisoryHook(ctx.directory),selfReviewConfig=SelfReviewConfigSchema.parse(config3.self_review??{}),selfReviewHook=createSelfReviewHook({enabled:selfReviewConfig.enabled,skip_in_turbo:selfReviewConfig.skip_in_turbo},advisoryInjector),autoReviewHook=createAutoReviewHook({config:AutoReviewConfigSchema.parse(config3.auto_review??{}),directory:ctx.directory,injectAdvisory:advisoryInjector}),summaryConfig=SummaryConfigSchema.parse(config3.summaries??{}),toolSummarizerHook=createToolSummarizerHook(summaryConfig,ctx.directory),knowledgeConfigBase=config3.knowledge??{},knowledgeConfig=KnowledgeConfigSchema.parse(knowledgeConfigBase),skillImproverConfig=SkillImproverConfigSchema.parse(config3.skill_improver??{}),skillPropagationConfig=SkillPropagationConfigSchema.parse(config3.skillPropagation??{});if(skillImproverConfig.enabled&&skillImproverConfig.trigger==="scheduled")queueMicrotask(()=>{Promise.resolve().then(() => (init_skill_consolidation(),exports_skill_consolidation)).then(({runSkillConsolidationFireAndForget:runSkillConsolidationFireAndForget2})=>{runSkillConsolidationFireAndForget2({directory:ctx.directory,config:skillImproverConfig,source:"startup",enrichmentQuota:{maxCalls:knowledgeConfig.enrichment.max_calls_per_day,window:knowledgeConfig.enrichment.quota_window},evaluateDrafts:!0},void 0,(err2)=>{let msg=err2 instanceof Error?err2.message:String(err2);log("scheduled skill consolidation failed (non-fatal)",{error:msg})})}).catch((err2)=>{let msg=err2 instanceof Error?err2.message:String(err2);log("failed to schedule skill consolidation (non-fatal)",{error:msg})})});let knowledgeCuratorHook=knowledgeConfig.enabled?createKnowledgeCuratorHook(ctx.directory,knowledgeConfig,{llmDelegateFactory:(sessionID)=>createCuratorLLMDelegate(ctx.directory,"phase",sessionID),enrichmentQuota:{maxCalls:knowledgeConfig.enrichment.max_calls_per_day,window:knowledgeConfig.enrichment.quota_window}}):void 0,hivePromoterHook=knowledgeConfig.enabled&&knowledgeConfig.hive_enabled?createHivePromoterHook(ctx.directory,knowledgeConfig):void 0,knowledgeInjectorHook=knowledgeConfig.enabled?createKnowledgeInjectorHook(ctx.directory,knowledgeConfig,config3.context_budget?.model_limits??{},config3.context_budget?.unified_injection_tokens):void 0,steeringConsumedHook=createSteeringConsumedHook(ctx.directory),coChangeSuggesterHook=createCoChangeSuggesterHook(ctx.directory),darkMatterDetectorHook=createDarkMatterDetectorHook(ctx.directory),slopDetectorHook=config3.slop_detector?.enabled!==!1?createSlopDetectorHook(config3.slop_detector??{enabled:!0,classThreshold:3,commentStripThreshold:5,diffLineThreshold:200,importHygieneThreshold:2},ctx.directory,(sessionId,message)=>{let s=swarmState.agentSessions.get(sessionId);if(s)s.pendingAdvisoryMessages??=[],s.pendingAdvisoryMessages.push(message)}):null,incrementalVerifyHook=config3.incremental_verify?.enabled!==!1?createIncrementalVerifyHook(config3.incremental_verify??{enabled:!0,command:null,timeoutMs:30000,triggerAgents:["coder"]},ctx.directory,(sessionId,message)=>{let s=swarmState.agentSessions.get(sessionId);if(s)s.pendingAdvisoryMessages??=[],s.pendingAdvisoryMessages.push(message)}):null,compactionServiceHook=config3.compaction_service?.enabled!==!1?createCompactionService(config3.compaction_service??{enabled:!0,observationThreshold:40,reflectionThreshold:60,emergencyThreshold:80,preserveLastNTurns:5},ctx.directory,(sessionId,message)=>{let s=swarmState.agentSessions.get(sessionId);if(s)s.pendingAdvisoryMessages??=[],s.pendingAdvisoryMessages.push(message)}):null,snapshotWriterHook=createSnapshotWriterHook(ctx.directory),automationConfig=AutomationConfigSchema.parse(config3.automation??{}),automationManager,preflightTriggerManager,statusArtifact,prMonitorWorker=null;if(automationConfig.mode!=="manual"){automationManager=createAutomationManager(automationConfig),automationManager.start();let{PreflightTriggerManager:PTM}=await Promise.resolve().then(() => (init_trigger(),exports_trigger));preflightTriggerManager=new PTM(automationConfig);let{AutomationStatusArtifact:ASA}=await Promise.resolve().then(() => (init_status_artifact(),exports_status_artifact)),swarmDir=path237.resolve(ctx.directory,".swarm");if(statusArtifact=new ASA(swarmDir),statusArtifact.updateConfig(automationConfig.mode,automationConfig.capabilities),automationConfig.capabilities?.evidence_auto_summaries===!0){let{createEvidenceSummaryIntegration:createEvidenceSummaryIntegration2}=await Promise.resolve().then(() => (init_evidence_summary_integration(),exports_evidence_summary_integration));createEvidenceSummaryIntegration2({automationConfig,directory:ctx.directory,projectDir:ctx.directory,summaryFilename:"evidence-summary.json"}),log("Evidence summary integration initialized",{directory:ctx.directory})}if(automationConfig.capabilities?.phase_preflight===!0){let{createPreflightIntegration:createPreflightIntegration2}=await Promise.resolve().then(() => (init_preflight_integration(),exports_preflight_integration));try{let{manager}=createPreflightIntegration2({automationConfig,directory:ctx.directory,swarmDir});preflightTriggerManager=manager,log("Preflight integration initialized",{directory:ctx.directory})}catch(err2){log("Preflight integration failed to initialize (non-fatal)",{error:err2 instanceof Error?err2.message:String(err2)})}}if(automationConfig.capabilities?.plan_sync===!0)try{new PlanSyncWorker({directory:ctx.directory}).start(),log("PlanSyncWorker initialized",{directory:ctx.directory})}catch(err2){log("PlanSyncWorker failed to initialize (non-fatal)",{error:err2 instanceof Error?err2.message:String(err2)})}log("Automation framework initialized",{mode:automationConfig.mode,enabled:automationManager?.isEnabled(),running:automationManager?.isActive(),preflightEnabled:preflightTriggerManager?.isEnabled()})}let prMonitorConfig=PrMonitorConfigSchema.parse(config3.pr_monitor??{});function ensurePrMonitorWorkerRunning(directory){try{if(!prMonitorConfig.enabled)return;if(!prMonitorWorker)prMonitorWorker=new PrMonitorWorker({directory,config:prMonitorConfig});if(!prMonitorWorker.isRunning())prMonitorWorker.start(),log("PR Monitor Worker started",{directory})}catch(err2){error48("[pr-monitor] Worker failed to start (non-fatal)",{error:err2 instanceof Error?err2.message:String(err2)})}}setOnSubscriptionCreated((directory,_record3)=>{ensurePrMonitorWorkerRunning(directory)});let prEventCleanup=null,prEventDelivery=null;if(prMonitorConfig.enabled){try{let{registerPrEventSubscribers:registerPrEventSubscribers2}=await Promise.resolve().then(() => (init_pr_event_subscribers(),exports_pr_event_subscribers));prEventCleanup=registerPrEventSubscribers2({directory:ctx.directory,config:prMonitorConfig})}catch(err2){log("[pr-monitor] Failed to register PR event subscribers (non-fatal)",{error:err2 instanceof Error?err2.message:String(err2)})}if(prMonitorConfig.event_delivery==="prompt")try{let deliveryModule=await Promise.resolve().then(() => (init_pr_event_delivery(),exports_pr_event_delivery));deliveryModule.registerPrEventDelivery({client:ctx.client,directory:ctx.directory,config:prMonitorConfig}),prEventDelivery={noteSessionIdle:deliveryModule.noteSessionIdle,unregisterPrEventDelivery:deliveryModule.unregisterPrEventDelivery}}catch(err2){log("[pr-monitor] Failed to register wake delivery (non-fatal)",{error:err2 instanceof Error?err2.message:String(err2)})}}let prAutoSubscribeHook=createPrAutoSubscribeHook(ctx.directory,prMonitorConfig);if(prMonitorConfig.enabled)queueMicrotask(()=>{listActive(ctx.directory).then((active)=>{if(active.length>0)ensurePrMonitorWorkerRunning(ctx.directory)}).catch((err2)=>{error48("[pr-monitor] Startup scan failed (non-fatal)",{error:err2 instanceof Error?err2.message:String(err2)})})});let cleanupAutomation=()=>{automationManager?.stop(),prMonitorWorker?.stop(),prEventCleanup?.(),prEventDelivery?.unregisterPrEventDelivery()};if(process.on("exit",cleanupAutomation),shouldRunOnStartup(automationConfig)){let enableAutofix=automationConfig.capabilities?.config_doctor_autofix===!0;Promise.resolve().then(() => (init_config_doctor(),exports_config_doctor)).then(({runConfigDoctorWithFixes:runConfigDoctorWithFixes2})=>{runConfigDoctorWithFixes2(ctx.directory,config3,enableAutofix).then((doctorResult)=>{if(doctorResult.result.findings.length>0){log("Config Doctor ran on startup",{findings:doctorResult.result.findings.length,errors:doctorResult.result.summary.error,warnings:doctorResult.result.summary.warn,appliedFixes:doctorResult.appliedFixes.length,autofixEnabled:enableAutofix});try{let autoFixableCount=doctorResult.result.findings.filter((f)=>f.autoFixable).length;if(!enableAutofix&&autoFixableCount>0){let msg=`[opencode-swarm] Config Doctor found ${autoFixableCount} auto-fixable issue(s). Run /swarm config doctor --fix to apply.`;if(!config3.quiet)console.warn(msg);else addDeferredWarning(msg)}else if(enableAutofix&&doctorResult.appliedFixes.length>0){let msg=`[opencode-swarm] Config Doctor applied ${doctorResult.appliedFixes.length} fix(es) automatically.`;if(!config3.quiet)console.warn(msg);else addDeferredWarning(msg)}}catch{}}}).catch((err2)=>{log("Config Doctor error (non-fatal)",{error:err2 instanceof Error?err2.message:String(err2)})})})}return log("Plugin initialized",{maxIterations:config3.max_iterations,agentCount:Object.keys(agents).length,hooks:{pipeline:!!pipelineHook["experimental.chat.messages.transform"],systemEnhancer:!!systemEnhancerHook["experimental.chat.system.transform"],compaction:!!compactionHook["experimental.session.compacting"],contextBudget:!!contextBudgetHandler,commands:!0,agentActivity:config3.hooks?.agent_activity!==!1,delegationTracker:config3.hooks?.delegation_tracker===!0,guardrails:guardrailsConfig.enabled,toolSummarizer:summaryConfig.enabled,knowledge:knowledgeConfig.enabled},automation:{mode:automationConfig.mode,capabilities:automationConfig.capabilities}}),{name:"opencode-swarm",agent:agents,tool:buildPluginToolObject(agentDefinitionMap,config3),event:async(input)=>{try{if(rememberAssistantUsageEvent(input),prEventDelivery){let evt=input.event;if(evt?.type==="session.idle"&&typeof evt.properties?.sessionID==="string")prEventDelivery.noteSessionIdle(evt.properties.sessionID)}await backgroundCompletionObserver.event(input)}catch(err2){warn(`[swarm] event hook error: ${err2 instanceof Error?err2.message:String(err2)}`)}},config:async(opencodeConfig)=>{let isObjectRecord=(value)=>typeof value==="object"&&value!==null,pluginConfig=opencodeConfig;if(!isObjectRecord(pluginConfig.agent))pluginConfig.agent={};let agentConfig=pluginConfig.agent;Object.assign(agentConfig,agents);let autoSelect=config3?.auto_select_architect;if(autoSelect)if(Object.keys(agents).some((name)=>stripKnownSwarmPrefix(name)==="architect")){for(let builtin of["build","plan"]){let existing=agentConfig[builtin];if(isObjectRecord(existing)&&existing.disable===!0)continue;agentConfig[builtin]={...isObjectRecord(existing)?existing:{},disable:!0}}if(autoSelect===!0){let primaryArchitects=Object.entries(agents).filter(([name,cfg])=>stripKnownSwarmPrefix(name)==="architect"&&isObjectRecord(cfg)&&cfg.mode==="primary");if(primaryArchitects.length>1){let names=primaryArchitects.map(([n])=>n).join(", ");addDeferredWarning(`[swarm] auto_select_architect is true but ${primaryArchitects.length} architect agents are primary (${names}). Consider setting auto_select_architect to a specific agent name.`)}}if(typeof autoSelect==="string"&&autoSelect!==""){let targetName=autoSelect;if(Object.hasOwn(agents,targetName)&&stripKnownSwarmPrefix(targetName)==="architect"){for(let[name,cfg]of Object.entries(agents))if(stripKnownSwarmPrefix(name)==="architect"&&name!==targetName)agentConfig[name]={...isObjectRecord(cfg)?cfg:{},mode:"subagent"};let targetExisting=agentConfig[targetName],targetAgent=agents[targetName];agentConfig[targetName]={...isObjectRecord(targetExisting)?targetExisting:{},...isObjectRecord(targetAgent)?targetAgent:{},mode:"primary"}}else addDeferredWarning(`[swarm] auto_select_architect is set to "${targetName}" but that is not a known architect agent. No architect demotion applied.`)}}else addDeferredWarning("[swarm] auto_select_architect is enabled but no architect agents were found in the generated set. The option has no effect.");let shortcutDescription=(cmd)=>{let entry=COMMAND_REGISTRY[cmd];if(!entry?.description)return`Use /swarm ${cmd}`;let desc=entry.description.charAt(0).toLowerCase()+entry.description.slice(1);return`Use /swarm ${cmd} to ${desc}`};opencodeConfig.command={...opencodeConfig.command||{},swarm:{template:"/swarm $ARGUMENTS",description:(()=>{return`Swarm management commands: /swarm [${VALID_COMMANDS.filter((cmd)=>{let entry=COMMAND_REGISTRY[cmd];return!entry.aliasOf&&!entry.deprecated&&!entry.subcommandOf}).join("|")}]`})()},"swarm-status":{template:"/swarm status",description:"Use /swarm status to show current swarm status and active phase"},"swarm-show-plan":{template:"/swarm show-plan $ARGUMENTS",description:"Use /swarm show-plan to view or filter the current execution plan"},"swarm-plan":{template:"/swarm plan $ARGUMENTS",description:"Deprecated alias for /swarm show-plan"},"swarm-agents":{template:"/swarm agents",description:"Use /swarm agents to list registered swarm agents"},"swarm-history":{template:"/swarm history",description:"Use /swarm history to show completed phases summary"},"swarm-config":{template:"/swarm config $ARGUMENTS",description:"Use /swarm config to show or validate configuration"},"swarm-evidence":{template:"/swarm evidence $ARGUMENTS",description:"Use /swarm evidence to view evidence bundles and summaries"},"swarm-handoff":{template:"/swarm handoff",description:"Use /swarm handoff to prepare handoff brief for switching models mid-task"},"swarm-archive":{template:"/swarm archive",description:"Use /swarm archive to archive old evidence bundles"},"swarm-diagnose":{template:"/swarm diagnose",description:"Use /swarm diagnose to run health checks on swarm state"},"swarm-diagnosis":{template:"/swarm diagnosis",description:"Use /swarm diagnosis to run health checks on swarm state"},"swarm-preflight":{template:"/swarm preflight",description:"Use /swarm preflight to run preflight automation checks"},"swarm-sync-plan":{template:"/swarm sync-plan",description:"Use /swarm sync-plan to sync plan.json with plan.md"},"swarm-benchmark":{template:"/swarm benchmark",description:"Use /swarm benchmark to show performance metrics"},"swarm-costs":{template:"/swarm costs $ARGUMENTS",description:"Use /swarm costs to show per-agent, task, gate, and retry token/cost totals"},"swarm-export":{template:"/swarm export",description:"Use /swarm export to export plan and context as JSON"},"swarm-reset":{template:"/swarm reset --confirm",description:"Use /swarm reset --confirm to clear swarm state (requires --confirm)"},"swarm-rollback":{template:"/swarm rollback $ARGUMENTS",description:"Use /swarm rollback to restore swarm state to a checkpoint"},"swarm-retrieve":{template:"/swarm retrieve $ARGUMENTS",description:"Use /swarm retrieve to retrieve full output from summary"},"swarm-clarify":{template:"/swarm clarify $ARGUMENTS",description:"Use /swarm clarify to clarify and refine a feature specification"},"swarm-analyze":{template:"/swarm analyze",description:"Use /swarm analyze to analyze spec vs plan for coverage gaps"},"swarm-specify":{template:"/swarm specify $ARGUMENTS",description:"Use /swarm specify to generate or import a feature specification"},"swarm-brainstorm":{template:"/swarm brainstorm $ARGUMENTS",description:"Use /swarm brainstorm to enter the architect MODE: BRAINSTORM planning workflow"},"swarm-loop":{template:"/swarm loop $ARGUMENTS",description:"Use /swarm loop <objective> to run a compound-engineering loop: brainstorm → plan → build → review → improve, iterating until done [--max-cycles 1..5] [--autonomy checkpoint|auto] [--depth standard|exhaustive] [--resume]"},"swarm-council":{template:"/swarm council $ARGUMENTS",description:"Use /swarm council <question> to convene a multi-model General Council deliberation (generalist / skeptic / domain expert) [--spec-review]"},"swarm-pr-review":{template:"/swarm pr-review $ARGUMENTS",description:"Use /swarm pr-review to launch deep PR review with multi-lane analysis"},"swarm-pr-feedback":{template:"/swarm pr-feedback $ARGUMENTS",description:"Use /swarm pr-feedback to ingest and close known PR feedback (review comments, CI failures, conflicts) without a fresh broad review"},"swarm-pr-subscribe":{template:"/swarm pr subscribe $ARGUMENTS",description:shortcutDescription("pr subscribe")},"swarm-pr-unsubscribe":{template:"/swarm pr unsubscribe $ARGUMENTS",description:shortcutDescription("pr unsubscribe")},"swarm-pr-status":{template:"/swarm pr status",description:shortcutDescription("pr status")},"swarm-ci-simulate":{template:"/swarm ci-simulate $ARGUMENTS",description:shortcutDescription("ci-simulate")},"swarm-learning":{template:"/swarm learning",description:shortcutDescription("learning")},"swarm-post-mortem":{template:"/swarm post-mortem $ARGUMENTS",description:shortcutDescription("post-mortem")},"swarm-deep-dive":{template:"/swarm deep-dive $ARGUMENTS",description:"Use /swarm deep-dive to launch a read-only deep audit with parallel explorer waves, dual reviewers, and critic challenge"},"swarm-deep-research":{template:"/swarm deep-research $ARGUMENTS",description:"Use /swarm deep-research <question> to run a multi-source, fact-checked deep research pass and synthesize a cited report [--depth standard|exhaustive] [--max-researchers 1..6] [--rounds 1..4] [--brief]"},"swarm-codebase-review":{template:"/swarm codebase-review $ARGUMENTS",description:"Use /swarm codebase-review to launch codebase-review-swarm for a quote-grounded full-repo or large-subsystem audit"},"swarm-design-docs":{template:"/swarm design-docs $ARGUMENTS",description:"Use /swarm design-docs to generate or sync language-agnostic design docs for the project under build"},"swarm-sdd":{template:"/swarm sdd $ARGUMENTS",description:"Use /swarm sdd to inspect OpenSpec-compatible SDD artifacts"},"swarm-sdd-status":{template:"/swarm sdd status",description:"Use /swarm sdd status to show effective spec and OpenSpec artifact status"},"swarm-sdd-validate":{template:"/swarm sdd validate $ARGUMENTS",description:"Use /swarm sdd validate to validate OpenSpec-compatible SDD artifacts"},"swarm-sdd-project":{template:"/swarm sdd project $ARGUMENTS",description:"Use /swarm sdd project to materialize OpenSpec artifacts into .swarm/spec.md"},"swarm-issue":{template:"/swarm issue $ARGUMENTS",description:"Use /swarm issue to ingest a GitHub issue into the swarm workflow"},"swarm-qa-gates":{template:"/swarm qa-gates $ARGUMENTS",description:"Use /swarm qa-gates to view or modify QA gate profile for the current plan"},"swarm-dark-matter":{template:"/swarm dark-matter",description:"Use /swarm dark-matter to detect hidden file couplings"},"swarm-knowledge":{template:"/swarm knowledge $ARGUMENTS",description:"Use /swarm knowledge for knowledge management (quarantine/restore/migrate)"},"swarm-memory":{template:"/swarm memory $ARGUMENTS",description:"Use /swarm memory for memory status, JSONL export/import, and SQLite migration"},"swarm-memory-status":{template:"/swarm memory status",description:"Use /swarm memory status to show provider and migration status"},"swarm-memory-export":{template:"/swarm memory export",description:"Use /swarm memory export to write current memory to JSONL"},"swarm-memory-import":{template:"/swarm memory import",description:"Use /swarm memory import to import legacy JSONL into SQLite"},"swarm-memory-migrate":{template:"/swarm memory migrate",description:"Use /swarm memory migrate to run the one-time SQLite migration"},"swarm-curate":{template:"/swarm curate",description:"Use /swarm curate to curate knowledge artifacts and entries"},"swarm-consolidate":{template:"/swarm consolidate $ARGUMENTS",description:"Use /swarm consolidate to run quota-bounded skill-improver consolidation"},"swarm-concurrency":{template:"/swarm concurrency $ARGUMENTS",description:"Use /swarm concurrency to manage runtime concurrency override for plan execution"},"swarm-turbo":{template:"/swarm turbo",description:"Use /swarm turbo to enable turbo mode for faster execution"},"swarm-epic":{template:"/swarm epic $ARGUMENTS",description:shortcutDescription("epic")},"swarm-coupling":{template:"/swarm coupling $ARGUMENTS",description:shortcutDescription("coupling")},"swarm-lanes":{template:"/swarm lanes",description:shortcutDescription("lanes")},"swarm-guardrail-explain":{template:"/swarm guardrail explain $ARGUMENTS",description:shortcutDescription("guardrail explain")},"swarm-guardrail-log":{template:"/swarm guardrail-log $ARGUMENTS",description:shortcutDescription("guardrail-log")},"swarm-full-auto":{template:"/swarm full-auto $ARGUMENTS",description:"Toggle Full-Auto Mode for the active session [on|off]"},"swarm-auto-proceed":{template:"/swarm auto-proceed $ARGUMENTS",description:"Toggle auto-proceed mode for automatic phase advancement"},"swarm-write-retro":{template:"/swarm write-retro $ARGUMENTS",description:"Use /swarm write-retro to manually write a phase retrospective"},"swarm-reset-session":{template:"/swarm reset-session",description:"Use /swarm reset-session to clear session state and delegation chains"},"swarm-simulate":{template:"/swarm simulate $ARGUMENTS",description:"Use /swarm simulate to run a simulated agent session"},"swarm-promote":{template:"/swarm promote $ARGUMENTS",description:"Use /swarm promote to promote knowledge entries to production"},"swarm-checkpoint":{template:"/swarm checkpoint $ARGUMENTS",description:"Use /swarm checkpoint to save or restore git checkpoints"},"swarm-config-doctor":{template:"/swarm config doctor",description:"Use /swarm config doctor to diagnose configuration issues"},"swarm-evidence-summary":{template:"/swarm evidence summary",description:"Use /swarm evidence summary to generate evidence summaries"},"swarm-finalize":{template:"/swarm finalize",description:"Use /swarm finalize to archive the swarm project and close active state"},"swarm-close":{template:"/swarm close",description:"Deprecated alias for /swarm finalize"},"swarm-acknowledge-spec-drift":{template:"/swarm acknowledge-spec-drift",description:"Use /swarm acknowledge-spec-drift to acknowledge spec drift and suppress further warnings"},"swarm-doctor-tools":{template:"/swarm doctor tools",description:"Use /swarm doctor tools to run tool registration coherence check"},"swarm-link":{template:"/swarm link $ARGUMENTS",description:"Use /swarm link to link this worktree to a shared knowledge store [name|status]"},"swarm-unlink":{template:"/swarm unlink $ARGUMENTS",description:"Use /swarm unlink to unlink this worktree from the shared knowledge store [--no-copy]"}},log("Config applied",{agents:Object.keys(agents),commands:["swarm"]})},"experimental.chat.messages.transform":composeHandlers(...[(input,_output)=>{if(process.env.DEBUG_SWARM)console.error("[DIAG] messagesTransform START");let p=input;if(p.sessionID){let archAgent=swarmState.activeAgent.get(p.sessionID),archSession=swarmState.agentSessions.get(p.sessionID),agentName=archAgent??archSession?.agentName??"";if(stripKnownSwarmPrefix(agentName)===ORCHESTRATOR_NAME)try{delegationLedgerHook.onArchitectResume(p.sessionID)}catch{}}return Promise.resolve()},pipelineHook["experimental.chat.messages.transform"],contextBudgetHandler,initOrphanRecoveryAdvisoryHook.messagesTransform,guardrailsHooks.messagesTransform,fullAutoInterceptHook?.messagesTransform,ccCommandInterceptHook?.messagesTransform,delegationGateHooks.messagesTransform,delegationSanitizerHook,memoryLifecycleHooks.messagesTransform,knowledgeInjectorHook,(input,output)=>{try{let p=input;return knowledgeApplicationTransformScan(ctx.directory,output,p.sessionID)}catch{return Promise.resolve()}},(input,output)=>{try{if(!skillPropagationConfig.enabled)return Promise.resolve();let p=input;return skillPropagationTransformScan(ctx.directory,output,p.sessionID,skillPropagationConfig)}catch{return Promise.resolve()}},(_input,output)=>{if(output.messages)output.messages=consolidateSystemMessages(output.messages);if(process.env.DEBUG_SWARM)console.error("[DIAG] messagesTransform DONE");return Promise.resolve()}].filter((fn2)=>Boolean(fn2))),"experimental.chat.system.transform":composeHandlers(...[async(_input,_output)=>{if(process.env.DEBUG_SWARM)console.error("[DIAG] systemTransform START")},systemEnhancerHook["experimental.chat.system.transform"],async(_input,_output)=>{if(process.env.DEBUG_SWARM)console.error("[DIAG] systemTransform enhancer DONE")},contextCapsuleInjectHook["experimental.chat.system.transform"],(input,_output)=>{try{let{sessionID}=input;if(!sessionID)return Promise.resolve();let lastTime=_heartbeatTimers.get(sessionID);if(Date.now()-(lastTime??0)>30000)_heartbeatTimers.set(sessionID,Date.now()),telemetry.heartbeat(sessionID)}catch{}return Promise.resolve()},automationConfig.capabilities?.phase_preflight===!0&&preflightTriggerManager?createPhaseMonitorHook(ctx.directory,preflightTriggerManager,void 0,(sessionId)=>createCuratorLLMDelegate(ctx.directory,"init",sessionId)):knowledgeConfig.enabled?createPhaseMonitorHook(ctx.directory,void 0,void 0,(sessionId)=>createCuratorLLMDelegate(ctx.directory,"init",sessionId)):void 0,swarmCommandSystemRuleHook,(_input,output)=>{if(Array.isArray(output.system)&&output.system.length>1)output.system=[output.system.join(`
6074
6078
 
6075
6079
  `)];return Promise.resolve()}].filter(Boolean)),"experimental.session.compacting":compactionHook["experimental.session.compacting"],"command.execute.before":safeHook(commandHandler),"tool.execute.before":async(input,output)=>{if(process.env.DEBUG_SWARM)console.error(`[DIAG] toolBefore tool=${normalizeToolName(input.tool)??input.tool} session=${input.sessionID}`);if(!swarmState.activeAgent.has(input.sessionID))swarmState.activeAgent.set(input.sessionID,ORCHESTRATOR_NAME);let session=swarmState.agentSessions.get(input.sessionID),activeAgent=swarmState.activeAgent.get(input.sessionID);if(session&&activeAgent&&activeAgent!==ORCHESTRATOR_NAME){if(stripKnownSwarmPrefix(activeAgent)!==ORCHESTRATOR_NAME){if(!session.delegationActive&&Date.now()-session.lastAgentEventTime>1e4)swarmState.activeAgent.set(input.sessionID,ORCHESTRATOR_NAME),ensureAgentSession(input.sessionID,ORCHESTRATOR_NAME)}}await guardrailsHooks.toolBefore(input,output),await scopeGuardHook.toolBefore(input,output),await delegationGateHooks.toolBefore(input,output),await fullAutoDelegationHook.toolBefore(input,output),await fullAutoPermissionHook.toolBefore(input,output),await knowledgeApplicationGateBefore(ctx.directory,{tool:input.tool,agent:input.agent,sessionID:input.sessionID},KnowledgeApplicationConfigSchema.parse(config3.knowledge_application??{}));let skillResult=await skillPropagationGateBefore(ctx.directory,{tool:input.tool,agent:input.agent,sessionID:input.sessionID,args:input.args},skillPropagationConfig);if(skillResult.blocked)throw Error(skillResult.reason??"Blocked by skill propagation gate");if(skillResult.reason){let skillSession=ensureAgentSession(input.sessionID,swarmState.activeAgent.get(input.sessionID)??ORCHESTRATOR_NAME);skillSession.pendingAdvisoryMessages??=[],skillSession.pendingAdvisoryMessages.push(skillResult.reason)}if(skillResult.recommendedSkills&&skillResult.recommendedSkills.length>0){let argsRecord=input.args,promptRaw=argsRecord.prompt;if(typeof promptRaw==="string"){let parsedDelegation=parseDelegationArgs(input.args);if(parsedDelegation){if(!parsedDelegation.skillsField.trim()){let qualified=skillResult.recommendedSkills.filter((s)=>s.score>=0.5);if(qualified.length===0){if(argsRecord.prompt=`SKILLS: none
6076
6080