opencode-swarm 7.114.5 → 7.114.7
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.
- package/dist/cli/{curator-llm-factory-asqhpq08.js → curator-llm-factory-2xgznxyw.js} +6 -6
- package/dist/cli/{curator-2cnthj9n.js → curator-qshyr2tc.js} +6 -6
- package/dist/cli/{guardrail-explain-xt6skemq.js → guardrail-explain-4t8fnysh.js} +7 -7
- package/dist/cli/{hive-promoter-n9qt3sth.js → hive-promoter-5ngbmnrw.js} +6 -6
- package/dist/cli/{index-fc35yaah.js → index-6ctejje2.js} +33 -25
- package/dist/cli/{index-h7q1bvzm.js → index-7stsmndb.js} +3 -3
- package/dist/cli/{index-0q7rrh59.js → index-91qesget.js} +14 -9
- package/dist/cli/{index-s8se9nt5.js → index-gmjrwz34.js} +1 -1
- package/dist/cli/{index-qzqx2qky.js → index-kjbfry6m.js} +1 -1
- package/dist/cli/{index-43khae15.js → index-qrnhvhmg.js} +1 -1
- package/dist/cli/{index-mr4whary.js → index-vjvdvjd3.js} +3 -3
- package/dist/cli/{index-s0h4kf1t.js → index-z01r5483.js} +7 -7
- package/dist/cli/index.js +6 -6
- package/dist/cli/{knowledge-escalator-0q1p6br7.js → knowledge-escalator-qn7ew687.js} +3 -3
- package/dist/cli/{knowledge-events-9518gzsp.js → knowledge-events-k2xsz5bh.js} +1 -1
- package/dist/cli/{knowledge-store-k5rab79h.js → knowledge-store-ksa1dr2z.js} +1 -1
- package/dist/cli/{knowledge-validator-csay9wqj.js → knowledge-validator-2knz0d2t.js} +2 -2
- package/dist/cli/{skill-generator-z01sjppf.js → skill-generator-w6qd9mde.js} +4 -4
- package/dist/index.js +37 -37
- package/package.json +1 -1
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.5",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"]},write_pr_review_trigger_eval:{description:"persist the complete PR-review trigger evaluation with exact-set validation and dispatch provenance",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.7",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"]},write_pr_review_trigger_eval:{description:"persist the complete PR-review trigger evaluation with exact-set validation and dispatch provenance",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
|
|
|
@@ -303,9 +303,9 @@ ${warnings.map((w)=>` - ${w}`).join(`
|
|
|
303
303
|
`).map((line)=>{let match=line.match(/^Would remove (.+)$/);return match?match[1].trim():""}).filter((p)=>p.length>0).filter((p)=>!isSafeToClean(p));if(unsafePaths.length>0)return console.warn(`[swarm:cleanUntrackedFiles] Skipping clean — untracked source files detected: ${unsafePaths.join(", ")}`),{cleaned:!1,error:"untracked source files detected — skipping clean to prevent data loss"}}let result=await runGit2(["clean","-fd"],worktreePath);if(result.exitCode!==0)return{cleaned:!1,error:result.stderr.trim()||result.stdout.trim()};return{cleaned:!0}}async function assertCleanWorkingTree(directory){let[statusResult,untrackedResult]=await Promise.all([runGit2(["status","--porcelain"],directory),runGit2(["ls-files","--others","--exclude-standard"],directory)]);if(statusResult.exitCode!==0)return{clean:!1,error:`Unable to verify working tree cleanliness: ${statusResult.stderr.trim()||statusResult.stdout.trim()}`};if(untrackedResult.exitCode!==0)return{clean:!1,error:`Unable to verify working tree cleanliness: ${untrackedResult.stderr.trim()||untrackedResult.stdout.trim()}`};let hasChanges=statusResult.stdout.trim().length>0,hasUntracked=untrackedResult.stdout.trim().length>0;if(hasChanges||hasUntracked)return{clean:!1,error:"Working tree has uncommitted changes. Please commit or stash before provisioning worktrees. Run 'git status' for details."};return{clean:!0}}var _internals17,WORKTREE_TIMEOUT_MS=30000,WIN_PATH_BUDGET=250,SAFE_CLEAN_PATTERNS;var init_core3=__esm(()=>{init_utils();init_bun_compat();_internals17={bunSpawn,platform:process.platform,sleep:(ms)=>new Promise((resolve13)=>setTimeout(resolve13,ms)),osTmpdir:()=>os9.tmpdir(),getCoreLongPaths:async(directory)=>{let result=await runGit2(["config","core.longpaths"],directory);if(result.exitCode!==0)return;let value=result.stdout.trim().toLowerCase();return value===""?void 0:value},fs:{existsSync:fs15.existsSync,cp:fsPromises5.cp,cpSync:fs15.cpSync,symlinkSync:fs15.symlinkSync},writeScopeToDisk:async(directory,taskId,files)=>{let{writeScopeToDisk:realWrite}=await Promise.resolve().then(() => (init_scope_persistence(),exports_scope_persistence));return realWrite(directory,taskId,files)},writeLaneProfileToDisk:async(_worktreePath,_laneIndex,_envOverrides)=>{return writeLaneProfileToDiskReal(_worktreePath,_laneIndex,_envOverrides)},removeLaneProfileFromDisk:async(_worktreePath,_laneIndex)=>{return removeLaneProfileFromDiskReal(_worktreePath,_laneIndex)},removeWorktree};SAFE_CLEAN_PATTERNS=["dist/","build/",".turbo/","coverage/","node_modules/.cache/",".log",".tmp",".o",".pyc",".class"]});async function runGit3(args2,cwd,timeoutMs=MERGE_TIMEOUT_MS){let proc=_internals18.bunSpawn(["git",...args2],{cwd,timeout:timeoutMs,stdin:"ignore",stdout:"pipe",stderr:"pipe",env:{...process.env,LC_ALL:"C"}});try{let exitCode=await proc.exited,stdout=await proc.stdout.text(),stderr=await proc.stderr.text();return{exitCode,stdout,stderr}}finally{try{proc.kill()}catch{}}}function parseConflictFiles(output){let files=[],lines=output.split(`
|
|
304
304
|
`);for(let line of lines){let match=line.match(/CONFLICT\b.*(?:Merge conflict in |in )(.+)/);if(match?.[1])files.push(match[1].trim())}return files}function getMergeStrategy(config2){return config2.mergeStrategy??config2.merge_strategy??"merge"}async function mergeLaneBranch(primaryDir,branchName,strategy){let result;switch(strategy){case"merge":result=await runGit3(["merge","--no-edit",branchName],primaryDir);break;case"rebase":result=await runGit3(["rebase",branchName],primaryDir);break;case"cherry-pick":{let mergeBaseResult=await runGit3(["merge-base","HEAD",branchName],primaryDir);if(mergeBaseResult.exitCode===0&&mergeBaseResult.stdout.trim()){let mergeBase=mergeBaseResult.stdout.trim();result=await runGit3(["cherry-pick",`${mergeBase}..${branchName}`],primaryDir)}else console.warn("[worktree] mergeLaneBranch: git merge-base failed for cherry-pick; falling back to tip-only cherry-pick"),result=await runGit3(["cherry-pick",branchName],primaryDir);break}}if(result.exitCode===0)return{merged:!0,strategy};let combinedOutput=`${result.stderr}
|
|
305
305
|
${result.stdout}`;if(/CONFLICT/i.test(combinedOutput)||/conflict/i.test(combinedOutput)){let files=parseConflictFiles(combinedOutput);return await runGit3(strategy==="rebase"?["rebase","--abort"]:strategy==="cherry-pick"?["cherry-pick","--abort"]:["merge","--abort"],primaryDir),{conflict:!0,files,message:result.stderr.trim()}}return{error:result.stderr.trim()||result.stdout.trim()}}async function postMergeCleanup(directory,branchName){let deleteResult=await runGit3(["branch","-D",branchName],directory),deleteOk=deleteResult.exitCode===0,pruneResult=await runGit3(["worktree","prune"],directory),pruneOk=pruneResult.exitCode===0;if(deleteOk&&pruneOk)return{cleaned:!0};if(!deleteOk&&pruneOk)return{error:`Branch delete failed: ${deleteResult.stderr.trim()||deleteResult.stdout.trim()}`,partial:!0};return{error:deleteOk?`Worktree prune failed: ${pruneResult.stderr.trim()||pruneResult.stdout.trim()}`:`Branch delete failed: ${deleteResult.stderr.trim()||deleteResult.stdout.trim()}; worktree prune failed: ${pruneResult.stderr.trim()||pruneResult.stdout.trim()}`}}async function attemptMergeBackFromDirty(worktreePath,branchName,primaryDir,strategy){let autoCommitted=!1,cleaned=!1,autoCommitFailed=!1,cleanFailed=!1,commitResult=await autoCommitDirty(worktreePath);if(commitResult.committed)autoCommitted=!0;else if(commitResult.reason!=="Nothing to commit")autoCommitFailed=!0,console.warn(`[worktree] attemptMergeBackFromDirty: auto-commit failed for worktree "${worktreePath}" branch "${branchName}": ${commitResult.reason}`);let cleanResult=await cleanUntrackedFiles(worktreePath);if(cleanResult.cleaned)cleaned=!0;else cleanFailed=!0,console.warn(`[worktree] attemptMergeBackFromDirty: clean untracked failed for worktree "${worktreePath}" branch "${branchName}": ${cleanResult.error}`);if(autoCommitFailed&&cleanFailed)return{failed:!0,stage:"cleanup",message:"Auto-commit and clean both failed; abandoning worktree"};let mergeResult=await mergeLaneBranch(primaryDir,branchName,strategy);if("merged"in mergeResult&&mergeResult.merged)return{merged:!0,strategy,autoCommitted,cleaned};if("conflict"in mergeResult)return{partial:!0,stage:"merge",autoCommitted,cleaned,message:mergeResult.message,conflictFiles:mergeResult.files};if("error"in mergeResult)return{failed:!0,stage:"merge",message:mergeResult.error};return{failed:!0,stage:"merge",message:"Merge failed with unexpected result"}}function extractSessionId(branchName){let segments=branchName.trim().split("/");if(segments.length>=3&&segments[0]==="swarm-lane")return segments[1];if(segments.length>=4&&segments[0]==="swarm"&&segments[1]==="lane")return segments[2];return null}async function listLaneBranches(directory){let branches=new Set,result=await runGit3(["branch","--format=%(refname:short)"],directory);if(result.exitCode===0)for(let line of result.stdout.split(`
|
|
306
|
-
`)){let branch=line.trim();if(branch.length>0&&(branch.startsWith("swarm-lane/")||branch.startsWith("swarm/lane/")))branches.add(branch)}return[...branches]}async function cleanupOrphanedBranches(directory,activeSessionIds=[]){let removed=[],skipped=[],errors3=[],branches=await listLaneBranches(directory);for(let branch of branches){let sessionId=extractSessionId(branch);if(sessionId!==null&&activeSessionIds.includes(sessionId)){skipped.push(branch);continue}let deleteResult=await runGit3(["branch","-D",branch],directory);if(deleteResult.exitCode===0)removed.push(branch);else errors3.push({branch,error:deleteResult.stderr.trim()||deleteResult.stdout.trim()})}return await runGit3(["worktree","prune"],directory),{removed,skipped,errors:errors3}}async function startupOrphanRecovery(directory,activeSessionIds=[]){let warnings=[],pruneResult=await runGit3(["worktree","prune"],directory);if(pruneResult.exitCode!==0)warnings.push(`git worktree prune failed: ${pruneResult.stderr.trim()||pruneResult.stdout.trim()}`);let allBranches=await listLaneBranches(directory),orphanBranches=[];for(let branch of allBranches){let sessionId=extractSessionId(branch);if(sessionId===null||!activeSessionIds.includes(sessionId))orphanBranches.push(branch),warnings.push(`Orphaned swarm-lane branch "${branch}" detected in "${directory}"`)}for(let warning of warnings)console.warn(warning);return{prunedWorktrees:pruneResult.exitCode===0,remainingBranches:orphanBranches,warnings}}var _internals18,MERGE_TIMEOUT_MS=30000;var init_merge=__esm(()=>{init_bun_compat();init_core3();_internals18={bunSpawn,platform:process.platform,sleep:(ms)=>new Promise((resolve13)=>setTimeout(resolve13,ms)),cleanupOrphanedBranches,startupOrphanRecovery,extractSessionId}});var init_worktree=__esm(()=>{init_core3();init_merge()});import*as fs16 from"node:fs/promises";import*as path25 from"node:path";function parseLeanLaneIndex(laneId){let match=/^lane-(\d+)$/.exec(laneId);if(match){let n=parseInt(match[1],10);return Number.isNaN(n)?0:n-1}return 0}function computeLaneRuntimeProfile(runtime,laneIndex,worktreePath){if(!runtime?.enabled)return;let portStride=runtime.port_stride??1,envOverrides={};if(runtime.port_base!==void 0){let portBase=runtime.port_base,port=Math.min(portBase+laneIndex*portStride,65535);envOverrides.PORT=String(port)}if(runtime.env_overrides)Object.assign(envOverrides,runtime.env_overrides);if(runtime.cache_redirects)for(let[envName,basePath]of Object.entries(runtime.cache_redirects)){let laneSuffix=path25.join(basePath,`lane-${laneIndex}`);envOverrides[envName]=laneSuffix}return{laneIndex,worktreePath,envOverrides}}function allocateStandardLaneIndex(parentSessionID){let current=standardWorktreeLaneIndexBySession.get(parentSessionID)??0;return standardWorktreeLaneIndexBySession.set(parentSessionID,current+1),current}function rememberStandardWorktreeDispatch(dispatch){standardWorktreeByCallID.set(dispatch.callID,dispatch)}function hasStandardWorktreeDispatchCapacity(){return standardWorktreeByCallID.size<MAX_TRACKED_STANDARD_WORKTREE_CALLS}function hasInFlightStandardWorktreeDispatch(parentSessionID){for(let dispatch of standardWorktreeByCallID.values())if(dispatch.parentSessionID===parentSessionID)return!0;for(let record2 of awaitingMergeByCallID.values())if(record2.parentSessionID===parentSessionID)return!0;return!1}function handleStandardWorktreeFailure(parentSessionID,policy,message){if(policy==="required")throw Error(message);if(hasInFlightStandardWorktreeDispatch(parentSessionID))throw Error(`STANDARD_WORKTREE_ISOLATION_UNSAFE: ${message} Sibling coder task(s) are isolated in worktrees for this session, so dispatching this coder un-isolated in the main tree would risk a merge-back collision. Wait for in-flight coder task(s) to be reviewed and merged, then retry.`);serializeStandardWorktreeDispatches(parentSessionID,message)}function serializeStandardWorktreeDispatches(sessionID,message){if(!rememberStandardWorktreeSerializationSession(sessionID)){let session2=ensureAgentSession(sessionID);session2.pendingAdvisoryMessages??=[],session2.pendingAdvisoryMessages.push(`${message} Serialization tracking is at capacity (256 sessions active); continuing in normal parallel mode.`);return}let session=ensureAgentSession(sessionID);session.maxConcurrencyOverride=1,session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(`${message} Serializing standard coder dispatches for this session.`)}function resetStandardWorktreeIsolationState(){standardWorktreeByCallID.clear(),standardWorktreeSerializationSessions.clear(),serializationStateBySessionID.clear(),awaitingMergeByCallID.clear(),standardWorktreeMergeQueue=Promise.resolve(),standardWorktreeLaneIndexBySession.clear()}function releaseStandardWorktreeSerialization(sessionID){if(!standardWorktreeSerializationSessions.has(sessionID))return!1;standardWorktreeSerializationSessions.delete(sessionID),serializationStateBySessionID.delete(sessionID);let session=ensureAgentSession(sessionID);return session.maxConcurrencyOverride=void 0,session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(`WORKTREE_SERIALIZATION_RELEASED: ${sessionID} regains parallel dispatch eligibility (release-after-dispatches or TTL).`),!0}function checkStandardWorktreeSerializationRelease(sessionID,config2){let state=serializationStateBySessionID.get(sessionID);if(!state)return;let count=config2.serialization_release_after_dispatches??5,ttl=config2.serialization_release_after_ms??60000;if(state.successfulDispatchesSince>=count){releaseStandardWorktreeSerialization(sessionID);return}if(Date.now()-state.serializedAt>=ttl)releaseStandardWorktreeSerialization(sessionID)}function rememberStandardWorktreeSerializationSession(sessionID){if(standardWorktreeSerializationSessions.size>=MAX_TRACKED_STANDARD_WORKTREE_CALLS){let evicted=!1;for(let key of serializationStateBySessionID.keys())if(!hasInFlightStandardWorktreeDispatch(key)){standardWorktreeSerializationSessions.delete(key),serializationStateBySessionID.delete(key),evicted=!0;break}if(!evicted)return
|
|
307
|
-
`)){let line=rawLine.trim();if(line.startsWith("worktree ")){if(current.path)entries.push(current);current={path:line.slice(9),branch:void 0}}else if(line.startsWith("branch "))current.branch=line.slice(7)}if(current.path)entries.push(current);for(let entry of entries){if(!entry.branch)continue;let branchName=entry.branch.startsWith("refs/heads/")?entry.branch.slice(11):entry.branch,segments=branchName.split("/");if(segments.length>=4&&segments[0]==="swarm"&&segments[1]==="lane"){if(segments[3]===taskId){let ownerSessionId=segments[2];return{collision:!0,existingBranch:branchName,ownerSessionId,worktreePath:entry.path}}}if(segments.length>=3&&segments[0]==="swarm-lane"){if(segments[2]===taskId){let ownerSessionId=segments[1];return{collision:!0,existingBranch:branchName,ownerSessionId,worktreePath:entry.path}}}}return{collision:!1}}function isLaneOwnedByCurrentSession(branchName,expectedSessionId){return _internals18.extractSessionId(branchName)===expectedSessionId}async function precreateStandardWorktreeSession(args2){let worktreeConfig=resolveWorktreeIsolationConfig(args2.config);if(worktreeConfig.policy==="disabled")return;if(standardWorktreeSerializationSessions.has(args2.parentSessionID)){if(checkStandardWorktreeSerializationRelease(args2.parentSessionID,worktreeConfig),!standardWorktreeSerializationSessions.has(args2.parentSessionID))return}if(!hasStandardWorktreeDispatchCapacity()){if(worktreeConfig.policy==="required")throw Error("STANDARD_WORKTREE_TRACKING_CAP_EXCEEDED: too many standard worktree coder dispatches are already awaiting merge-back.");serializeStandardWorktreeDispatches(args2.parentSessionID,"STANDARD_WORKTREE_TRACKING_CAP_EXCEEDED: too many standard worktree coder dispatches are already awaiting merge-back.");return}let client=swarmState.opencodeClient;if(!client){handleStandardWorktreeFailure(args2.parentSessionID,worktreeConfig.policy,"STANDARD_WORKTREE_ISOLATION_UNAVAILABLE: OpenCode SDK client is unavailable; standard parallel coder work cannot be isolated.");return}try{await _internals19.startupOrphanRecovery(args2.directory,[args2.parentSessionID])}catch(recoveryError){console.warn(`[swarm] startup orphan recovery failed: ${recoveryError}`)}try{await _internals19.cleanupOrphanedBranches(args2.directory,[args2.parentSessionID])}catch(cleanupError){console.warn(`[swarm] orphaned branch cleanup failed: ${cleanupError}`)}let collision=await preProvisionCollisionCheck(args2.taskId,args2.directory,args2.parentSessionID);if(collision.collision)if(collision.existingBranch?isLaneOwnedByCurrentSession(collision.existingBranch,args2.parentSessionID):!1){let session=ensureAgentSession(args2.parentSessionID);session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(`FR-001b PREPROVISION: stale lane detected for task ${args2.taskId} (session ${args2.parentSessionID}); cleaning up before re-provisioning.`);try{let callID=null;for(let[id,dispatch]of _internals19.standardWorktreeByCallID)if(dispatch.handle.branchName===collision.existingBranch){callID=id;break}if(!callID){for(let[id,record2]of _internals19.awaitingMergeByCallID)if(record2.branch===collision.existingBranch){callID=id;break}}if(callID)await _internals19.cleanupStandardWorktreeForCallId(callID,"denied",args2.directory,worktreeConfig.worktree_dir);else{if(collision.worktreePath){let preserveResult=await _internals19.preserveDirtyWorktreeAtPath(collision.worktreePath,collision.existingBranch,"denied",args2.directory,worktreeConfig.worktree_dir);if(preserveResult.outcome==="preserve-failed"){let session2=ensureAgentSession(args2.parentSessionID);session2.pendingAdvisoryMessages??=[],session2.pendingAdvisoryMessages.push(`STANDARD_WORKTREE_PRESERVATION_FAILED_ABORT_CLEANUP: pre-provision collision for task ${args2.taskId} has dirty uncommitted work but preservation failed (${preserveResult.error}). Cleanup aborted to protect uncommitted work. Worktree=${collision.worktreePath}; branch=${collision.existingBranch}.`);return}await _internals19.removeWorktree(collision.worktreePath,args2.directory,{force:!0,worktreeDir:worktreeConfig.worktree_dir})}await _internals19.postMergeCleanup(args2.directory,collision.existingBranch)}}catch(cleanupError){console.warn(`[swarm] preProvision collision cleanup failed: ${cleanupError}; proceeding with provisioning anyway`)}}else{let ownerInfo=collision.ownerSessionId?` (owned by session ${collision.ownerSessionId})`:"",message=`FR-001b PREPROVISION_COLLISION: task ${args2.taskId} already has an active lane on branch ${collision.existingBranch}${ownerInfo}. Waiting for the owning session to complete and merge before retrying.`,session=ensureAgentSession(args2.parentSessionID);session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(message),handleStandardWorktreeFailure(args2.parentSessionID,worktreeConfig.policy,`PREPROVISION_COLLISION: ${message}`);return}let laneIndex=allocateStandardLaneIndex(args2.parentSessionID),provisionResult=await _internals19.provisionWorktree(args2.directory,args2.taskId,args2.parentSessionID,{purpose:"lane",worktreeDir:worktreeConfig.worktree_dir,mergeStrategy:worktreeConfig.merge_strategy,depsStrategy:worktreeConfig.deps_strategy,scope:args2.scope});if("error"in provisionResult){let message=`STANDARD_WORKTREE_PROVISION_FAILED: ${provisionResult.error}.`;handleStandardWorktreeFailure(args2.parentSessionID,worktreeConfig.policy,message);return}let laneProfile=computeLaneRuntimeProfile(worktreeConfig.runtime_isolation,laneIndex,provisionResult.worktreePath);if(laneProfile)try{let{writeLaneProfileToDiskReal:writeLaneProfileToDiskReal2}=await Promise.resolve().then(() => (init_core3(),exports_core3));await writeLaneProfileToDiskReal2(provisionResult.worktreePath,laneProfile.laneIndex,laneProfile.envOverrides)}catch{}if((worktreeConfig.deps_strategy??"skip")==="skip"){let desc=(args2.description??args2.taskId??"").toLowerCase();if(desc.includes("test")||desc.includes("build")||desc.includes("lint")||desc.includes("check")){let session=ensureAgentSession(args2.parentSessionID);session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(`WORKTREE_DEPS_SKIP: task ${args2.taskId} was provisioned with deps_strategy: 'skip' (default). This task's gates appear to include test/build commands; the lane may lack node_modules. Set worktree.deps_strategy to 'copy' or 'link' (or use a non-worktree lane) if the task requires host dependencies.`)}}let createResult=await client.session.create({body:{parentID:args2.parentSessionID,title:`${args2.description??args2.taskId} (worktree lane)`},query:{directory:provisionResult.worktreePath}});if(!createResult.data?.id){await _internals19.removeWorktree(provisionResult.worktreePath,args2.directory,{force:!0,worktreeDir:worktreeConfig.worktree_dir}).catch(()=>{});let createError=createResult.error,message=`STANDARD_WORKTREE_SESSION_CREATE_FAILED: ${typeof createError==="string"?createError:JSON.stringify(createError??"missing session id")}.`;handleStandardWorktreeFailure(args2.parentSessionID,worktreeConfig.policy,message);return}args2.outputArgs.task_id=createResult.data.id,rememberStandardWorktreeDispatch({callID:args2.callID,parentSessionID:args2.parentSessionID,taskId:args2.taskId,planTaskId:args2.planTaskId,handle:provisionResult,mergeStrategy:worktreeConfig.merge_strategy,laneIndex,worktree_dir:worktreeConfig.worktree_dir})}async function preserveDirtyWorktreeForCallId(callID,reason,_directory,_worktree_dir){let dispatch=standardWorktreeByCallID.get(callID),worktreePath,parentSessionID;if(dispatch)worktreePath=dispatch.handle.worktreePath,parentSessionID=dispatch.parentSessionID;else{let awaiting=awaitingMergeByCallID.get(callID);if(!awaiting)return{outcome:"clean",preserved:!1};worktreePath=awaiting.worktreePath,parentSessionID=awaiting.parentSessionID}let statusProc=_internals19.bunSpawn(["git","-C",worktreePath,"status","--porcelain"],{stdin:"ignore",stdout:"pipe",stderr:"pipe",timeout:PRESERVE_COMMIT_TIMEOUT_MS}),statusStdout="",statusStderr="";try{let exitCode=await statusProc.exited;if(statusStdout=await statusProc.stdout.text(),statusStderr=await statusProc.stderr.text(),exitCode!==0)return console.warn(`[swarm] preserveDirtyWorktreeForCallId: git status failed for ${callID}: ${statusStderr}`),{outcome:"preserve-failed",preserved:!1,error:`git status failed: ${statusStderr||`exit ${exitCode}`}`}}finally{try{statusProc.kill()}catch{}}if(statusStdout.trim()==="")return{outcome:"clean",preserved:!1};let addProc=_internals19.bunSpawn(["git","-C",worktreePath,"add","-A"],{stdin:"ignore",stdout:"pipe",stderr:"pipe",timeout:PRESERVE_COMMIT_TIMEOUT_MS});try{let addExit=await addProc.exited;if(addExit!==0){let addErr=await addProc.stderr.text();return console.warn(`[swarm] preserveDirtyWorktreeForCallId: git add failed for ${callID}: ${addErr}`),{outcome:"preserve-failed",preserved:!1,error:`git add failed: ${addErr||`exit ${addExit}`}`}}}finally{try{addProc.kill()}catch{}}let isoDate=new Date().toISOString(),sanitizedCallID=callID.replace(/[^A-Za-z0-9._-]/g,"-").slice(0,64),commitMessage=`swarm-preserved: ${reason} for callID ${sanitizedCallID} at ${isoDate}`,commitProc=_internals19.bunSpawn(["git","-C",worktreePath,"commit","-m",commitMessage],{stdin:"ignore",stdout:"pipe",stderr:"pipe",timeout:PRESERVE_COMMIT_TIMEOUT_MS}),commitHash="";try{let commitExit=await commitProc.exited;if(commitExit!==0){let commitErr=await commitProc.stderr.text();return console.warn(`[swarm] preserveDirtyWorktreeForCallId: git commit failed for ${callID}: ${commitErr}`),{outcome:"preserve-failed",preserved:!1,error:`git commit failed: ${commitErr||`exit ${commitExit}`}`}}}finally{try{commitProc.kill()}catch{}}let hashProc=_internals19.bunSpawn(["git","-C",worktreePath,"rev-parse","HEAD"],{stdin:"ignore",stdout:"pipe",stderr:"pipe",timeout:PRESERVE_COMMIT_TIMEOUT_MS});try{let hashExit=await hashProc.exited;if(hashExit!==0){let hashErr=await hashProc.stderr.text();return console.warn(`[swarm] preserveDirtyWorktreeForCallId: git rev-parse failed for ${callID}: ${hashErr}`),{outcome:"preserve-failed",preserved:!1,error:`git rev-parse failed: ${hashErr||`exit ${hashExit}`}`}}commitHash=(await hashProc.stdout.text()).trim()}finally{try{hashProc.kill()}catch{}}if(!commitHash)return{outcome:"preserve-failed",preserved:!1,error:"git rev-parse returned empty hash"};let shortHash=commitHash.slice(0,8),tagName=`swarm-preserved-${sanitizedCallID}-${shortHash}`,tagProc=_internals19.bunSpawn(["git","-C",worktreePath,"tag",tagName],{stdin:"ignore",stdout:"pipe",stderr:"pipe",timeout:PRESERVE_COMMIT_TIMEOUT_MS});try{let tagExit=await tagProc.exited;if(tagExit!==0){let tagErr=await tagProc.stderr.text();return console.warn(`[swarm] preserveDirtyWorktreeForCallId: git tag failed for ${callID}: ${tagErr}`),{outcome:"preserve-failed",preserved:!1,error:`git tag failed: ${tagErr||`exit ${tagExit}`}`}}}finally{try{tagProc.kill()}catch{}}let session=ensureAgentSession(parentSessionID);return session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(`STANDARD_WORKTREE_PRESERVED: dispatch ${callID} dirty work preserved as commit ${commitHash} (tag: ${tagName}; reason: ${reason}); worktree will be cleaned.`),{outcome:"preserved",preserved:!0,ref:commitHash}}async function preserveDirtyWorktreeAtPath(worktreePath,branchName,reason,_directory,_worktree_dir){let statusProc=_internals19.bunSpawn(["git","-C",worktreePath,"status","--porcelain"],{stdin:"ignore",stdout:"pipe",stderr:"pipe",timeout:PRESERVE_COMMIT_TIMEOUT_MS}),statusStdout="",statusStderr="";try{let exitCode=await statusProc.exited;if(statusStdout=await statusProc.stdout.text(),statusStderr=await statusProc.stderr.text(),exitCode!==0)return console.warn(`[swarm] preserveDirtyWorktreeAtPath: git status failed for ${worktreePath}: ${statusStderr}`),{outcome:"preserve-failed",preserved:!1,error:`git status failed: ${statusStderr||`exit ${exitCode}`}`}}finally{try{statusProc.kill()}catch{}}if(statusStdout.trim()==="")return{outcome:"clean",preserved:!1};let addProc=_internals19.bunSpawn(["git","-C",worktreePath,"add","-A"],{stdin:"ignore",stdout:"pipe",stderr:"pipe",timeout:PRESERVE_COMMIT_TIMEOUT_MS});try{let addExit=await addProc.exited;if(addExit!==0){let addErr=await addProc.stderr.text();return console.warn(`[swarm] preserveDirtyWorktreeAtPath: git add failed for ${worktreePath}: ${addErr}`),{outcome:"preserve-failed",preserved:!1,error:`git add failed: ${addErr||`exit ${addExit}`}`}}}finally{try{addProc.kill()}catch{}}let isoDate=new Date().toISOString(),sanitizedPath=worktreePath.replace(/[^A-Za-z0-9._-]/g,"-").slice(0,64),sanitizedBranch=branchName.replace(/[^A-Za-z0-9._-]/g,"-").slice(0,64),commitMessage=`swarm-preserved: ${reason} for worktree ${sanitizedPath} at ${isoDate}`,commitProc=_internals19.bunSpawn(["git","-C",worktreePath,"commit","-m",commitMessage],{stdin:"ignore",stdout:"pipe",stderr:"pipe",timeout:PRESERVE_COMMIT_TIMEOUT_MS}),commitHash="";try{let commitExit=await commitProc.exited;if(commitExit!==0){let commitErr=await commitProc.stderr.text();return console.warn(`[swarm] preserveDirtyWorktreeAtPath: git commit failed for ${worktreePath}: ${commitErr}`),{outcome:"preserve-failed",preserved:!1,error:`git commit failed: ${commitErr||`exit ${commitExit}`}`}}}finally{try{commitProc.kill()}catch{}}let hashProc=_internals19.bunSpawn(["git","-C",worktreePath,"rev-parse","HEAD"],{stdin:"ignore",stdout:"pipe",stderr:"pipe",timeout:PRESERVE_COMMIT_TIMEOUT_MS});try{let hashExit=await hashProc.exited;if(hashExit!==0){let hashErr=await hashProc.stderr.text();return console.warn(`[swarm] preserveDirtyWorktreeAtPath: git rev-parse failed for ${worktreePath}: ${hashErr}`),{outcome:"preserve-failed",preserved:!1,error:`git rev-parse failed: ${hashErr||`exit ${hashExit}`}`}}commitHash=(await hashProc.stdout.text()).trim()}finally{try{hashProc.kill()}catch{}}if(!commitHash)return{outcome:"preserve-failed",preserved:!1,error:"git rev-parse returned empty hash"};let shortHash=commitHash.slice(0,8),tagName=`swarm-preserved-worktree-${sanitizedBranch}-${shortHash}`,tagProc=_internals19.bunSpawn(["git","-C",worktreePath,"tag",tagName],{stdin:"ignore",stdout:"pipe",stderr:"pipe",timeout:PRESERVE_COMMIT_TIMEOUT_MS});try{let tagExit=await tagProc.exited;if(tagExit!==0){let tagErr=await tagProc.stderr.text();return console.warn(`[swarm] preserveDirtyWorktreeAtPath: git tag failed for ${worktreePath}: ${tagErr}`),{outcome:"preserve-failed",preserved:!1,error:`git tag failed: ${tagErr||`exit ${tagExit}`}`}}}finally{try{tagProc.kill()}catch{}}return{outcome:"preserved",preserved:!0,ref:commitHash}}async function cleanupStandardWorktreeForCallId(callID,reason,directory,worktree_dir){let dispatch=standardWorktreeByCallID.get(callID),worktreePath,branchName,parentSessionID;if(dispatch)worktreePath=dispatch.handle.worktreePath,branchName=dispatch.handle.branchName,parentSessionID=dispatch.parentSessionID;else{let awaiting=awaitingMergeByCallID.get(callID);if(!awaiting)return;worktreePath=awaiting.worktreePath,branchName=awaiting.branch,parentSessionID=awaiting.parentSessionID}let preserveResult;if(reason==="denied"||reason==="cancelled"){try{preserveResult=await _internals19.preserveDirtyWorktreeForCallId(callID,reason,directory,worktree_dir)}catch(err){console.warn(`[swarm] cleanupStandardWorktreeForCallId: preserveDirtyWorktreeForCallId threw for ${callID}: ${err}`),preserveResult={outcome:"preserve-failed",preserved:!1,error:String(err)}}if(preserveResult.outcome==="clean")try{preserveResult=await _internals19.preserveDirtyWorktreeForCallId(callID,reason,directory,worktree_dir)}catch(err){console.warn(`[swarm] cleanupStandardWorktreeForCallId: final preservation check threw for ${callID}: ${err}`),preserveResult={outcome:"preserve-failed",preserved:!1,error:String(err)}}}if(preserveResult&&preserveResult.outcome==="preserve-failed"){standardWorktreeByCallID.delete(callID),awaitingMergeByCallID.delete(callID);let session2=ensureAgentSession(parentSessionID);session2.pendingAdvisoryMessages??=[],session2.pendingAdvisoryMessages.push(`STANDARD_WORKTREE_PRESERVATION_FAILED_ABORT_CLEANUP: dispatch ${callID} has dirty uncommitted work but preservation failed (${preserveResult.error}). Cleanup aborted to protect uncommitted work. Investigate and resolve manually. Worktree=${worktreePath}; branch=${branchName}.`);return}await _internals19.removeWorktree(worktreePath,directory,{force:!0,worktreeDir:worktree_dir}).catch((err)=>console.warn(`[swarm] cleanupStandardWorktreeForCallId: removeWorktree failed for ${callID}: ${err}`)),await _internals19.postMergeCleanup(directory,branchName).catch((err)=>console.warn(`[swarm] cleanupStandardWorktreeForCallId: postMergeCleanup failed for ${callID}: ${err}`)),standardWorktreeByCallID.delete(callID),awaitingMergeByCallID.delete(callID);let session=ensureAgentSession(parentSessionID);session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(`STANDARD_WORKTREE_CLEANUP: dispatch ${callID} cleaned up (reason: ${reason}); worktree=${worktreePath}; branch=${branchName}.`)}async function abortStandardWorktreeDispatch(callID,reason,directory){let dispatch=standardWorktreeByCallID.get(callID);if(!dispatch){let session=ensureAgentSession("unknown");session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(`STANDARD_WORKTREE_ABORT_NOOP: dispatch ${callID} has no tracked worktree to abort (reason: ${reason}).`);return}await cleanupStandardWorktreeForCallId(callID,reason,directory,dispatch.worktree_dir)}async function finishStandardWorktreeDispatch(directory,dispatch,config2,callID){let wtConfig=config2?resolveWorktreeIsolationConfig(config2):DEFAULT_WORKTREE_ISOLATION_CONFIG,resolvedCallID=callID??dispatch.callID,run=async()=>{let mergeResult=await _internals19.attemptMergeBackFromDirty(dispatch.handle.worktreePath,dispatch.handle.branchName,directory,getMergeStrategy({merge_strategy:dispatch.mergeStrategy})),statusKey=dispatch.planTaskId??dispatch.taskId;if("merged"in mergeResult&&mergeResult.merged){clearWorktreeMergeStatus(statusKey);try{let{removeLaneProfileFromDiskReal:removeLaneProfileFromDiskReal2}=await Promise.resolve().then(() => (init_core3(),exports_core3));await removeLaneProfileFromDiskReal2(dispatch.handle.worktreePath,dispatch.laneIndex)}catch{}let state=serializationStateBySessionID.get(dispatch.parentSessionID);if(state)state.successfulDispatchesSince++,checkStandardWorktreeSerializationRelease(dispatch.parentSessionID,wtConfig);await cleanupStandardWorktreeForCallId(resolvedCallID,"success",directory,dispatch.worktree_dir);return}if("partial"in mergeResult){recordWorktreeMergeFailure(statusKey,{outcome:"partial",stage:mergeResult.stage,message:mergeResult.message,worktreePath:dispatch.handle.worktreePath,branch:dispatch.handle.branchName,completedAt:Date.now()});let session=ensureAgentSession(dispatch.parentSessionID);session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(`STANDARD_WORKTREE_MERGE_PARTIAL: task ${dispatch.taskId} preserved at ${dispatch.handle.worktreePath}; stage: ${mergeResult.stage}; ${mergeResult.message}`);return}if("failed"in mergeResult){recordWorktreeMergeFailure(statusKey,{outcome:"failed",stage:mergeResult.stage,message:mergeResult.message,worktreePath:dispatch.handle.worktreePath,branch:dispatch.handle.branchName,completedAt:Date.now()});let session=ensureAgentSession(dispatch.parentSessionID);session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(`STANDARD_WORKTREE_MERGE_FAILED: task ${dispatch.taskId} preserved at ${dispatch.handle.worktreePath}; stage: ${mergeResult.stage}; ${mergeResult.message}.`)}};if(standardWorktreeMergeQueue=standardWorktreeMergeQueue.then(run,run),await standardWorktreeMergeQueue,resolvedCallID)awaitingMergeByCallID.delete(resolvedCallID)}async function readLaneEnvFileFromDisk(worktreePath,laneIndex){let envPath=path25.join(worktreePath,".swarm","lanes",`${laneIndex}.env`),content;try{content=await fs16.readFile(envPath,"utf-8")}catch(err){if(err.code==="ENOENT")return{};return console.warn(`[worktree-isolation] failed to read lane env file ${envPath}: ${err.message}`),{}}let result={};for(let rawLine of content.split(`
|
|
308
|
-
`)){let line=rawLine.trim();if(!line||line.startsWith("#"))continue;let eqIdx=line.indexOf("=");if(eqIdx<0)continue;let k=line.slice(0,eqIdx),v=line.slice(eqIdx+1);if(!isValidEnvKey(k))continue;result[k]=v}return result}var MAX_TRACKED_STANDARD_WORKTREE_CALLS=256,awaitingMergeByCallID,standardWorktreeByCallID,standardWorktreeSerializationSessions,standardWorktreeMergeQueue,standardWorktreeLaneIndexBySession,serializationStateBySessionID,WORKTREE_LIST_TIMEOUT_MS=15000,PRESERVE_COMMIT_TIMEOUT_MS=30000,_internals19;var init_worktree_isolation=__esm(()=>{init_constants();init_executor();init_state2();init_bun_compat();init_worktree();init_worktree_merge_status();init_worktree_isolation_config();awaitingMergeByCallID=new Map,standardWorktreeByCallID=new Map,standardWorktreeSerializationSessions=new Set,standardWorktreeMergeQueue=Promise.resolve(),standardWorktreeLaneIndexBySession=new Map,serializationStateBySessionID=new Map;_internals19={provisionWorktree,removeWorktree,attemptMergeBackFromDirty,postMergeCleanup,readLaneEnvFileFromDisk,serializationStateBySessionID,rememberStandardWorktreeSerializationSession,awaitingMergeByCallID,startupOrphanRecovery,cleanupOrphanedBranches,cleanupStandardWorktreeForCallId,preserveDirtyWorktreeForCallId,preserveDirtyWorktreeAtPath,abortStandardWorktreeDispatch,standardWorktreeByCallID,preProvisionCollisionCheck,isLaneOwnedByCurrentSession,bunSpawn}});function resolveMemoryConfig(input){return{...DEFAULT_MEMORY_CONFIG,...input??{},sqlite:{...DEFAULT_MEMORY_CONFIG.sqlite,...input?.sqlite??{}},recall:{...DEFAULT_MEMORY_CONFIG.recall,...input?.recall??{},injection:{...DEFAULT_MEMORY_CONFIG.recall.injection,...input?.recall?.injection??{}}},learning:{...DEFAULT_MEMORY_CONFIG.learning,...input?.learning??{}},writes:{...DEFAULT_MEMORY_CONFIG.writes,...input?.writes??{}},redaction:{...DEFAULT_MEMORY_CONFIG.redaction,...input?.redaction??{}},maintenance:{...DEFAULT_MEMORY_CONFIG.maintenance,...input?.maintenance??{},importance:{...DEFAULT_MEMORY_CONFIG.maintenance.importance,...input?.maintenance?.importance??{}}},consolidation:{...DEFAULT_MEMORY_CONFIG.consolidation,...input?.consolidation??{},decayHalfLifeDays:{...DEFAULT_MEMORY_CONFIG.consolidation.decayHalfLifeDays,...input?.consolidation?.decayHalfLifeDays??{}}},embeddings:{...DEFAULT_MEMORY_CONFIG.embeddings,...input?.embeddings??{}},retrieval:{...DEFAULT_MEMORY_CONFIG.retrieval,...input?.retrieval??{},weights:{...DEFAULT_MEMORY_CONFIG.retrieval.weights,...input?.retrieval?.weights??{}},rerank:{...DEFAULT_MEMORY_CONFIG.retrieval.rerank,...input?.retrieval?.rerank??{}}},qLearning:{...DEFAULT_MEMORY_CONFIG.qLearning,...input?.qLearning??{}}}}var DEFAULT_DECAY_HALF_LIFE_DAYS,DEFAULT_IMPORTANCE_CONFIG,DEFAULT_QLEARNING_CONFIG,COUNCIL_VERDICT_REWARDS,DEFAULT_CONSOLIDATION_CONFIG,DEFAULT_MEMORY_LEARNING_CONFIG,DEFAULT_EMBEDDINGS_CONFIG,DEFAULT_RETRIEVAL_CONFIG,DEFAULT_MEMORY_CONFIG,DURABLE_MEMORY_KINDS,EVIDENCE_REQUIRED_KINDS;var init_config2=__esm(()=>{DEFAULT_DECAY_HALF_LIFE_DAYS={scratch:7,todo:30,code_pattern:90,test_pattern:90,failure_pattern:90,api_finding:180,evidence:180,architecture_decision:0,repo_convention:0,project_fact:0,security_note:0,user_preference:0},DEFAULT_IMPORTANCE_CONFIG={wRecency:0.2,wFrequency:0.2,wFreshness:0.15,wConfidence:0.25,lambda:0.05,mu:0.01,n:50,threshold:0.2},DEFAULT_QLEARNING_CONFIG={learningRate:0.1,qValueBoostWeight:0.1,suppressionThreshold:0.15,promotionThreshold:0.85,promotionMinRetrievals:5,propagationFraction:0.3,propagationFanoutCap:20,propagationWindowDays:30,propagationRelatednessThreshold:0.7,explorationRate:0.05,verdictPayloadCapBytes:8192,initialQValue:0.5},COUNCIL_VERDICT_REWARDS={APPROVE:1,CONCERNS:0.5,REJECT:0},DEFAULT_CONSOLIDATION_CONFIG={enabled:!1,maxClustersPerPass:10,jaccardThreshold:0.3,autoApplyMinConfidence:0.6,decayHalfLifeDays:{...DEFAULT_DECAY_HALF_LIFE_DAYS}},DEFAULT_MEMORY_LEARNING_CONFIG={learningRate:0.1,propagationFactor:0.3,qValueBoostWeight:0.1,suppressionThreshold:0.15,promotionThreshold:0.85,propagationTokenOverlapThreshold:0.4,propagationEmbeddingCosineThreshold:0.7,propagationFanout:20,propagationLookbackDays:30},DEFAULT_EMBEDDINGS_CONFIG={enabled:!1,model:"Xenova/all-MiniLM-L6-v2",dimension:384,cacheSize:256},DEFAULT_RETRIEVAL_CONFIG={rrfK:60,weights:{lexical:0.5,dense:0.4,metadata:0.1},rerank:{enabled:!1},latencyBudgetMs:250},DEFAULT_MEMORY_CONFIG={enabled:!1,provider:"sqlite",storageDir:".swarm/memory",sqlite:{path:".swarm/memory/memory.db",busyTimeoutMs:5000},recall:{defaultMaxItems:8,defaultTokenBudget:1200,minScore:0.05,injection:{enabled:!0,minScore:0.25,requireQuerySignal:!0,maxItems:6,tokenBudget:1000}},learning:{...DEFAULT_MEMORY_LEARNING_CONFIG},writes:{mode:"propose"},redaction:{rejectDurableSecrets:!0},maintenance:{lowUtilityMaxConfidence:0.45,lowUtilityMinAgeDays:30,autoCompactEveryNRecalls:50,importance:{...DEFAULT_IMPORTANCE_CONFIG}},consolidation:{...DEFAULT_CONSOLIDATION_CONFIG,decayHalfLifeDays:{...DEFAULT_DECAY_HALF_LIFE_DAYS}},embeddings:{...DEFAULT_EMBEDDINGS_CONFIG},retrieval:{...DEFAULT_RETRIEVAL_CONFIG},qLearning:{...DEFAULT_QLEARNING_CONFIG},hardDelete:!1},DURABLE_MEMORY_KINDS=new Set(["user_preference","project_fact","architecture_decision","repo_convention","code_pattern","test_pattern","failure_pattern","security_note"]),EVIDENCE_REQUIRED_KINDS=new Set(["api_finding","evidence","security_note"])});var MemoryValidationError,MemoryDisabledError;var init_errors4=__esm(()=>{MemoryValidationError=class MemoryValidationError extends Error{code;constructor(message,code="memory_validation_error"){super(message);this.name="MemoryValidationError",this.code=code}};MemoryDisabledError=class MemoryDisabledError extends Error{constructor(message="Swarm memory is disabled"){super(message);this.name="MemoryDisabledError"}}});function findSecrets(text){let findings=[];for(let{type,pattern}of SECRET_PATTERNS){pattern.lastIndex=0;for(let match of text.matchAll(pattern))if(match[0])findings.push({type,match:match[0]})}return findings}function containsSecret(text){return findSecrets(text).length>0}function redactSecrets(text){let redacted=text;for(let{type,pattern}of SECRET_PATTERNS)pattern.lastIndex=0,redacted=redacted.replace(pattern,`[REDACTED:${type}]`);return redacted}var SECRET_PATTERNS;var init_redaction=__esm(()=>{SECRET_PATTERNS=[{type:"openai_api_key",pattern:/\bsk-[A-Za-z0-9_-]{20,}\b/g},{type:"github_token",pattern:/\b(?:ghp|gho|ghu|ghs|ghr|github_pat)_[A-Za-z0-9_]{20,}\b/g},{type:"aws_access_key_id",pattern:/\bAKIA[0-9A-Z]{16}\b/g},{type:"private_key_block",pattern:/-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g},{type:"authorization_bearer",pattern:/\bAuthorization\s*:\s*Bearer\s+[A-Za-z0-9._~+/=-]{12,}/gi},{type:"env_secret",pattern:/\b(?:[A-Z][A-Z0-9]+_)+(?:KEY|TOKEN|SECRET|PASSWORD)\b\s*=\s*["']?[^\s"'`]{8,}["']?/gi},{type:"gitlab_token",pattern:/\bgl(?:pat|ptt)-[A-Za-z0-9_-]{15,}\b/g},{type:"slack_token",pattern:/\bxox[abprs]-[A-Za-z0-9-]{10,}\b/g},{type:"jwt_token",pattern:/\beyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g},{type:"aws_secret_access_key",pattern:/\b(?:aws_secret_access_key|AWS_SECRET_ACCESS_KEY)\s*[=:]\s*[A-Za-z0-9/+=]{40}\b/g},{type:"stripe_secret_key",pattern:/\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{24,}\b/g},{type:"google_api_key",pattern:/\bAIza[0-9A-Za-z_-]{35}\b/g},{type:"openssh_private_key_block",pattern:/-----BEGIN[ ]OPENSSH[ ]PRIVATE[ ]KEY-----[\s\S]*?-----END[ ]OPENSSH[ ]PRIVATE[ ]KEY-----/g}]});var MEMORY_RECALL_SENTINEL="## Retrieved Swarm Memory";import{createHash as createHash7}from"node:crypto";function normalizeMemoryText(text){return text.replace(/\s+/g," ").trim()}function stableScopeKey(scope){let ordered={type:scope.type},keys=scope.type==="repository"?["repoId"]:["userId","workspaceId","projectId","repoId","repoRoot","runId","agentId"];for(let key of keys){let value=scope[key];if(value)ordered[key]=value}return JSON.stringify(ordered)}function computeMemoryContentHash(recordLike){let normalized=normalizeMemoryText(recordLike.text).toLowerCase();return createHash7("sha256").update(`${stableScopeKey(recordLike.scope)}
|
|
306
|
+
`)){let branch=line.trim();if(branch.length>0&&(branch.startsWith("swarm-lane/")||branch.startsWith("swarm/lane/")))branches.add(branch)}return[...branches]}async function cleanupOrphanedBranches(directory,activeSessionIds=[]){let removed=[],skipped=[],errors3=[],branches=await listLaneBranches(directory);for(let branch of branches){let sessionId=extractSessionId(branch);if(sessionId!==null&&activeSessionIds.includes(sessionId)){skipped.push(branch);continue}let deleteResult=await runGit3(["branch","-D",branch],directory);if(deleteResult.exitCode===0)removed.push(branch);else errors3.push({branch,error:deleteResult.stderr.trim()||deleteResult.stdout.trim()})}return await runGit3(["worktree","prune"],directory),{removed,skipped,errors:errors3}}async function startupOrphanRecovery(directory,activeSessionIds=[]){let warnings=[],pruneResult=await runGit3(["worktree","prune"],directory);if(pruneResult.exitCode!==0)warnings.push(`git worktree prune failed: ${pruneResult.stderr.trim()||pruneResult.stdout.trim()}`);let allBranches=await listLaneBranches(directory),orphanBranches=[];for(let branch of allBranches){let sessionId=extractSessionId(branch);if(sessionId===null||!activeSessionIds.includes(sessionId))orphanBranches.push(branch),warnings.push(`Orphaned swarm-lane branch "${branch}" detected in "${directory}"`)}for(let warning of warnings)console.warn(warning);return{prunedWorktrees:pruneResult.exitCode===0,remainingBranches:orphanBranches,warnings}}var _internals18,MERGE_TIMEOUT_MS=30000;var init_merge=__esm(()=>{init_bun_compat();init_core3();_internals18={bunSpawn,platform:process.platform,sleep:(ms)=>new Promise((resolve13)=>setTimeout(resolve13,ms)),cleanupOrphanedBranches,startupOrphanRecovery,extractSessionId}});var init_worktree=__esm(()=>{init_core3();init_merge()});import*as fs16 from"node:fs/promises";import*as path25 from"node:path";function parseLeanLaneIndex(laneId){let match=/^lane-(\d+)$/.exec(laneId);if(match){let n=parseInt(match[1],10);return Number.isNaN(n)?0:n-1}return 0}function computeLaneRuntimeProfile(runtime,laneIndex,worktreePath){if(!runtime?.enabled)return;let portStride=runtime.port_stride??1,envOverrides={};if(runtime.port_base!==void 0){let portBase=runtime.port_base,port=Math.min(portBase+laneIndex*portStride,65535);envOverrides.PORT=String(port)}if(runtime.env_overrides)Object.assign(envOverrides,runtime.env_overrides);if(runtime.cache_redirects)for(let[envName,basePath]of Object.entries(runtime.cache_redirects)){let laneSuffix=path25.join(basePath,`lane-${laneIndex}`);envOverrides[envName]=laneSuffix}return{laneIndex,worktreePath,envOverrides}}function allocateStandardLaneIndex(parentSessionID){let current=standardWorktreeLaneIndexBySession.get(parentSessionID)??0;return standardWorktreeLaneIndexBySession.set(parentSessionID,current+1),current}function rememberStandardWorktreeDispatch(dispatch){standardWorktreeByCallID.set(dispatch.callID,dispatch)}function hasStandardWorktreeDispatchCapacity(){return standardWorktreeByCallID.size<MAX_TRACKED_STANDARD_WORKTREE_CALLS}function hasInFlightStandardWorktreeDispatch(parentSessionID){for(let dispatch of standardWorktreeByCallID.values())if(dispatch.parentSessionID===parentSessionID)return!0;for(let record2 of awaitingMergeByCallID.values())if(record2.parentSessionID===parentSessionID)return!0;return!1}function handleStandardWorktreeFailure(parentSessionID,policy,message){if(policy==="required")throw Error(message);if(hasInFlightStandardWorktreeDispatch(parentSessionID))throw Error(`STANDARD_WORKTREE_ISOLATION_UNSAFE: ${message} Sibling coder task(s) are isolated in worktrees for this session, so dispatching this coder un-isolated in the main tree would risk a merge-back collision. Wait for in-flight coder task(s) to be reviewed and merged, then retry.`);serializeStandardWorktreeDispatches(parentSessionID,message)}function serializeStandardWorktreeDispatches(sessionID,message){if(!rememberStandardWorktreeSerializationSession(sessionID)){let session2=ensureAgentSession(sessionID);session2.pendingAdvisoryMessages??=[],session2.pendingAdvisoryMessages.push(`${message} Serialization tracking is at capacity (256 sessions active); continuing in normal parallel mode.`);return}let session=ensureAgentSession(sessionID);session.maxConcurrencyOverride=1,session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(`${message} Serializing standard coder dispatches for this session.`)}function resetStandardWorktreeIsolationState(){standardWorktreeByCallID.clear(),standardWorktreeSerializationSessions.clear(),serializationStateBySessionID.clear(),awaitingMergeByCallID.clear(),standardWorktreeMergeQueue=Promise.resolve(),standardWorktreeLaneIndexBySession.clear()}function releaseStandardWorktreeSerialization(sessionID){if(!standardWorktreeSerializationSessions.has(sessionID))return!1;standardWorktreeSerializationSessions.delete(sessionID),serializationStateBySessionID.delete(sessionID);let session=ensureAgentSession(sessionID);return session.maxConcurrencyOverride=void 0,session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(`WORKTREE_SERIALIZATION_RELEASED: ${sessionID} regains parallel dispatch eligibility (release-after-dispatches or TTL).`),!0}function checkStandardWorktreeSerializationRelease(sessionID,config2){let state=serializationStateBySessionID.get(sessionID);if(!state)return;let count=config2.serialization_release_after_dispatches??5,ttl=config2.serialization_release_after_ms??60000;if(state.successfulDispatchesSince>=count){releaseStandardWorktreeSerialization(sessionID);return}if(Date.now()-state.serializedAt>=ttl)releaseStandardWorktreeSerialization(sessionID)}function rememberStandardWorktreeSerializationSession(sessionID){if(standardWorktreeSerializationSessions.size>=MAX_TRACKED_STANDARD_WORKTREE_CALLS){let evicted=!1;for(let key of serializationStateBySessionID.keys())if(!hasInFlightStandardWorktreeDispatch(key)){standardWorktreeSerializationSessions.delete(key),serializationStateBySessionID.delete(key),evicted=!0;break}if(!evicted)return log(`[worktree-isolation] serialization set at cap with all sessions active; refusing eviction for ${sessionID}`),!1}if(standardWorktreeSerializationSessions.add(sessionID),!serializationStateBySessionID.has(sessionID))serializationStateBySessionID.set(sessionID,{sessionID,serializedAt:Date.now(),successfulDispatchesSince:0});return!0}function sanitizeWorktreeTaskId(raw){return raw.replace(/[^A-Za-z0-9._-]/g,"-").slice(0,64)||"task"}async function preProvisionCollisionCheck(taskId,directory,_sessionId){let proc=_internals19.bunSpawn(["git","-C",directory,"worktree","list","--porcelain"],{stdin:"ignore",stdout:"pipe",stderr:"pipe",timeout:WORKTREE_LIST_TIMEOUT_MS}),stdout="",stderr="";try{let exitCode=await proc.exited;if(stdout=await proc.stdout.text(),stderr=await proc.stderr.text(),exitCode!==0)return log(`[swarm] preProvisionCollisionCheck: git worktree list failed (exit ${exitCode}): ${stderr}`),{collision:!1}}finally{try{proc.kill()}catch{}}let entries=[],current={path:"",branch:void 0};for(let rawLine of stdout.split(`
|
|
307
|
+
`)){let line=rawLine.trim();if(line.startsWith("worktree ")){if(current.path)entries.push(current);current={path:line.slice(9),branch:void 0}}else if(line.startsWith("branch "))current.branch=line.slice(7)}if(current.path)entries.push(current);for(let entry of entries){if(!entry.branch)continue;let branchName=entry.branch.startsWith("refs/heads/")?entry.branch.slice(11):entry.branch,segments=branchName.split("/");if(segments.length>=4&&segments[0]==="swarm"&&segments[1]==="lane"){if(segments[3]===taskId){let ownerSessionId=segments[2];return{collision:!0,existingBranch:branchName,ownerSessionId,worktreePath:entry.path}}}if(segments.length>=3&&segments[0]==="swarm-lane"){if(segments[2]===taskId){let ownerSessionId=segments[1];return{collision:!0,existingBranch:branchName,ownerSessionId,worktreePath:entry.path}}}}return{collision:!1}}function isLaneOwnedByCurrentSession(branchName,expectedSessionId){return _internals18.extractSessionId(branchName)===expectedSessionId}async function precreateStandardWorktreeSession(args2){let worktreeConfig=resolveWorktreeIsolationConfig(args2.config);if(worktreeConfig.policy==="disabled")return;if(standardWorktreeSerializationSessions.has(args2.parentSessionID)){if(checkStandardWorktreeSerializationRelease(args2.parentSessionID,worktreeConfig),!standardWorktreeSerializationSessions.has(args2.parentSessionID))return}if(!hasStandardWorktreeDispatchCapacity()){if(worktreeConfig.policy==="required")throw Error("STANDARD_WORKTREE_TRACKING_CAP_EXCEEDED: too many standard worktree coder dispatches are already awaiting merge-back.");serializeStandardWorktreeDispatches(args2.parentSessionID,"STANDARD_WORKTREE_TRACKING_CAP_EXCEEDED: too many standard worktree coder dispatches are already awaiting merge-back.");return}let client=swarmState.opencodeClient;if(!client){handleStandardWorktreeFailure(args2.parentSessionID,worktreeConfig.policy,"STANDARD_WORKTREE_ISOLATION_UNAVAILABLE: OpenCode SDK client is unavailable; standard parallel coder work cannot be isolated.");return}try{await _internals19.startupOrphanRecovery(args2.directory,[args2.parentSessionID])}catch(recoveryError){log(`[swarm] startup orphan recovery failed: ${recoveryError}`)}try{await _internals19.cleanupOrphanedBranches(args2.directory,[args2.parentSessionID])}catch(cleanupError){log(`[swarm] orphaned branch cleanup failed: ${cleanupError}`)}let collision=await preProvisionCollisionCheck(args2.taskId,args2.directory,args2.parentSessionID);if(collision.collision)if(collision.existingBranch?isLaneOwnedByCurrentSession(collision.existingBranch,args2.parentSessionID):!1){let session=ensureAgentSession(args2.parentSessionID);session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(`FR-001b PREPROVISION: stale lane detected for task ${args2.taskId} (session ${args2.parentSessionID}); cleaning up before re-provisioning.`);try{let callID=null;for(let[id,dispatch]of _internals19.standardWorktreeByCallID)if(dispatch.handle.branchName===collision.existingBranch){callID=id;break}if(!callID){for(let[id,record2]of _internals19.awaitingMergeByCallID)if(record2.branch===collision.existingBranch){callID=id;break}}if(callID)await _internals19.cleanupStandardWorktreeForCallId(callID,"denied",args2.directory,worktreeConfig.worktree_dir);else{if(collision.worktreePath){let preserveResult=await _internals19.preserveDirtyWorktreeAtPath(collision.worktreePath,collision.existingBranch,"denied",args2.directory,worktreeConfig.worktree_dir);if(preserveResult.outcome==="preserve-failed"){let session2=ensureAgentSession(args2.parentSessionID);session2.pendingAdvisoryMessages??=[],session2.pendingAdvisoryMessages.push(`STANDARD_WORKTREE_PRESERVATION_FAILED_ABORT_CLEANUP: pre-provision collision for task ${args2.taskId} has dirty uncommitted work but preservation failed (${preserveResult.error}). Cleanup aborted to protect uncommitted work. Worktree=${collision.worktreePath}; branch=${collision.existingBranch}.`);return}await _internals19.removeWorktree(collision.worktreePath,args2.directory,{force:!0,worktreeDir:worktreeConfig.worktree_dir})}await _internals19.postMergeCleanup(args2.directory,collision.existingBranch)}}catch(cleanupError){log(`[swarm] preProvision collision cleanup failed: ${cleanupError}; proceeding with provisioning anyway`)}}else{let ownerInfo=collision.ownerSessionId?` (owned by session ${collision.ownerSessionId})`:"",message=`FR-001b PREPROVISION_COLLISION: task ${args2.taskId} already has an active lane on branch ${collision.existingBranch}${ownerInfo}. Waiting for the owning session to complete and merge before retrying.`,session=ensureAgentSession(args2.parentSessionID);session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(message),handleStandardWorktreeFailure(args2.parentSessionID,worktreeConfig.policy,`PREPROVISION_COLLISION: ${message}`);return}let laneIndex=allocateStandardLaneIndex(args2.parentSessionID),provisionResult=await _internals19.provisionWorktree(args2.directory,args2.taskId,args2.parentSessionID,{purpose:"lane",worktreeDir:worktreeConfig.worktree_dir,mergeStrategy:worktreeConfig.merge_strategy,depsStrategy:worktreeConfig.deps_strategy,scope:args2.scope});if("error"in provisionResult){let message=`STANDARD_WORKTREE_PROVISION_FAILED: ${provisionResult.error}.`;handleStandardWorktreeFailure(args2.parentSessionID,worktreeConfig.policy,message);return}let laneProfile=computeLaneRuntimeProfile(worktreeConfig.runtime_isolation,laneIndex,provisionResult.worktreePath);if(laneProfile)try{let{writeLaneProfileToDiskReal:writeLaneProfileToDiskReal2}=await Promise.resolve().then(() => (init_core3(),exports_core3));await writeLaneProfileToDiskReal2(provisionResult.worktreePath,laneProfile.laneIndex,laneProfile.envOverrides)}catch{}if((worktreeConfig.deps_strategy??"skip")==="skip"){let desc=(args2.description??args2.taskId??"").toLowerCase();if(desc.includes("test")||desc.includes("build")||desc.includes("lint")||desc.includes("check")){let session=ensureAgentSession(args2.parentSessionID);session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(`WORKTREE_DEPS_SKIP: task ${args2.taskId} was provisioned with deps_strategy: 'skip' (default). This task's gates appear to include test/build commands; the lane may lack node_modules. Set worktree.deps_strategy to 'copy' or 'link' (or use a non-worktree lane) if the task requires host dependencies.`)}}let createResult=await client.session.create({body:{parentID:args2.parentSessionID,title:`${args2.description??args2.taskId} (worktree lane)`},query:{directory:provisionResult.worktreePath}});if(!createResult.data?.id){await _internals19.removeWorktree(provisionResult.worktreePath,args2.directory,{force:!0,worktreeDir:worktreeConfig.worktree_dir}).catch(()=>{});let createError=createResult.error,message=`STANDARD_WORKTREE_SESSION_CREATE_FAILED: ${typeof createError==="string"?createError:JSON.stringify(createError??"missing session id")}.`;handleStandardWorktreeFailure(args2.parentSessionID,worktreeConfig.policy,message);return}args2.outputArgs.task_id=createResult.data.id,rememberStandardWorktreeDispatch({callID:args2.callID,parentSessionID:args2.parentSessionID,taskId:args2.taskId,planTaskId:args2.planTaskId,handle:provisionResult,mergeStrategy:worktreeConfig.merge_strategy,laneIndex,worktree_dir:worktreeConfig.worktree_dir})}async function preserveDirtyWorktreeForCallId(callID,reason,_directory,_worktree_dir){let dispatch=standardWorktreeByCallID.get(callID),worktreePath,parentSessionID;if(dispatch)worktreePath=dispatch.handle.worktreePath,parentSessionID=dispatch.parentSessionID;else{let awaiting=awaitingMergeByCallID.get(callID);if(!awaiting)return{outcome:"clean",preserved:!1};worktreePath=awaiting.worktreePath,parentSessionID=awaiting.parentSessionID}let statusProc=_internals19.bunSpawn(["git","-C",worktreePath,"status","--porcelain"],{stdin:"ignore",stdout:"pipe",stderr:"pipe",timeout:PRESERVE_COMMIT_TIMEOUT_MS}),statusStdout="",statusStderr="";try{let exitCode=await statusProc.exited;if(statusStdout=await statusProc.stdout.text(),statusStderr=await statusProc.stderr.text(),exitCode!==0)return log(`[swarm] preserveDirtyWorktreeForCallId: git status failed for ${callID}: ${statusStderr}`),{outcome:"preserve-failed",preserved:!1,error:`git status failed: ${statusStderr||`exit ${exitCode}`}`}}finally{try{statusProc.kill()}catch{}}if(statusStdout.trim()==="")return{outcome:"clean",preserved:!1};let addProc=_internals19.bunSpawn(["git","-C",worktreePath,"add","-A"],{stdin:"ignore",stdout:"pipe",stderr:"pipe",timeout:PRESERVE_COMMIT_TIMEOUT_MS});try{let addExit=await addProc.exited;if(addExit!==0){let addErr=await addProc.stderr.text();return log(`[swarm] preserveDirtyWorktreeForCallId: git add failed for ${callID}: ${addErr}`),{outcome:"preserve-failed",preserved:!1,error:`git add failed: ${addErr||`exit ${addExit}`}`}}}finally{try{addProc.kill()}catch{}}let isoDate=new Date().toISOString(),sanitizedCallID=callID.replace(/[^A-Za-z0-9._-]/g,"-").slice(0,64),commitMessage=`swarm-preserved: ${reason} for callID ${sanitizedCallID} at ${isoDate}`,commitProc=_internals19.bunSpawn(["git","-C",worktreePath,"commit","-m",commitMessage],{stdin:"ignore",stdout:"pipe",stderr:"pipe",timeout:PRESERVE_COMMIT_TIMEOUT_MS}),commitHash="";try{let commitExit=await commitProc.exited;if(commitExit!==0){let commitErr=await commitProc.stderr.text();return log(`[swarm] preserveDirtyWorktreeForCallId: git commit failed for ${callID}: ${commitErr}`),{outcome:"preserve-failed",preserved:!1,error:`git commit failed: ${commitErr||`exit ${commitExit}`}`}}}finally{try{commitProc.kill()}catch{}}let hashProc=_internals19.bunSpawn(["git","-C",worktreePath,"rev-parse","HEAD"],{stdin:"ignore",stdout:"pipe",stderr:"pipe",timeout:PRESERVE_COMMIT_TIMEOUT_MS});try{let hashExit=await hashProc.exited;if(hashExit!==0){let hashErr=await hashProc.stderr.text();return log(`[swarm] preserveDirtyWorktreeForCallId: git rev-parse failed for ${callID}: ${hashErr}`),{outcome:"preserve-failed",preserved:!1,error:`git rev-parse failed: ${hashErr||`exit ${hashExit}`}`}}commitHash=(await hashProc.stdout.text()).trim()}finally{try{hashProc.kill()}catch{}}if(!commitHash)return{outcome:"preserve-failed",preserved:!1,error:"git rev-parse returned empty hash"};let shortHash=commitHash.slice(0,8),tagName=`swarm-preserved-${sanitizedCallID}-${shortHash}`,tagProc=_internals19.bunSpawn(["git","-C",worktreePath,"tag",tagName],{stdin:"ignore",stdout:"pipe",stderr:"pipe",timeout:PRESERVE_COMMIT_TIMEOUT_MS});try{let tagExit=await tagProc.exited;if(tagExit!==0){let tagErr=await tagProc.stderr.text();return log(`[swarm] preserveDirtyWorktreeForCallId: git tag failed for ${callID}: ${tagErr}`),{outcome:"preserve-failed",preserved:!1,error:`git tag failed: ${tagErr||`exit ${tagExit}`}`}}}finally{try{tagProc.kill()}catch{}}let session=ensureAgentSession(parentSessionID);return session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(`STANDARD_WORKTREE_PRESERVED: dispatch ${callID} dirty work preserved as commit ${commitHash} (tag: ${tagName}; reason: ${reason}); worktree will be cleaned.`),{outcome:"preserved",preserved:!0,ref:commitHash}}async function preserveDirtyWorktreeAtPath(worktreePath,branchName,reason,_directory,_worktree_dir){let statusProc=_internals19.bunSpawn(["git","-C",worktreePath,"status","--porcelain"],{stdin:"ignore",stdout:"pipe",stderr:"pipe",timeout:PRESERVE_COMMIT_TIMEOUT_MS}),statusStdout="",statusStderr="";try{let exitCode=await statusProc.exited;if(statusStdout=await statusProc.stdout.text(),statusStderr=await statusProc.stderr.text(),exitCode!==0)return log(`[swarm] preserveDirtyWorktreeAtPath: git status failed for ${worktreePath}: ${statusStderr}`),{outcome:"preserve-failed",preserved:!1,error:`git status failed: ${statusStderr||`exit ${exitCode}`}`}}finally{try{statusProc.kill()}catch{}}if(statusStdout.trim()==="")return{outcome:"clean",preserved:!1};let addProc=_internals19.bunSpawn(["git","-C",worktreePath,"add","-A"],{stdin:"ignore",stdout:"pipe",stderr:"pipe",timeout:PRESERVE_COMMIT_TIMEOUT_MS});try{let addExit=await addProc.exited;if(addExit!==0){let addErr=await addProc.stderr.text();return log(`[swarm] preserveDirtyWorktreeAtPath: git add failed for ${worktreePath}: ${addErr}`),{outcome:"preserve-failed",preserved:!1,error:`git add failed: ${addErr||`exit ${addExit}`}`}}}finally{try{addProc.kill()}catch{}}let isoDate=new Date().toISOString(),sanitizedPath=worktreePath.replace(/[^A-Za-z0-9._-]/g,"-").slice(0,64),sanitizedBranch=branchName.replace(/[^A-Za-z0-9._-]/g,"-").slice(0,64),commitMessage=`swarm-preserved: ${reason} for worktree ${sanitizedPath} at ${isoDate}`,commitProc=_internals19.bunSpawn(["git","-C",worktreePath,"commit","-m",commitMessage],{stdin:"ignore",stdout:"pipe",stderr:"pipe",timeout:PRESERVE_COMMIT_TIMEOUT_MS}),commitHash="";try{let commitExit=await commitProc.exited;if(commitExit!==0){let commitErr=await commitProc.stderr.text();return log(`[swarm] preserveDirtyWorktreeAtPath: git commit failed for ${worktreePath}: ${commitErr}`),{outcome:"preserve-failed",preserved:!1,error:`git commit failed: ${commitErr||`exit ${commitExit}`}`}}}finally{try{commitProc.kill()}catch{}}let hashProc=_internals19.bunSpawn(["git","-C",worktreePath,"rev-parse","HEAD"],{stdin:"ignore",stdout:"pipe",stderr:"pipe",timeout:PRESERVE_COMMIT_TIMEOUT_MS});try{let hashExit=await hashProc.exited;if(hashExit!==0){let hashErr=await hashProc.stderr.text();return log(`[swarm] preserveDirtyWorktreeAtPath: git rev-parse failed for ${worktreePath}: ${hashErr}`),{outcome:"preserve-failed",preserved:!1,error:`git rev-parse failed: ${hashErr||`exit ${hashExit}`}`}}commitHash=(await hashProc.stdout.text()).trim()}finally{try{hashProc.kill()}catch{}}if(!commitHash)return{outcome:"preserve-failed",preserved:!1,error:"git rev-parse returned empty hash"};let shortHash=commitHash.slice(0,8),tagName=`swarm-preserved-worktree-${sanitizedBranch}-${shortHash}`,tagProc=_internals19.bunSpawn(["git","-C",worktreePath,"tag",tagName],{stdin:"ignore",stdout:"pipe",stderr:"pipe",timeout:PRESERVE_COMMIT_TIMEOUT_MS});try{let tagExit=await tagProc.exited;if(tagExit!==0){let tagErr=await tagProc.stderr.text();return log(`[swarm] preserveDirtyWorktreeAtPath: git tag failed for ${worktreePath}: ${tagErr}`),{outcome:"preserve-failed",preserved:!1,error:`git tag failed: ${tagErr||`exit ${tagExit}`}`}}}finally{try{tagProc.kill()}catch{}}return{outcome:"preserved",preserved:!0,ref:commitHash}}async function cleanupStandardWorktreeForCallId(callID,reason,directory,worktree_dir){let dispatch=standardWorktreeByCallID.get(callID),worktreePath,branchName,parentSessionID;if(dispatch)worktreePath=dispatch.handle.worktreePath,branchName=dispatch.handle.branchName,parentSessionID=dispatch.parentSessionID;else{let awaiting=awaitingMergeByCallID.get(callID);if(!awaiting)return;worktreePath=awaiting.worktreePath,branchName=awaiting.branch,parentSessionID=awaiting.parentSessionID}let preserveResult;if(reason==="denied"||reason==="cancelled"){try{preserveResult=await _internals19.preserveDirtyWorktreeForCallId(callID,reason,directory,worktree_dir)}catch(err){log(`[swarm] cleanupStandardWorktreeForCallId: preserveDirtyWorktreeForCallId threw for ${callID}: ${err}`),preserveResult={outcome:"preserve-failed",preserved:!1,error:String(err)}}if(preserveResult.outcome==="clean")try{preserveResult=await _internals19.preserveDirtyWorktreeForCallId(callID,reason,directory,worktree_dir)}catch(err){log(`[swarm] cleanupStandardWorktreeForCallId: final preservation check threw for ${callID}: ${err}`),preserveResult={outcome:"preserve-failed",preserved:!1,error:String(err)}}}if(preserveResult&&preserveResult.outcome==="preserve-failed"){standardWorktreeByCallID.delete(callID),awaitingMergeByCallID.delete(callID);let session2=ensureAgentSession(parentSessionID);session2.pendingAdvisoryMessages??=[],session2.pendingAdvisoryMessages.push(`STANDARD_WORKTREE_PRESERVATION_FAILED_ABORT_CLEANUP: dispatch ${callID} has dirty uncommitted work but preservation failed (${preserveResult.error}). Cleanup aborted to protect uncommitted work. Investigate and resolve manually. Worktree=${worktreePath}; branch=${branchName}.`);return}await _internals19.removeWorktree(worktreePath,directory,{force:!0,worktreeDir:worktree_dir}).catch((err)=>log(`[swarm] cleanupStandardWorktreeForCallId: removeWorktree failed for ${callID}: ${err}`)),await _internals19.postMergeCleanup(directory,branchName).catch((err)=>log(`[swarm] cleanupStandardWorktreeForCallId: postMergeCleanup failed for ${callID}: ${err}`)),standardWorktreeByCallID.delete(callID),awaitingMergeByCallID.delete(callID);let session=ensureAgentSession(parentSessionID);session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(`STANDARD_WORKTREE_CLEANUP: dispatch ${callID} cleaned up (reason: ${reason}); worktree=${worktreePath}; branch=${branchName}.`)}async function abortStandardWorktreeDispatch(callID,reason,directory){let dispatch=standardWorktreeByCallID.get(callID);if(!dispatch){let session=ensureAgentSession("unknown");session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(`STANDARD_WORKTREE_ABORT_NOOP: dispatch ${callID} has no tracked worktree to abort (reason: ${reason}).`);return}await cleanupStandardWorktreeForCallId(callID,reason,directory,dispatch.worktree_dir)}async function finishStandardWorktreeDispatch(directory,dispatch,config2,callID){let wtConfig=config2?resolveWorktreeIsolationConfig(config2):DEFAULT_WORKTREE_ISOLATION_CONFIG,resolvedCallID=callID??dispatch.callID,run=async()=>{let mergeResult=await _internals19.attemptMergeBackFromDirty(dispatch.handle.worktreePath,dispatch.handle.branchName,directory,getMergeStrategy({merge_strategy:dispatch.mergeStrategy})),statusKey=dispatch.planTaskId??dispatch.taskId;if("merged"in mergeResult&&mergeResult.merged){clearWorktreeMergeStatus(statusKey);try{let{removeLaneProfileFromDiskReal:removeLaneProfileFromDiskReal2}=await Promise.resolve().then(() => (init_core3(),exports_core3));await removeLaneProfileFromDiskReal2(dispatch.handle.worktreePath,dispatch.laneIndex)}catch{}let state=serializationStateBySessionID.get(dispatch.parentSessionID);if(state)state.successfulDispatchesSince++,checkStandardWorktreeSerializationRelease(dispatch.parentSessionID,wtConfig);await cleanupStandardWorktreeForCallId(resolvedCallID,"success",directory,dispatch.worktree_dir);return}if("partial"in mergeResult){recordWorktreeMergeFailure(statusKey,{outcome:"partial",stage:mergeResult.stage,message:mergeResult.message,worktreePath:dispatch.handle.worktreePath,branch:dispatch.handle.branchName,completedAt:Date.now()});let session=ensureAgentSession(dispatch.parentSessionID);session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(`STANDARD_WORKTREE_MERGE_PARTIAL: task ${dispatch.taskId} preserved at ${dispatch.handle.worktreePath}; stage: ${mergeResult.stage}; ${mergeResult.message}`);return}if("failed"in mergeResult){recordWorktreeMergeFailure(statusKey,{outcome:"failed",stage:mergeResult.stage,message:mergeResult.message,worktreePath:dispatch.handle.worktreePath,branch:dispatch.handle.branchName,completedAt:Date.now()});let session=ensureAgentSession(dispatch.parentSessionID);session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(`STANDARD_WORKTREE_MERGE_FAILED: task ${dispatch.taskId} preserved at ${dispatch.handle.worktreePath}; stage: ${mergeResult.stage}; ${mergeResult.message}.`)}};if(standardWorktreeMergeQueue=standardWorktreeMergeQueue.then(run,run),await standardWorktreeMergeQueue,resolvedCallID)awaitingMergeByCallID.delete(resolvedCallID)}async function readLaneEnvFileFromDisk(worktreePath,laneIndex){let envPath=path25.join(worktreePath,".swarm","lanes",`${laneIndex}.env`),content;try{content=await fs16.readFile(envPath,"utf-8")}catch(err){if(err.code==="ENOENT")return{};return log(`[worktree-isolation] failed to read lane env file ${envPath}: ${err.message}`),{}}let result={};for(let rawLine of content.split(`
|
|
308
|
+
`)){let line=rawLine.trim();if(!line||line.startsWith("#"))continue;let eqIdx=line.indexOf("=");if(eqIdx<0)continue;let k=line.slice(0,eqIdx),v=line.slice(eqIdx+1);if(!isValidEnvKey(k))continue;result[k]=v}return result}var MAX_TRACKED_STANDARD_WORKTREE_CALLS=256,awaitingMergeByCallID,standardWorktreeByCallID,standardWorktreeSerializationSessions,standardWorktreeMergeQueue,standardWorktreeLaneIndexBySession,serializationStateBySessionID,WORKTREE_LIST_TIMEOUT_MS=15000,PRESERVE_COMMIT_TIMEOUT_MS=30000,_internals19;var init_worktree_isolation=__esm(()=>{init_constants();init_executor();init_state2();init_bun_compat();init_logger();init_worktree();init_worktree_merge_status();init_worktree_isolation_config();awaitingMergeByCallID=new Map,standardWorktreeByCallID=new Map,standardWorktreeSerializationSessions=new Set,standardWorktreeMergeQueue=Promise.resolve(),standardWorktreeLaneIndexBySession=new Map,serializationStateBySessionID=new Map;_internals19={provisionWorktree,removeWorktree,attemptMergeBackFromDirty,postMergeCleanup,readLaneEnvFileFromDisk,serializationStateBySessionID,rememberStandardWorktreeSerializationSession,awaitingMergeByCallID,startupOrphanRecovery,cleanupOrphanedBranches,cleanupStandardWorktreeForCallId,preserveDirtyWorktreeForCallId,preserveDirtyWorktreeAtPath,abortStandardWorktreeDispatch,standardWorktreeByCallID,preProvisionCollisionCheck,isLaneOwnedByCurrentSession,bunSpawn}});function resolveMemoryConfig(input){return{...DEFAULT_MEMORY_CONFIG,...input??{},sqlite:{...DEFAULT_MEMORY_CONFIG.sqlite,...input?.sqlite??{}},recall:{...DEFAULT_MEMORY_CONFIG.recall,...input?.recall??{},injection:{...DEFAULT_MEMORY_CONFIG.recall.injection,...input?.recall?.injection??{}}},learning:{...DEFAULT_MEMORY_CONFIG.learning,...input?.learning??{}},writes:{...DEFAULT_MEMORY_CONFIG.writes,...input?.writes??{}},redaction:{...DEFAULT_MEMORY_CONFIG.redaction,...input?.redaction??{}},maintenance:{...DEFAULT_MEMORY_CONFIG.maintenance,...input?.maintenance??{},importance:{...DEFAULT_MEMORY_CONFIG.maintenance.importance,...input?.maintenance?.importance??{}}},consolidation:{...DEFAULT_MEMORY_CONFIG.consolidation,...input?.consolidation??{},decayHalfLifeDays:{...DEFAULT_MEMORY_CONFIG.consolidation.decayHalfLifeDays,...input?.consolidation?.decayHalfLifeDays??{}}},embeddings:{...DEFAULT_MEMORY_CONFIG.embeddings,...input?.embeddings??{}},retrieval:{...DEFAULT_MEMORY_CONFIG.retrieval,...input?.retrieval??{},weights:{...DEFAULT_MEMORY_CONFIG.retrieval.weights,...input?.retrieval?.weights??{}},rerank:{...DEFAULT_MEMORY_CONFIG.retrieval.rerank,...input?.retrieval?.rerank??{}}},qLearning:{...DEFAULT_MEMORY_CONFIG.qLearning,...input?.qLearning??{}}}}var DEFAULT_DECAY_HALF_LIFE_DAYS,DEFAULT_IMPORTANCE_CONFIG,DEFAULT_QLEARNING_CONFIG,COUNCIL_VERDICT_REWARDS,DEFAULT_CONSOLIDATION_CONFIG,DEFAULT_MEMORY_LEARNING_CONFIG,DEFAULT_EMBEDDINGS_CONFIG,DEFAULT_RETRIEVAL_CONFIG,DEFAULT_MEMORY_CONFIG,DURABLE_MEMORY_KINDS,EVIDENCE_REQUIRED_KINDS;var init_config2=__esm(()=>{DEFAULT_DECAY_HALF_LIFE_DAYS={scratch:7,todo:30,code_pattern:90,test_pattern:90,failure_pattern:90,api_finding:180,evidence:180,architecture_decision:0,repo_convention:0,project_fact:0,security_note:0,user_preference:0},DEFAULT_IMPORTANCE_CONFIG={wRecency:0.2,wFrequency:0.2,wFreshness:0.15,wConfidence:0.25,lambda:0.05,mu:0.01,n:50,threshold:0.2},DEFAULT_QLEARNING_CONFIG={learningRate:0.1,qValueBoostWeight:0.1,suppressionThreshold:0.15,promotionThreshold:0.85,promotionMinRetrievals:5,propagationFraction:0.3,propagationFanoutCap:20,propagationWindowDays:30,propagationRelatednessThreshold:0.7,explorationRate:0.05,verdictPayloadCapBytes:8192,initialQValue:0.5},COUNCIL_VERDICT_REWARDS={APPROVE:1,CONCERNS:0.5,REJECT:0},DEFAULT_CONSOLIDATION_CONFIG={enabled:!1,maxClustersPerPass:10,jaccardThreshold:0.3,autoApplyMinConfidence:0.6,decayHalfLifeDays:{...DEFAULT_DECAY_HALF_LIFE_DAYS}},DEFAULT_MEMORY_LEARNING_CONFIG={learningRate:0.1,propagationFactor:0.3,qValueBoostWeight:0.1,suppressionThreshold:0.15,promotionThreshold:0.85,propagationTokenOverlapThreshold:0.4,propagationEmbeddingCosineThreshold:0.7,propagationFanout:20,propagationLookbackDays:30},DEFAULT_EMBEDDINGS_CONFIG={enabled:!1,model:"Xenova/all-MiniLM-L6-v2",dimension:384,cacheSize:256},DEFAULT_RETRIEVAL_CONFIG={rrfK:60,weights:{lexical:0.5,dense:0.4,metadata:0.1},rerank:{enabled:!1},latencyBudgetMs:250},DEFAULT_MEMORY_CONFIG={enabled:!1,provider:"sqlite",storageDir:".swarm/memory",sqlite:{path:".swarm/memory/memory.db",busyTimeoutMs:5000},recall:{defaultMaxItems:8,defaultTokenBudget:1200,minScore:0.05,injection:{enabled:!0,minScore:0.25,requireQuerySignal:!0,maxItems:6,tokenBudget:1000}},learning:{...DEFAULT_MEMORY_LEARNING_CONFIG},writes:{mode:"propose"},redaction:{rejectDurableSecrets:!0},maintenance:{lowUtilityMaxConfidence:0.45,lowUtilityMinAgeDays:30,autoCompactEveryNRecalls:50,importance:{...DEFAULT_IMPORTANCE_CONFIG}},consolidation:{...DEFAULT_CONSOLIDATION_CONFIG,decayHalfLifeDays:{...DEFAULT_DECAY_HALF_LIFE_DAYS}},embeddings:{...DEFAULT_EMBEDDINGS_CONFIG},retrieval:{...DEFAULT_RETRIEVAL_CONFIG},qLearning:{...DEFAULT_QLEARNING_CONFIG},hardDelete:!1},DURABLE_MEMORY_KINDS=new Set(["user_preference","project_fact","architecture_decision","repo_convention","code_pattern","test_pattern","failure_pattern","security_note"]),EVIDENCE_REQUIRED_KINDS=new Set(["api_finding","evidence","security_note"])});var MemoryValidationError,MemoryDisabledError;var init_errors4=__esm(()=>{MemoryValidationError=class MemoryValidationError extends Error{code;constructor(message,code="memory_validation_error"){super(message);this.name="MemoryValidationError",this.code=code}};MemoryDisabledError=class MemoryDisabledError extends Error{constructor(message="Swarm memory is disabled"){super(message);this.name="MemoryDisabledError"}}});function findSecrets(text){let findings=[];for(let{type,pattern}of SECRET_PATTERNS){pattern.lastIndex=0;for(let match of text.matchAll(pattern))if(match[0])findings.push({type,match:match[0]})}return findings}function containsSecret(text){return findSecrets(text).length>0}function redactSecrets(text){let redacted=text;for(let{type,pattern}of SECRET_PATTERNS)pattern.lastIndex=0,redacted=redacted.replace(pattern,`[REDACTED:${type}]`);return redacted}var SECRET_PATTERNS;var init_redaction=__esm(()=>{SECRET_PATTERNS=[{type:"openai_api_key",pattern:/\bsk-[A-Za-z0-9_-]{20,}\b/g},{type:"github_token",pattern:/\b(?:ghp|gho|ghu|ghs|ghr|github_pat)_[A-Za-z0-9_]{20,}\b/g},{type:"aws_access_key_id",pattern:/\bAKIA[0-9A-Z]{16}\b/g},{type:"private_key_block",pattern:/-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g},{type:"authorization_bearer",pattern:/\bAuthorization\s*:\s*Bearer\s+[A-Za-z0-9._~+/=-]{12,}/gi},{type:"env_secret",pattern:/\b(?:[A-Z][A-Z0-9]+_)+(?:KEY|TOKEN|SECRET|PASSWORD)\b\s*=\s*["']?[^\s"'`]{8,}["']?/gi},{type:"gitlab_token",pattern:/\bgl(?:pat|ptt)-[A-Za-z0-9_-]{15,}\b/g},{type:"slack_token",pattern:/\bxox[abprs]-[A-Za-z0-9-]{10,}\b/g},{type:"jwt_token",pattern:/\beyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g},{type:"aws_secret_access_key",pattern:/\b(?:aws_secret_access_key|AWS_SECRET_ACCESS_KEY)\s*[=:]\s*[A-Za-z0-9/+=]{40}\b/g},{type:"stripe_secret_key",pattern:/\b(?:sk|rk)_(?:live|test)_[A-Za-z0-9]{24,}\b/g},{type:"google_api_key",pattern:/\bAIza[0-9A-Za-z_-]{35}\b/g},{type:"openssh_private_key_block",pattern:/-----BEGIN[ ]OPENSSH[ ]PRIVATE[ ]KEY-----[\s\S]*?-----END[ ]OPENSSH[ ]PRIVATE[ ]KEY-----/g}]});var MEMORY_RECALL_SENTINEL="## Retrieved Swarm Memory";import{createHash as createHash7}from"node:crypto";function normalizeMemoryText(text){return text.replace(/\s+/g," ").trim()}function stableScopeKey(scope){let ordered={type:scope.type},keys=scope.type==="repository"?["repoId"]:["userId","workspaceId","projectId","repoId","repoRoot","runId","agentId"];for(let key of keys){let value=scope[key];if(value)ordered[key]=value}return JSON.stringify(ordered)}function computeMemoryContentHash(recordLike){let normalized=normalizeMemoryText(recordLike.text).toLowerCase();return createHash7("sha256").update(`${stableScopeKey(recordLike.scope)}
|
|
309
309
|
${recordLike.kind}
|
|
310
310
|
${normalized}`).digest("hex")}function createMemoryId(recordLike){return`mem_${computeMemoryContentHash(recordLike).slice(0,16)}`}function createProposalId(input){return`prop_${createHash7("sha256").update(`${input.createdAt}
|
|
311
311
|
${input.proposer}
|
|
@@ -639,13 +639,13 @@ ${trimComment}${after}`}}}let sessionID=lastUserMessage.info?.sessionID,planTask
|
|
|
639
639
|
${parallelGuidance??"[NEXT] Execute the next gate for the current task."}`}else guidance=parallelGuidance??"[NEXT] Begin the first plan task and run gates sequentially.";let systemMsgIdx=messages.findIndex((m)=>m&&m.info?.role==="system"),insertIdx=systemMsgIdx>=0?systemMsgIdx+1:0,guidanceMessage={info:{role:"system"},parts:[{type:"text",text:guidance}]};messages.splice(insertIdx,0,guidanceMessage)}}let warnings=[];if(text.length>delegationMaxChars)warnings.push(`Delegation exceeds recommended size (${text.length} chars, limit ${delegationMaxChars}). Consider splitting into smaller tasks.`);if(isCoderDelegation){let fileMatches=text.match(/^FILE:/gm);if(fileMatches&&fileMatches.length>1)warnings.push(`Multiple FILE: directives detected (${fileMatches.length}). Each coder task should target ONE file.`)}if(isCoderDelegation){let taskMatches=text.match(/^TASK:/gm);if(taskMatches&&taskMatches.length>1)warnings.push(`Multiple TASK: sections detected (${taskMatches.length}). Send ONE task per coder call.`)}if(isCoderDelegation){let batchingPattern=/\b(?:and also|then also|additionally|as well as|along with|while you'?re at it)[.,]?\b/gi,batchingMatches=text.match(batchingPattern);if(batchingMatches&&batchingMatches.length>0)warnings.push(`Batching language detected (${batchingMatches.join(", ")}). Break compound objectives into separate coder calls.`)}if(isCoderDelegation){let taskLine=extractTaskLine(text);if(taskLine){if(/\s+and\s+(update|add|remove|modify|refactor|implement|create|delete|fix|change|build|deploy|write|test|move|rename|extend|extract|convert|migrate|upgrade|replace)\b/i.test(taskLine))warnings.push('TASK line contains "and" connecting separate actions')}}if(isCoderDelegation&&sessionID){let delegationChain=swarmState.delegationChains.get(sessionID);if(delegationChain&&delegationChain.length>=2){let coderIndices=[];for(let i=delegationChain.length-1;i>=0;i--)if(stripKnownSwarmPrefix(delegationChain[i].to).includes("coder")){if(coderIndices.unshift(i),coderIndices.length===2)break}if(coderIndices.length===2){let prevCoderIndex=coderIndices[0],betweenCoders=delegationChain.slice(prevCoderIndex+1),hasReviewer=betweenCoders.some((d)=>stripKnownSwarmPrefix(d.to)==="reviewer"),hasTestEngineer=betweenCoders.some((d)=>stripKnownSwarmPrefix(d.to)==="test_engineer"),session=ensureAgentSession(sessionID),priorTaskStuckAtCoder=priorCoderTaskId!==null&&getTaskState(session,priorCoderTaskId)==="coder_delegated";if(!hasReviewer||!hasTestEngineer||priorTaskStuckAtCoder){if(session.qaSkipCount>=1){telemetry.qaSkipViolation(_input.sessionID,session.agentName,session.qaSkipCount+1);let skippedTasks=session.qaSkipTaskIds.join(", ");throw Error(`\uD83D\uDED1 QA GATE ENFORCEMENT: ${session.qaSkipCount+1} consecutive coder delegations without reviewer/test_engineer. Skipped tasks: [${skippedTasks}]. DELEGATE to reviewer and test_engineer NOW before any further coder work.`)}session.qaSkipCount++,session.qaSkipTaskIds.push(currentTaskId??"unknown"),warnings.push("⚠️ PROTOCOL VIOLATION: Previous coder task completed, but QA gate was skipped. "+"You MUST delegate to reviewer (code review) and test_engineer (test execution) before starting a new coder task. Review RULES 7-8 in your system prompt.")}}}}if(warnings.length===0)return;let warningText=`⚠️ BATCH DETECTED: Your coder delegation appears to contain multiple tasks.
|
|
640
640
|
Rule 3: ONE task per coder call. Split this into separate delegations.
|
|
641
641
|
${warnings.map((w)=>`Detected signal: ${w}`).join(`
|
|
642
|
-
`)}`,batchWarnSystemIdx=messages.findIndex((m)=>m&&m.info?.role==="system"),batchWarnInsertIdx=batchWarnSystemIdx>=0?batchWarnSystemIdx+1:0,batchWarnMessage={info:{role:"system"},parts:[{type:"text",text:warningText}]};messages.splice(batchWarnInsertIdx,0,batchWarnMessage)},toolAfter:async(input,_output)=>{if(!input.sessionID)return;let session=swarmState.agentSessions.get(input.sessionID);if(!session)return;let normalized=normalizeToolName(input.tool),{qaGateSessionOverrides}=ensureAgentSession(input.sessionID),councilActive=await isCouncilGateActive(directory,config2.council,qaGateSessionOverrides??{});if(normalized==="update_task_status"){let directArgs=input.args,storedArgs=getStoredInputArgs(input.callID),completionArgs=directArgs??storedArgs;if(completionArgs&&completionArgs.status==="completed"){let rawTaskId=completionArgs.task_id??completionArgs.taskId,completionTaskId=typeof rawTaskId==="string"?rawTaskId.trim():null;if(completionTaskId&&isStrictTaskId(completionTaskId))try{let completionSession=ensureAgentSession(input.sessionID);await advanceTaskStateAndPersist(completionSession,completionTaskId,"complete",directory,{telemetrySessionId:input.sessionID},config2.council)}catch(err){warn(`[delegation-gate] toolAfter completion advancement: could not advance ${completionTaskId} → complete: ${err instanceof Error?err.message:String(err)}`)}}}if(normalized==="submit_council_verdicts"){try{let result=typeof _output==="string"?JSON.parse(_output):_output;if(result&&typeof result==="object"&&result.success===!0&&typeof result.overallVerdict==="string"){let directArgs=input.args,storedArgs=getStoredInputArgs(input.callID),taskIdRaw=directArgs?.taskId??storedArgs?.taskId,taskId=typeof taskIdRaw==="string"?taskIdRaw:null;if(taskId){if(!session.taskCouncilApproved)session.taskCouncilApproved=new Map;let priorRewarded=session.taskCouncilApproved.get(taskId)?.rewarded===!0;if(session.taskCouncilApproved.set(taskId,{verdict:result.overallVerdict,roundNumber:typeof result.roundNumber==="number"?result.roundNumber:1,quorumSize:typeof result.quorumSize==="number"?result.quorumSize:1,rewarded:priorRewarded}),councilActive&&result.overallVerdict==="APPROVE"&&result.allCriteriaMet===!0&&(result.requiredFixesCount??0)===0)try{await advanceTaskStateAndPersist(session,taskId,"complete",directory,{telemetrySessionId:input.sessionID},config2.council);try{let memoryConfig=config2.memory;if(getTaskState(session,taskId)==="complete"&&memoryConfig?.enabled===!0){let approvedEntry=session.taskCouncilApproved?.get(taskId);if(approvedEntry?.rewarded!==!0){let provider=createConfiguredMemoryProvider(directory,memoryConfig);try{let synthesis={overallVerdict:result.overallVerdict,allCriteriaMet:result.allCriteriaMet===!0,requiredFixesCount:result.requiredFixesCount??0,roundNumber:typeof result.roundNumber==="number"?result.roundNumber:void 0,quorumSize:typeof result.quorumSize==="number"?result.quorumSize:void 0},verdictSynthesisJson=JSON.stringify(synthesis),cap=memoryConfig.qLearning.verdictPayloadCapBytes;if(typeof cap==="number"&&cap>0&&verdictSynthesisJson.length>cap)verdictSynthesisJson=JSON.stringify(truncateObjectForJson(synthesis,cap));if(await applyCouncilReward(provider,{runId:input.sessionID,unitId:taskId,reward:COUNCIL_VERDICT_REWARDS.APPROVE,eta:memoryConfig.qLearning.learningRate,initialQValue:memoryConfig.qLearning.initialQValue,qLearning:memoryConfig.qLearning,verdictSynthesisJson,timestamp:new Date().toISOString()}),approvedEntry)approvedEntry.rewarded=!0}finally{await provider.close?.()}}}}catch(rewardErr){warn(`[delegation-gate] council reward capture failed: ${rewardErr instanceof Error?rewardErr.message:String(rewardErr)}`)}}catch(err){warn(`[delegation-gate] toolAfter submit_council_verdicts: could not advance ${taskId} → complete: ${err instanceof Error?err.message:String(err)}`)}}}}catch(err){console.warn(`[delegation-gate] toolAfter submit_council_verdicts: failed to parse output: ${err instanceof Error?err.message:String(err)}`)}return}if(normalized==="Task"||normalized==="task"){let standardDispatch=standardWorktreeByCallID.get(input.callID),directArgsRaw=input.args,directArgs=directArgsRaw?{...directArgsRaw}:void 0;if(standardDispatch&&directArgs)if(standardDispatch.planTaskId)directArgs.task_id=standardDispatch.planTaskId;else delete directArgs.task_id;let storedArgs=getStoredInputArgs(input.callID),subagentType=directArgs?.subagent_type??storedArgs?.subagent_type;if(typeof subagentType==="string"&&isKnownCanonicalRole(stripKnownSwarmPrefix(subagentType))&&(isBackgroundTrue(directArgs?.background)||isBackgroundTrue(storedArgs?.background)||outputLooksLikeBackgroundRunning(_output))){if(backgroundSubagentsEnabled)try{let{extractDispatchIds:extractDispatchIds2}=await Promise.resolve().then(() => (init_task_envelope(),exports_task_envelope)),{buildPromptSnapshot:buildPromptSnapshot2,recordPendingDelegation:recordPendingDelegation2}=await Promise.resolve().then(() => (init_pending_delegations(),exports_pending_delegations)),{captureWorkspaceSnapshot:captureWorkspaceSnapshot2}=await Promise.resolve().then(() => (init_workspace_snapshot(),exports_workspace_snapshot)),{subagentSessionId,jobId}=extractDispatchIds2(_output);if(subagentSessionId){let mergedArgs={...storedArgs??{},...directArgs},evidenceTaskId=await resolveEvidenceTaskId(mergedArgs,session,directory),scope=session.declaredCoderScope&&session.declaredCoderScope.length>0?session.declaredCoderScope.join(","):evidenceTaskId,prHeadShaRaw=mergedArgs.prHeadSha??mergedArgs.pr_head_sha,prHeadSha=typeof prHeadShaRaw==="string"?prHeadShaRaw:null,taskChangeContext=stripKnownSwarmPrefix(subagentType)==="coder"?coderTaskChangeContextByCallID.get(input.callID):void 0;await recordPendingDelegation2(directory,{correlationId:subagentSessionId,jobId,subagentSessionId,parentSessionId:input.sessionID,callID:input.callID,normalizedAgent:stripKnownSwarmPrefix(subagentType),swarmPrefixedAgent:subagentType,planTaskId:evidenceTaskId,evidenceTaskId,workspace:taskChangeContext?{...taskChangeContext.baseline,prHeadSha,scope}:captureWorkspaceSnapshot2(directory,{prHeadSha,scope}),taskChangeContext,prompt:typeof mergedArgs.prompt==="string"?buildPromptSnapshot2(mergedArgs.prompt,delegationMaxChars):void 0,generation:1},{staleTimeoutMs:backgroundPendingTimeoutMs})}else warn("[delegation-gate] background dispatch had no correlation id (no jobId / no envelope) — not tracked")}catch(err){warn(`[delegation-gate] background pending recording failed: ${err instanceof Error?err.message:String(err)}`)}if(clearCoderTaskChangeContext(input.callID),storedArgs!==void 0)deleteStoredInputArgs(input.callID);return}if(typeof subagentType==="string")try{let mergedArgs={...storedArgs??{},...directArgs??{}};await recordPlanCriticApprovalSnapshotIfApplicable(directory,input,mergedArgs,_output)}catch(err){warn(`[delegation-gate] plan critic approval snapshot failed: ${err instanceof Error?err.message:String(err)}`)}if(standardDispatch){let taskChangeContext=coderTaskChangeContextByCallID.get(input.callID);if(taskChangeContext)rememberCoderObservedFiles(input.callID,changedFilesSinceSnapshot(taskChangeContext.baseline.directory,taskChangeContext.baseline));standardWorktreeByCallID.delete(input.callID),awaitingMergeByCallID.set(input.callID,{callID:input.callID,parentSessionID:standardDispatch.parentSessionID,taskId:standardDispatch.taskId,planTaskId:standardDispatch.planTaskId,branch:standardDispatch.handle.branchName,worktreePath:standardDispatch.handle.worktreePath,mergeStrategy:standardDispatch.mergeStrategy,queuedAt:Date.now()}),await finishStandardWorktreeDispatch(directory,standardDispatch,config2,input.callID).catch((err)=>{let reason=err instanceof Error?err.message:String(err);warn(`[delegation-gate] standard worktree merge-back failed for ${standardDispatch.taskId}: ${reason}`),recordWorktreeMergeFailure(standardDispatch.planTaskId??standardDispatch.taskId,{outcome:"failed",stage:"merge-back",message:reason,worktreePath:standardDispatch.handle.worktreePath,branch:standardDispatch.handle.branchName,completedAt:Date.now()});let dispatchSession=ensureAgentSession(standardDispatch.parentSessionID);dispatchSession.pendingAdvisoryMessages??=[],dispatchSession.pendingAdvisoryMessages.push(`STANDARD_WORKTREE_MERGE_FAILED: task ${standardDispatch.taskId} preserved at ${standardDispatch.handle.worktreePath}; reason: ${reason}.`),awaitingMergeByCallID.delete(input.callID)})}let hasReviewer=!1,hasTestEngineer=!1;if(typeof subagentType==="string"){let targetAgent=stripKnownSwarmPrefix(subagentType);if(targetAgent==="reviewer")hasReviewer=!0;if(targetAgent==="test_engineer")hasTestEngineer=!0;if(!councilActive){if((targetAgent==="reviewer"||targetAgent==="test_engineer")&&session.taskWorkflowStates){let stageBEligibleStates=["coder_delegated","pre_check_passed","reviewer_run"],perTaskVerdicts=parsePerTaskVerdicts(outputText(_output)),hasPerTaskAttribution=perTaskVerdicts.size>0,{readTaskEvidence:readTaskEvidence2}=await Promise.resolve().then(() => (init_gate_evidence(),exports_gate_evidence));for(let[taskId,state]of session.taskWorkflowStates){if(!stageBEligibleStates.includes(state))continue;if(hasPerTaskAttribution&&!perTaskVerdicts.has(taskId))continue;let eligibleState=state;if(recordStageBCompletion(session,taskId,targetAgent),hasPerTaskAttribution)try{let turbo=hasActiveTurboMode(input.sessionID),{recordGateEvidence:recordGateEvidence2}=await Promise.resolve().then(() => (init_gate_evidence(),exports_gate_evidence));await recordGateEvidence2(directory,taskId,targetAgent,input.sessionID,turbo)}catch(err){warn(`[delegation-gate] per-task evidence recording failed for ${taskId}: ${err instanceof Error?err.message:String(err)}`)}let taskEvidence=await readTaskEvidence2(directory,taskId),reviewerCompletesStageB=targetAgent==="reviewer"&&taskEvidence?.test_engineer_exempt===!0;if(hasBothStageBCompletions(session,taskId)||reviewerCompletesStageB)try{if(eligibleState==="coder_delegated"||eligibleState==="pre_check_passed")advanceTaskState(session,taskId,"reviewer_run",{telemetrySessionId:input.sessionID});advanceTaskState(session,taskId,"tests_run",{telemetrySessionId:input.sessionID})}catch(err){warn(`[delegation-gate] toolAfter stage-b-parallel: could not advance ${taskId} (${eligibleState}) → tests_run: ${err instanceof Error?err.message:String(err)}`)}else try{if(targetAgent==="reviewer"&&(eligibleState==="coder_delegated"||eligibleState==="pre_check_passed"))advanceTaskState(session,taskId,"reviewer_run",{telemetrySessionId:input.sessionID});else if(targetAgent==="test_engineer"&&eligibleState==="reviewer_run")advanceTaskState(session,taskId,"tests_run",{telemetrySessionId:input.sessionID})}catch(err){warn(`[delegation-gate] toolAfter stage-b-parallel intermediate: could not advance ${taskId} (${eligibleState}) after ${targetAgent}: ${err instanceof Error?err.message:String(err)}`)}}let seedTaskId=getSeedTaskId(session);if(seedTaskId){let seedEvidence=await readTaskEvidence2(directory,seedTaskId),reviewerCompletesSeedStageB=targetAgent==="reviewer"&&seedEvidence?.test_engineer_exempt===!0;for(let[,otherSession]of swarmState.agentSessions){if(otherSession===session)continue;if(!otherSession.taskWorkflowStates)continue;if(!otherSession.taskWorkflowStates.has(seedTaskId))otherSession.taskWorkflowStates.set(seedTaskId,"coder_delegated");let seedState=otherSession.taskWorkflowStates.get(seedTaskId);if(!seedState||!stageBEligibleStates.includes(seedState))continue;let seedEligibleState=seedState;if(recordStageBCompletion(otherSession,seedTaskId,targetAgent),hasBothStageBCompletions(otherSession,seedTaskId)||reviewerCompletesSeedStageB)try{if(seedEligibleState==="coder_delegated"||seedEligibleState==="pre_check_passed")advanceTaskState(otherSession,seedTaskId,"reviewer_run",{emitTelemetry:!1});advanceTaskState(otherSession,seedTaskId,"tests_run",{emitTelemetry:!1})}catch(err){warn(`[delegation-gate] toolAfter cross-session stage-b-parallel: could not advance ${seedTaskId} (${seedEligibleState}) → tests_run: ${err instanceof Error?err.message:String(err)}`)}else try{if(targetAgent==="reviewer"&&(seedEligibleState==="coder_delegated"||seedEligibleState==="pre_check_passed"))advanceTaskState(otherSession,seedTaskId,"reviewer_run",{emitTelemetry:!1});else if(targetAgent==="test_engineer"&&seedEligibleState==="reviewer_run")advanceTaskState(otherSession,seedTaskId,"tests_run",{emitTelemetry:!1})}catch(err){warn(`[delegation-gate] toolAfter cross-session stage-b-parallel intermediate: could not advance ${seedTaskId} (${seedEligibleState}) after ${targetAgent}: ${err instanceof Error?err.message:String(err)}`)}}}}}}if(typeof subagentType==="string")try{let mergedArgs={...storedArgs??{},...directArgs},evidenceTaskId=await resolveEvidenceTaskId(mergedArgs,session,directory);if(evidenceTaskId){let turbo=hasActiveTurboMode(input.sessionID),gateAgents=["reviewer","test_engineer","docs","designer","critic","explorer","sme"],targetAgentForEvidence=stripKnownSwarmPrefix(subagentType);if(gateAgents.includes(targetAgentForEvidence)){let{recordGateEvidence:recordGateEvidence2}=await Promise.resolve().then(() => (init_gate_evidence(),exports_gate_evidence));await recordGateEvidence2(directory,evidenceTaskId,targetAgentForEvidence,input.sessionID,turbo)}else{let{recordAgentDispatch:recordAgentDispatch2}=await Promise.resolve().then(() => (init_gate_evidence(),exports_gate_evidence)),taskChangeContext=targetAgentForEvidence==="coder"?coderTaskChangeContextByCallID.get(input.callID):void 0,observedFiles=taskChangeContext?coderObservedFilesByCallID.get(input.callID)??changedFilesSinceSnapshot(taskChangeContext.baseline.directory,taskChangeContext.baseline):null;await recordAgentDispatch2(directory,evidenceTaskId,targetAgentForEvidence,turbo,{testEngineerExempt:targetAgentForEvidence==="coder"&&isMarkdownOnlyTaskChange(taskChangeContext?.declaredFiles,observedFiles)})}}}catch(err){console.warn(`[delegation-gate] evidence recording failed: ${err instanceof Error?err.message:String(err)}`)}finally{if(stripKnownSwarmPrefix(subagentType)==="coder")clearCoderTaskChangeContext(input.callID)}if(storedArgs!==void 0)deleteStoredInputArgs(input.callID);if(!subagentType||!hasReviewer||councilActive){let delegationChain=swarmState.delegationChains.get(input.sessionID);if(delegationChain&&delegationChain.length>0){let lastCoderIndex=-1;for(let i=delegationChain.length-1;i>=0;i--)if(stripKnownSwarmPrefix(delegationChain[i].to).includes("coder")){lastCoderIndex=i;break}let searchStart=lastCoderIndex===-1?0:lastCoderIndex,afterCoder=delegationChain.slice(searchStart);for(let delegation of afterCoder){let target=stripKnownSwarmPrefix(delegation.to);if(target==="reviewer")hasReviewer=!0;if(target==="test_engineer")hasTestEngineer=!0}if(lastCoderIndex!==-1&&hasReviewer&&hasTestEngineer)session.qaSkipCount=0,session.qaSkipTaskIds=[];if(!councilActive){if(lastCoderIndex!==-1&&hasReviewer&&session.taskWorkflowStates){for(let[taskId,state]of session.taskWorkflowStates)if(state==="coder_delegated"||state==="pre_check_passed")try{advanceTaskState(session,taskId,"reviewer_run")}catch(err){warn(`[delegation-gate] fallback: could not advance ${taskId} (${state}) → reviewer_run: ${err instanceof Error?err.message:String(err)}`)}}if(lastCoderIndex!==-1&&hasReviewer&&hasTestEngineer&&session.taskWorkflowStates){for(let[taskId,state]of session.taskWorkflowStates)if(state==="reviewer_run")try{advanceTaskState(session,taskId,"tests_run")}catch(err){warn(`[delegation-gate] fallback: could not advance ${taskId} (${state}) → tests_run: ${err instanceof Error?err.message:String(err)}`)}}if(lastCoderIndex!==-1&&hasReviewer)for(let[,otherSession]of swarmState.agentSessions){if(otherSession===session)continue;if(!otherSession.taskWorkflowStates)continue;let seedTaskId=getSeedTaskId(session);if(seedTaskId&&!otherSession.taskWorkflowStates.has(seedTaskId))otherSession.taskWorkflowStates.set(seedTaskId,"coder_delegated");for(let[taskId,state]of otherSession.taskWorkflowStates)if(state==="coder_delegated"||state==="pre_check_passed")try{advanceTaskState(otherSession,taskId,"reviewer_run",{emitTelemetry:!1})}catch(err){warn(`[delegation-gate] fallback cross-session: could not advance ${taskId} (${state}) → reviewer_run: ${err instanceof Error?err.message:String(err)}`)}}if(lastCoderIndex!==-1&&hasReviewer&&hasTestEngineer)for(let[,otherSession]of swarmState.agentSessions){if(otherSession===session)continue;if(!otherSession.taskWorkflowStates)continue;let seedTaskId=getSeedTaskId(session);if(seedTaskId&&!otherSession.taskWorkflowStates.has(seedTaskId))otherSession.taskWorkflowStates.set(seedTaskId,"reviewer_run");for(let[taskId,state]of otherSession.taskWorkflowStates)if(state==="reviewer_run")try{advanceTaskState(otherSession,taskId,"tests_run",{emitTelemetry:!1})}catch(err){warn(`[delegation-gate] fallback cross-session: could not advance ${taskId} (${state}) → tests_run: ${err instanceof Error?err.message:String(err)}`)}}}}try{let evidenceTaskId=await resolveEvidenceTaskId(directArgs,session,directory);if(evidenceTaskId){let turbo=hasActiveTurboMode(input.sessionID);if(hasReviewer){let{recordGateEvidence:recordGateEvidence2}=await Promise.resolve().then(() => (init_gate_evidence(),exports_gate_evidence));await recordGateEvidence2(directory,evidenceTaskId,"reviewer",input.sessionID,turbo)}if(hasTestEngineer){let{recordGateEvidence:recordGateEvidence2}=await Promise.resolve().then(() => (init_gate_evidence(),exports_gate_evidence));await recordGateEvidence2(directory,evidenceTaskId,"test_engineer",input.sessionID,turbo)}}}catch(err){console.warn(`[delegation-gate] fallback evidence recording failed: ${err instanceof Error?err.message:String(err)}`)}}if(session.taskWorkflowStates){for(let[,state]of session.taskWorkflowStates)if(state==="tests_run"){let taskAwaiting=await findTaskAwaitingCompletion(directory,session);if(taskAwaiting)session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(completionGateViolationMessage(taskAwaiting));break}}}}}}var EvidenceTaskIdPlanSchema,pendingCoderScopeByTaskId,SWARM_BACKGROUND_TASK_BLOCKED_MESSAGE,PLAN_CRITIC_TASK_SIGNALS,ACTIVE_PARALLEL_TASK_STATES,_internals25;var init_delegation_gate=__esm(()=>{init_zod();init_workspace_snapshot();init_schema();init_gate_evidence_classification();init_ledger();init_manager();init_utils3();init_state2();init_telemetry();init_logger();init_task_id();init_worktree_isolation();init_config2();init_gateway();init_reward_capture();init_worktree_isolation();init_worktree_merge_status();init_guardrails2();init_normalize_tool_name();init_utils2();EvidenceTaskIdPlanSchema=exports_external.object({phases:exports_external.array(exports_external.object({tasks:exports_external.array(exports_external.object({id:exports_external.string(),status:exports_external.string().optional()}).passthrough()).optional()}).passthrough()).optional()}).passthrough(),pendingCoderScopeByTaskId=new Map;SWARM_BACKGROUND_TASK_BLOCKED_MESSAGE="SWARM_BACKGROUND_TASK_BLOCKED: OpenCode background subagents (Task with background=true, requires OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true) are recognized upstream, but swarm "+"cannot yet safely consume their deferred completion events — the Task returns a running "+"placeholder now and completes later via synthetic injection, which would advance swarm gates before any review/test output exists. Omit `background` (or set background=false) for swarm delegations until the completion-ingestion PR lands.";PLAN_CRITIC_TASK_SIGNALS=["critic-gate","plan critic","review plan","review the plan","plan.md","approve the plan","plan approval"];ACTIVE_PARALLEL_TASK_STATES=new Set(["coder_delegated","pre_check_passed","reviewer_run","tests_run"]);_internals25={resolveEvidenceTaskId,resolveDelegatedPlanTaskId,parsePerTaskVerdicts,buildParallelExecutionGuidance,loadPlanJsonOnly,resetStandardWorktreeIsolationState,PLAN_CRITIC_TASK_SIGNALS,get provisionWorktree(){return _internals19.provisionWorktree},set provisionWorktree(v){_internals19.provisionWorktree=v},get removeWorktree(){return _internals19.removeWorktree},set removeWorktree(v){_internals19.removeWorktree=v},get attemptMergeBackFromDirty(){return _internals19.attemptMergeBackFromDirty},set attemptMergeBackFromDirty(v){_internals19.attemptMergeBackFromDirty=v},get postMergeCleanup(){return _internals19.postMergeCleanup},set postMergeCleanup(v){_internals19.postMergeCleanup=v}}});function positiveIntegerOrDefault(value,fallback){return Number.isInteger(value)&&Number(value)>0?Number(value):fallback}function rememberSession(sessionID,state){if(realtimeLearningNudgeBySession.has(sessionID))realtimeLearningNudgeBySession.delete(sessionID);realtimeLearningNudgeBySession.set(sessionID,state);while(realtimeLearningNudgeBySession.size>500){let oldestSessionID=realtimeLearningNudgeBySession.keys().next().value;if(oldestSessionID===void 0)break;realtimeLearningNudgeBySession.delete(oldestSessionID)}}function recordRealtimeLearningToolCall(sessionID){let prior=realtimeLearningNudgeBySession.get(sessionID),nextState={observedToolCallCount:(prior?.observedToolCallCount??0)+1,lastNudgedAtToolCallCount:prior?.lastNudgedAtToolCallCount??0};return rememberSession(sessionID,nextState),nextState.observedToolCallCount}function getRealtimeLearningToolCallCount(sessionID){if(!sessionID)return 0;return realtimeLearningNudgeBySession.get(sessionID)?.observedToolCallCount??0}function shouldInjectRealtimeLearningNudge(args2){if(!args2.sessionID)return!1;if(args2.config?.enabled===!1)return!1;let state=realtimeLearningNudgeBySession.get(args2.sessionID),toolCallCount=state?.observedToolCallCount??0,firstAfterToolCalls=positiveIntegerOrDefault(args2.config?.first_after_tool_calls,10),repeatAfterToolCalls=positiveIntegerOrDefault(args2.config?.repeat_after_tool_calls,25);if(toolCallCount<firstAfterToolCalls)return!1;if(!state||state.lastNudgedAtToolCallCount===0)return!0;return toolCallCount-state.lastNudgedAtToolCallCount>=repeatAfterToolCalls}function recordRealtimeLearningNudge(sessionID){let prior=realtimeLearningNudgeBySession.get(sessionID);if(!prior)return;rememberSession(sessionID,{...prior,lastNudgedAtToolCallCount:prior.observedToolCallCount})}function resetRealtimeLearningNudgeState(){realtimeLearningNudgeBySession.clear()}function clearRealtimeLearningNudgeSession(sessionID){realtimeLearningNudgeBySession.delete(sessionID)}function buildRealtimeLearningNudge(args2){return["[SWARM LEARNING NUDGE]",`Session has ${args2.toolCallCount} tool calls in phase ${args2.currentPhase}. Before continuing, decide whether the current work revealed a durable procedural lesson.`,"- If yes, call knowledge_add now with actionable when/then/scope fields so later turns can retrieve it.","- If the signal needs review across evidence, repeated outcomes, or generated-skill health, let the curator phase/postmortem path handle it; curator can emit knowledge_application_findings and skill_candidates without activating skills.","- Prefer reinforcing existing knowledge over noisy one-offs. Do not save transient setup failures, stale negative tool claims, or repo-specific accidents without a reusable trigger.","- If repeated KNOWLEDGE_IGNORED/VIOLATED outcomes or stale generated skills are accumulating, use skill_improve only when enabled/approved; generated skills stay proposal/draft gated and must not auto-activate.","- If there is nothing durable, continue without adding knowledge."].join(`
|
|
642
|
+
`)}`,batchWarnSystemIdx=messages.findIndex((m)=>m&&m.info?.role==="system"),batchWarnInsertIdx=batchWarnSystemIdx>=0?batchWarnSystemIdx+1:0,batchWarnMessage={info:{role:"system"},parts:[{type:"text",text:warningText}]};messages.splice(batchWarnInsertIdx,0,batchWarnMessage)},toolAfter:async(input,_output)=>{if(!input.sessionID)return;let session=swarmState.agentSessions.get(input.sessionID);if(!session)return;let normalized=normalizeToolName(input.tool),{qaGateSessionOverrides}=ensureAgentSession(input.sessionID),councilActive=await isCouncilGateActive(directory,config2.council,qaGateSessionOverrides??{});if(normalized==="update_task_status"){let directArgs=input.args,storedArgs=getStoredInputArgs(input.callID),completionArgs=directArgs??storedArgs;if(completionArgs&&completionArgs.status==="completed"){let rawTaskId=completionArgs.task_id??completionArgs.taskId,completionTaskId=typeof rawTaskId==="string"?rawTaskId.trim():null;if(completionTaskId&&isStrictTaskId(completionTaskId))try{let completionSession=ensureAgentSession(input.sessionID);await advanceTaskStateAndPersist(completionSession,completionTaskId,"complete",directory,{telemetrySessionId:input.sessionID},config2.council)}catch(err){warn(`[delegation-gate] toolAfter completion advancement: could not advance ${completionTaskId} → complete: ${err instanceof Error?err.message:String(err)}`)}}}if(normalized==="submit_council_verdicts"){try{let result=typeof _output==="string"?JSON.parse(_output):_output;if(result&&typeof result==="object"&&result.success===!0&&typeof result.overallVerdict==="string"){let directArgs=input.args,storedArgs=getStoredInputArgs(input.callID),taskIdRaw=directArgs?.taskId??storedArgs?.taskId,taskId=typeof taskIdRaw==="string"?taskIdRaw:null;if(taskId){if(!session.taskCouncilApproved)session.taskCouncilApproved=new Map;let priorRewarded=session.taskCouncilApproved.get(taskId)?.rewarded===!0;if(session.taskCouncilApproved.set(taskId,{verdict:result.overallVerdict,roundNumber:typeof result.roundNumber==="number"?result.roundNumber:1,quorumSize:typeof result.quorumSize==="number"?result.quorumSize:1,rewarded:priorRewarded}),councilActive&&result.overallVerdict==="APPROVE"&&result.allCriteriaMet===!0&&(result.requiredFixesCount??0)===0)try{await advanceTaskStateAndPersist(session,taskId,"complete",directory,{telemetrySessionId:input.sessionID},config2.council);try{let memoryConfig=config2.memory;if(getTaskState(session,taskId)==="complete"&&memoryConfig?.enabled===!0){let approvedEntry=session.taskCouncilApproved?.get(taskId);if(approvedEntry?.rewarded!==!0){let provider=createConfiguredMemoryProvider(directory,memoryConfig);try{let synthesis={overallVerdict:result.overallVerdict,allCriteriaMet:result.allCriteriaMet===!0,requiredFixesCount:result.requiredFixesCount??0,roundNumber:typeof result.roundNumber==="number"?result.roundNumber:void 0,quorumSize:typeof result.quorumSize==="number"?result.quorumSize:void 0},verdictSynthesisJson=JSON.stringify(synthesis),cap=memoryConfig.qLearning.verdictPayloadCapBytes;if(typeof cap==="number"&&cap>0&&verdictSynthesisJson.length>cap)verdictSynthesisJson=JSON.stringify(truncateObjectForJson(synthesis,cap));if(await applyCouncilReward(provider,{runId:input.sessionID,unitId:taskId,reward:COUNCIL_VERDICT_REWARDS.APPROVE,eta:memoryConfig.qLearning.learningRate,initialQValue:memoryConfig.qLearning.initialQValue,qLearning:memoryConfig.qLearning,verdictSynthesisJson,timestamp:new Date().toISOString()}),approvedEntry)approvedEntry.rewarded=!0}finally{await provider.close?.()}}}}catch(rewardErr){warn(`[delegation-gate] council reward capture failed: ${rewardErr instanceof Error?rewardErr.message:String(rewardErr)}`)}}catch(err){warn(`[delegation-gate] toolAfter submit_council_verdicts: could not advance ${taskId} → complete: ${err instanceof Error?err.message:String(err)}`)}}}}catch(err){log(`[delegation-gate] toolAfter submit_council_verdicts: failed to parse output: ${err instanceof Error?err.message:String(err)}`)}return}if(normalized==="Task"||normalized==="task"){let standardDispatch=standardWorktreeByCallID.get(input.callID),directArgsRaw=input.args,directArgs=directArgsRaw?{...directArgsRaw}:void 0;if(standardDispatch&&directArgs)if(standardDispatch.planTaskId)directArgs.task_id=standardDispatch.planTaskId;else delete directArgs.task_id;let storedArgs=getStoredInputArgs(input.callID),subagentType=directArgs?.subagent_type??storedArgs?.subagent_type;if(typeof subagentType==="string"&&isKnownCanonicalRole(stripKnownSwarmPrefix(subagentType))&&(isBackgroundTrue(directArgs?.background)||isBackgroundTrue(storedArgs?.background)||outputLooksLikeBackgroundRunning(_output))){if(backgroundSubagentsEnabled)try{let{extractDispatchIds:extractDispatchIds2}=await Promise.resolve().then(() => (init_task_envelope(),exports_task_envelope)),{buildPromptSnapshot:buildPromptSnapshot2,recordPendingDelegation:recordPendingDelegation2}=await Promise.resolve().then(() => (init_pending_delegations(),exports_pending_delegations)),{captureWorkspaceSnapshot:captureWorkspaceSnapshot2}=await Promise.resolve().then(() => (init_workspace_snapshot(),exports_workspace_snapshot)),{subagentSessionId,jobId}=extractDispatchIds2(_output);if(subagentSessionId){let mergedArgs={...storedArgs??{},...directArgs},evidenceTaskId=await resolveEvidenceTaskId(mergedArgs,session,directory),scope=session.declaredCoderScope&&session.declaredCoderScope.length>0?session.declaredCoderScope.join(","):evidenceTaskId,prHeadShaRaw=mergedArgs.prHeadSha??mergedArgs.pr_head_sha,prHeadSha=typeof prHeadShaRaw==="string"?prHeadShaRaw:null,taskChangeContext=stripKnownSwarmPrefix(subagentType)==="coder"?coderTaskChangeContextByCallID.get(input.callID):void 0;await recordPendingDelegation2(directory,{correlationId:subagentSessionId,jobId,subagentSessionId,parentSessionId:input.sessionID,callID:input.callID,normalizedAgent:stripKnownSwarmPrefix(subagentType),swarmPrefixedAgent:subagentType,planTaskId:evidenceTaskId,evidenceTaskId,workspace:taskChangeContext?{...taskChangeContext.baseline,prHeadSha,scope}:captureWorkspaceSnapshot2(directory,{prHeadSha,scope}),taskChangeContext,prompt:typeof mergedArgs.prompt==="string"?buildPromptSnapshot2(mergedArgs.prompt,delegationMaxChars):void 0,generation:1},{staleTimeoutMs:backgroundPendingTimeoutMs})}else warn("[delegation-gate] background dispatch had no correlation id (no jobId / no envelope) — not tracked")}catch(err){warn(`[delegation-gate] background pending recording failed: ${err instanceof Error?err.message:String(err)}`)}if(clearCoderTaskChangeContext(input.callID),storedArgs!==void 0)deleteStoredInputArgs(input.callID);return}if(typeof subagentType==="string")try{let mergedArgs={...storedArgs??{},...directArgs??{}};await recordPlanCriticApprovalSnapshotIfApplicable(directory,input,mergedArgs,_output)}catch(err){warn(`[delegation-gate] plan critic approval snapshot failed: ${err instanceof Error?err.message:String(err)}`)}if(standardDispatch){let taskChangeContext=coderTaskChangeContextByCallID.get(input.callID);if(taskChangeContext)rememberCoderObservedFiles(input.callID,changedFilesSinceSnapshot(taskChangeContext.baseline.directory,taskChangeContext.baseline));standardWorktreeByCallID.delete(input.callID),awaitingMergeByCallID.set(input.callID,{callID:input.callID,parentSessionID:standardDispatch.parentSessionID,taskId:standardDispatch.taskId,planTaskId:standardDispatch.planTaskId,branch:standardDispatch.handle.branchName,worktreePath:standardDispatch.handle.worktreePath,mergeStrategy:standardDispatch.mergeStrategy,queuedAt:Date.now()}),await finishStandardWorktreeDispatch(directory,standardDispatch,config2,input.callID).catch((err)=>{let reason=err instanceof Error?err.message:String(err);warn(`[delegation-gate] standard worktree merge-back failed for ${standardDispatch.taskId}: ${reason}`),recordWorktreeMergeFailure(standardDispatch.planTaskId??standardDispatch.taskId,{outcome:"failed",stage:"merge-back",message:reason,worktreePath:standardDispatch.handle.worktreePath,branch:standardDispatch.handle.branchName,completedAt:Date.now()});let dispatchSession=ensureAgentSession(standardDispatch.parentSessionID);dispatchSession.pendingAdvisoryMessages??=[],dispatchSession.pendingAdvisoryMessages.push(`STANDARD_WORKTREE_MERGE_FAILED: task ${standardDispatch.taskId} preserved at ${standardDispatch.handle.worktreePath}; reason: ${reason}.`),awaitingMergeByCallID.delete(input.callID)})}let hasReviewer=!1,hasTestEngineer=!1;if(typeof subagentType==="string"){let targetAgent=stripKnownSwarmPrefix(subagentType);if(targetAgent==="reviewer")hasReviewer=!0;if(targetAgent==="test_engineer")hasTestEngineer=!0;if(!councilActive){if((targetAgent==="reviewer"||targetAgent==="test_engineer")&&session.taskWorkflowStates){let stageBEligibleStates=["coder_delegated","pre_check_passed","reviewer_run"],perTaskVerdicts=parsePerTaskVerdicts(outputText(_output)),hasPerTaskAttribution=perTaskVerdicts.size>0,{readTaskEvidence:readTaskEvidence2}=await Promise.resolve().then(() => (init_gate_evidence(),exports_gate_evidence));for(let[taskId,state]of session.taskWorkflowStates){if(!stageBEligibleStates.includes(state))continue;if(hasPerTaskAttribution&&!perTaskVerdicts.has(taskId))continue;let eligibleState=state;if(recordStageBCompletion(session,taskId,targetAgent),hasPerTaskAttribution)try{let turbo=hasActiveTurboMode(input.sessionID),{recordGateEvidence:recordGateEvidence2}=await Promise.resolve().then(() => (init_gate_evidence(),exports_gate_evidence));await recordGateEvidence2(directory,taskId,targetAgent,input.sessionID,turbo)}catch(err){warn(`[delegation-gate] per-task evidence recording failed for ${taskId}: ${err instanceof Error?err.message:String(err)}`)}let taskEvidence=await readTaskEvidence2(directory,taskId),reviewerCompletesStageB=targetAgent==="reviewer"&&taskEvidence?.test_engineer_exempt===!0;if(hasBothStageBCompletions(session,taskId)||reviewerCompletesStageB)try{if(eligibleState==="coder_delegated"||eligibleState==="pre_check_passed")advanceTaskState(session,taskId,"reviewer_run",{telemetrySessionId:input.sessionID});advanceTaskState(session,taskId,"tests_run",{telemetrySessionId:input.sessionID})}catch(err){warn(`[delegation-gate] toolAfter stage-b-parallel: could not advance ${taskId} (${eligibleState}) → tests_run: ${err instanceof Error?err.message:String(err)}`)}else try{if(targetAgent==="reviewer"&&(eligibleState==="coder_delegated"||eligibleState==="pre_check_passed"))advanceTaskState(session,taskId,"reviewer_run",{telemetrySessionId:input.sessionID});else if(targetAgent==="test_engineer"&&eligibleState==="reviewer_run")advanceTaskState(session,taskId,"tests_run",{telemetrySessionId:input.sessionID})}catch(err){warn(`[delegation-gate] toolAfter stage-b-parallel intermediate: could not advance ${taskId} (${eligibleState}) after ${targetAgent}: ${err instanceof Error?err.message:String(err)}`)}}let seedTaskId=getSeedTaskId(session);if(seedTaskId){let seedEvidence=await readTaskEvidence2(directory,seedTaskId),reviewerCompletesSeedStageB=targetAgent==="reviewer"&&seedEvidence?.test_engineer_exempt===!0;for(let[,otherSession]of swarmState.agentSessions){if(otherSession===session)continue;if(!otherSession.taskWorkflowStates)continue;if(!otherSession.taskWorkflowStates.has(seedTaskId))otherSession.taskWorkflowStates.set(seedTaskId,"coder_delegated");let seedState=otherSession.taskWorkflowStates.get(seedTaskId);if(!seedState||!stageBEligibleStates.includes(seedState))continue;let seedEligibleState=seedState;if(recordStageBCompletion(otherSession,seedTaskId,targetAgent),hasBothStageBCompletions(otherSession,seedTaskId)||reviewerCompletesSeedStageB)try{if(seedEligibleState==="coder_delegated"||seedEligibleState==="pre_check_passed")advanceTaskState(otherSession,seedTaskId,"reviewer_run",{emitTelemetry:!1});advanceTaskState(otherSession,seedTaskId,"tests_run",{emitTelemetry:!1})}catch(err){warn(`[delegation-gate] toolAfter cross-session stage-b-parallel: could not advance ${seedTaskId} (${seedEligibleState}) → tests_run: ${err instanceof Error?err.message:String(err)}`)}else try{if(targetAgent==="reviewer"&&(seedEligibleState==="coder_delegated"||seedEligibleState==="pre_check_passed"))advanceTaskState(otherSession,seedTaskId,"reviewer_run",{emitTelemetry:!1});else if(targetAgent==="test_engineer"&&seedEligibleState==="reviewer_run")advanceTaskState(otherSession,seedTaskId,"tests_run",{emitTelemetry:!1})}catch(err){warn(`[delegation-gate] toolAfter cross-session stage-b-parallel intermediate: could not advance ${seedTaskId} (${seedEligibleState}) after ${targetAgent}: ${err instanceof Error?err.message:String(err)}`)}}}}}}if(typeof subagentType==="string")try{let mergedArgs={...storedArgs??{},...directArgs},evidenceTaskId=await resolveEvidenceTaskId(mergedArgs,session,directory);if(evidenceTaskId){let turbo=hasActiveTurboMode(input.sessionID),gateAgents=["reviewer","test_engineer","docs","designer","critic","explorer","sme"],targetAgentForEvidence=stripKnownSwarmPrefix(subagentType);if(gateAgents.includes(targetAgentForEvidence)){let{recordGateEvidence:recordGateEvidence2}=await Promise.resolve().then(() => (init_gate_evidence(),exports_gate_evidence));await recordGateEvidence2(directory,evidenceTaskId,targetAgentForEvidence,input.sessionID,turbo)}else{let{recordAgentDispatch:recordAgentDispatch2}=await Promise.resolve().then(() => (init_gate_evidence(),exports_gate_evidence)),taskChangeContext=targetAgentForEvidence==="coder"?coderTaskChangeContextByCallID.get(input.callID):void 0,observedFiles=taskChangeContext?coderObservedFilesByCallID.get(input.callID)??changedFilesSinceSnapshot(taskChangeContext.baseline.directory,taskChangeContext.baseline):null;await recordAgentDispatch2(directory,evidenceTaskId,targetAgentForEvidence,turbo,{testEngineerExempt:targetAgentForEvidence==="coder"&&isMarkdownOnlyTaskChange(taskChangeContext?.declaredFiles,observedFiles)})}}}catch(err){log(`[delegation-gate] evidence recording failed: ${err instanceof Error?err.message:String(err)}`)}finally{if(stripKnownSwarmPrefix(subagentType)==="coder")clearCoderTaskChangeContext(input.callID)}if(storedArgs!==void 0)deleteStoredInputArgs(input.callID);if(!subagentType||!hasReviewer||councilActive){let delegationChain=swarmState.delegationChains.get(input.sessionID);if(delegationChain&&delegationChain.length>0){let lastCoderIndex=-1;for(let i=delegationChain.length-1;i>=0;i--)if(stripKnownSwarmPrefix(delegationChain[i].to).includes("coder")){lastCoderIndex=i;break}let searchStart=lastCoderIndex===-1?0:lastCoderIndex,afterCoder=delegationChain.slice(searchStart);for(let delegation of afterCoder){let target=stripKnownSwarmPrefix(delegation.to);if(target==="reviewer")hasReviewer=!0;if(target==="test_engineer")hasTestEngineer=!0}if(lastCoderIndex!==-1&&hasReviewer&&hasTestEngineer)session.qaSkipCount=0,session.qaSkipTaskIds=[];if(!councilActive){if(lastCoderIndex!==-1&&hasReviewer&&session.taskWorkflowStates){for(let[taskId,state]of session.taskWorkflowStates)if(state==="coder_delegated"||state==="pre_check_passed")try{advanceTaskState(session,taskId,"reviewer_run")}catch(err){warn(`[delegation-gate] fallback: could not advance ${taskId} (${state}) → reviewer_run: ${err instanceof Error?err.message:String(err)}`)}}if(lastCoderIndex!==-1&&hasReviewer&&hasTestEngineer&&session.taskWorkflowStates){for(let[taskId,state]of session.taskWorkflowStates)if(state==="reviewer_run")try{advanceTaskState(session,taskId,"tests_run")}catch(err){warn(`[delegation-gate] fallback: could not advance ${taskId} (${state}) → tests_run: ${err instanceof Error?err.message:String(err)}`)}}if(lastCoderIndex!==-1&&hasReviewer)for(let[,otherSession]of swarmState.agentSessions){if(otherSession===session)continue;if(!otherSession.taskWorkflowStates)continue;let seedTaskId=getSeedTaskId(session);if(seedTaskId&&!otherSession.taskWorkflowStates.has(seedTaskId))otherSession.taskWorkflowStates.set(seedTaskId,"coder_delegated");for(let[taskId,state]of otherSession.taskWorkflowStates)if(state==="coder_delegated"||state==="pre_check_passed")try{advanceTaskState(otherSession,taskId,"reviewer_run",{emitTelemetry:!1})}catch(err){warn(`[delegation-gate] fallback cross-session: could not advance ${taskId} (${state}) → reviewer_run: ${err instanceof Error?err.message:String(err)}`)}}if(lastCoderIndex!==-1&&hasReviewer&&hasTestEngineer)for(let[,otherSession]of swarmState.agentSessions){if(otherSession===session)continue;if(!otherSession.taskWorkflowStates)continue;let seedTaskId=getSeedTaskId(session);if(seedTaskId&&!otherSession.taskWorkflowStates.has(seedTaskId))otherSession.taskWorkflowStates.set(seedTaskId,"reviewer_run");for(let[taskId,state]of otherSession.taskWorkflowStates)if(state==="reviewer_run")try{advanceTaskState(otherSession,taskId,"tests_run",{emitTelemetry:!1})}catch(err){warn(`[delegation-gate] fallback cross-session: could not advance ${taskId} (${state}) → tests_run: ${err instanceof Error?err.message:String(err)}`)}}}}try{let evidenceTaskId=await resolveEvidenceTaskId(directArgs,session,directory);if(evidenceTaskId){let turbo=hasActiveTurboMode(input.sessionID);if(hasReviewer){let{recordGateEvidence:recordGateEvidence2}=await Promise.resolve().then(() => (init_gate_evidence(),exports_gate_evidence));await recordGateEvidence2(directory,evidenceTaskId,"reviewer",input.sessionID,turbo)}if(hasTestEngineer){let{recordGateEvidence:recordGateEvidence2}=await Promise.resolve().then(() => (init_gate_evidence(),exports_gate_evidence));await recordGateEvidence2(directory,evidenceTaskId,"test_engineer",input.sessionID,turbo)}}}catch(err){log(`[delegation-gate] fallback evidence recording failed: ${err instanceof Error?err.message:String(err)}`)}}if(session.taskWorkflowStates){for(let[,state]of session.taskWorkflowStates)if(state==="tests_run"){let taskAwaiting=await findTaskAwaitingCompletion(directory,session);if(taskAwaiting)session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(completionGateViolationMessage(taskAwaiting));break}}}}}}var EvidenceTaskIdPlanSchema,pendingCoderScopeByTaskId,SWARM_BACKGROUND_TASK_BLOCKED_MESSAGE,PLAN_CRITIC_TASK_SIGNALS,ACTIVE_PARALLEL_TASK_STATES,_internals25;var init_delegation_gate=__esm(()=>{init_zod();init_workspace_snapshot();init_schema();init_gate_evidence_classification();init_ledger();init_manager();init_utils3();init_state2();init_telemetry();init_logger();init_task_id();init_worktree_isolation();init_config2();init_gateway();init_reward_capture();init_worktree_isolation();init_worktree_merge_status();init_guardrails2();init_normalize_tool_name();init_utils2();EvidenceTaskIdPlanSchema=exports_external.object({phases:exports_external.array(exports_external.object({tasks:exports_external.array(exports_external.object({id:exports_external.string(),status:exports_external.string().optional()}).passthrough()).optional()}).passthrough()).optional()}).passthrough(),pendingCoderScopeByTaskId=new Map;SWARM_BACKGROUND_TASK_BLOCKED_MESSAGE="SWARM_BACKGROUND_TASK_BLOCKED: OpenCode background subagents (Task with background=true, requires OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true) are recognized upstream, but swarm "+"cannot yet safely consume their deferred completion events — the Task returns a running "+"placeholder now and completes later via synthetic injection, which would advance swarm gates before any review/test output exists. Omit `background` (or set background=false) for swarm delegations until the completion-ingestion PR lands.";PLAN_CRITIC_TASK_SIGNALS=["critic-gate","plan critic","review plan","review the plan","plan.md","approve the plan","plan approval"];ACTIVE_PARALLEL_TASK_STATES=new Set(["coder_delegated","pre_check_passed","reviewer_run","tests_run"]);_internals25={resolveEvidenceTaskId,resolveDelegatedPlanTaskId,parsePerTaskVerdicts,buildParallelExecutionGuidance,loadPlanJsonOnly,resetStandardWorktreeIsolationState,PLAN_CRITIC_TASK_SIGNALS,get provisionWorktree(){return _internals19.provisionWorktree},set provisionWorktree(v){_internals19.provisionWorktree=v},get removeWorktree(){return _internals19.removeWorktree},set removeWorktree(v){_internals19.removeWorktree=v},get attemptMergeBackFromDirty(){return _internals19.attemptMergeBackFromDirty},set attemptMergeBackFromDirty(v){_internals19.attemptMergeBackFromDirty=v},get postMergeCleanup(){return _internals19.postMergeCleanup},set postMergeCleanup(v){_internals19.postMergeCleanup=v}}});function positiveIntegerOrDefault(value,fallback){return Number.isInteger(value)&&Number(value)>0?Number(value):fallback}function rememberSession(sessionID,state){if(realtimeLearningNudgeBySession.has(sessionID))realtimeLearningNudgeBySession.delete(sessionID);realtimeLearningNudgeBySession.set(sessionID,state);while(realtimeLearningNudgeBySession.size>500){let oldestSessionID=realtimeLearningNudgeBySession.keys().next().value;if(oldestSessionID===void 0)break;realtimeLearningNudgeBySession.delete(oldestSessionID)}}function recordRealtimeLearningToolCall(sessionID){let prior=realtimeLearningNudgeBySession.get(sessionID),nextState={observedToolCallCount:(prior?.observedToolCallCount??0)+1,lastNudgedAtToolCallCount:prior?.lastNudgedAtToolCallCount??0};return rememberSession(sessionID,nextState),nextState.observedToolCallCount}function getRealtimeLearningToolCallCount(sessionID){if(!sessionID)return 0;return realtimeLearningNudgeBySession.get(sessionID)?.observedToolCallCount??0}function shouldInjectRealtimeLearningNudge(args2){if(!args2.sessionID)return!1;if(args2.config?.enabled===!1)return!1;let state=realtimeLearningNudgeBySession.get(args2.sessionID),toolCallCount=state?.observedToolCallCount??0,firstAfterToolCalls=positiveIntegerOrDefault(args2.config?.first_after_tool_calls,10),repeatAfterToolCalls=positiveIntegerOrDefault(args2.config?.repeat_after_tool_calls,25);if(toolCallCount<firstAfterToolCalls)return!1;if(!state||state.lastNudgedAtToolCallCount===0)return!0;return toolCallCount-state.lastNudgedAtToolCallCount>=repeatAfterToolCalls}function recordRealtimeLearningNudge(sessionID){let prior=realtimeLearningNudgeBySession.get(sessionID);if(!prior)return;rememberSession(sessionID,{...prior,lastNudgedAtToolCallCount:prior.observedToolCallCount})}function resetRealtimeLearningNudgeState(){realtimeLearningNudgeBySession.clear()}function clearRealtimeLearningNudgeSession(sessionID){realtimeLearningNudgeBySession.delete(sessionID)}function buildRealtimeLearningNudge(args2){return["[SWARM LEARNING NUDGE]",`Session has ${args2.toolCallCount} tool calls in phase ${args2.currentPhase}. Before continuing, decide whether the current work revealed a durable procedural lesson.`,"- If yes, call knowledge_add now with actionable when/then/scope fields so later turns can retrieve it.","- If the signal needs review across evidence, repeated outcomes, or generated-skill health, let the curator phase/postmortem path handle it; curator can emit knowledge_application_findings and skill_candidates without activating skills.","- Prefer reinforcing existing knowledge over noisy one-offs. Do not save transient setup failures, stale negative tool claims, or repo-specific accidents without a reusable trigger.","- If repeated KNOWLEDGE_IGNORED/VIOLATED outcomes or stale generated skills are accumulating, use skill_improve only when enabled/approved; generated skills stay proposal/draft gated and must not auto-activate.","- If there is nothing durable, continue without adding knowledge."].join(`
|
|
643
643
|
`)}var REALTIME_LEARNING_NUDGE_ID_PREFIX="realtime-learning-nudge",realtimeLearningNudgeBySession;var init_realtime_learning_nudge=__esm(()=>{realtimeLearningNudgeBySession=new Map});function evictOldestStepSessionIfNeeded(sessionId){if(sessionStepCounters.has(sessionId))return;while(sessionStepCounters.size>=500){let oldestSessionId=sessionStepCounters.keys().next().value;if(oldestSessionId===void 0)break;sessionStepCounters.delete(oldestSessionId)}}function nextTrajectoryStep(sessionId){evictOldestStepSessionIfNeeded(sessionId);let step=(sessionStepCounters.get(sessionId)??0)+1;return sessionStepCounters.set(sessionId,step),step}function clearTrajectoryStepCounters(sessionId){if(sessionId!==void 0)sessionStepCounters.delete(sessionId);else sessionStepCounters.clear()}var sessionStepCounters;var init_trajectory_step_state=__esm(()=>{sessionStepCounters=new Map});import*as fs21 from"node:fs/promises";import*as path45 from"node:path";function getTrajectoryPath(sessionId,directory){let relativePath=path45.join("trajectories",`${sessionId}.jsonl`);return validateSwarmPath(directory,relativePath)}function setTrajectoryCache(sessionId,entries,maxLines=1000){let boundedEntries=entries.length>maxLines?entries.slice(-Math.max(1,Math.floor(maxLines/2))):[...entries];if(!_inMemoryTrajectoryCache.has(sessionId))while(_inMemoryTrajectoryCache.size>=MAX_TRACKED_TRAJECTORY_SESSIONS){let oldestSessionId=_inMemoryTrajectoryCache.keys().next().value;if(oldestSessionId===void 0)break;_inMemoryTrajectoryCache.delete(oldestSessionId)}_inMemoryTrajectoryCache.set(sessionId,boundedEntries)}function getInMemoryTrajectory(sessionId){let cached2=_inMemoryTrajectoryCache.get(sessionId);return cached2?[...cached2]:[]}function clearTrajectoryCache(sessionId){if(sessionId!==void 0)_inMemoryTrajectoryCache.delete(sessionId);else _inMemoryTrajectoryCache.clear()}async function appendTrajectoryEntry(sessionId,entry,directory,maxLines=1000){try{let trajectoryPath=getTrajectoryPath(sessionId,directory);await fs21.mkdir(path45.dirname(trajectoryPath),{recursive:!0});let line=`${JSON.stringify(entry)}
|
|
644
|
-
`;await fs21.appendFile(trajectoryPath,line,"utf-8");let cached2=_inMemoryTrajectoryCache.get(sessionId)??[];setTrajectoryCache(sessionId,[...cached2,entry],maxLines)}catch(err){
|
|
645
|
-
`).filter((line)=>line.trim().length>0),entries=[];for(let line of lines)try{entries.push(JSON.parse(line))}catch{}return setTrajectoryCache(sessionId,entries),entries}catch(err){if(err.code==="ENOENT")return[];return
|
|
644
|
+
`;await fs21.appendFile(trajectoryPath,line,"utf-8");let cached2=_inMemoryTrajectoryCache.get(sessionId)??[];setTrajectoryCache(sessionId,[...cached2,entry],maxLines)}catch(err){log(`[trajectory-store] Failed to append trajectory entry: ${err}`)}}async function readTrajectory(sessionId,directory){try{let trajectoryPath=getTrajectoryPath(sessionId,directory),lines=(await fs21.readFile(trajectoryPath,"utf-8")).split(`
|
|
645
|
+
`).filter((line)=>line.trim().length>0),entries=[];for(let line of lines)try{entries.push(JSON.parse(line))}catch{}return setTrajectoryCache(sessionId,entries),entries}catch(err){if(err.code==="ENOENT")return[];return log(`[trajectory-store] Failed to read trajectory: ${err}`),[]}}async function cleanupOldTrajectoryFiles(directory,maxAgeDays=7){let cutoffMs=maxAgeDays*24*60*60*1000,now=Date.now();for(let subdir of["trajectories","replays"])try{let dirPath=validateSwarmPath(directory,subdir),entries=await fs21.readdir(dirPath,{withFileTypes:!0});for(let entry of entries){if(!entry.isFile())continue;let filePath=path45.join(dirPath,entry.name);try{let stat7=await fs21.stat(filePath);if(now-stat7.mtimeMs>cutoffMs)await fs21.unlink(filePath)}catch{}}}catch{}}var MAX_TRACKED_TRAJECTORY_SESSIONS=500,_inMemoryTrajectoryCache;var init_trajectory_store=__esm(()=>{init_utils2();init_logger();_inMemoryTrajectoryCache=new Map});import{existsSync as existsSync20,mkdirSync as mkdirSync16,readFileSync as readFileSync14,writeFileSync as writeFileSync8}from"node:fs";import*as path46 from"node:path";function recordSessionStart(directory,startMs){try{let swarmDir=path46.join(directory,".swarm"),sessionDir=path46.join(swarmDir,"session"),filePath=path46.join(sessionDir,SESSION_START_FILE),line=JSON.stringify({startMs,ts:Date.now()});mkdirSync16(sessionDir,{recursive:!0}),writeFileSync8(filePath,`${line}
|
|
646
646
|
`,{flag:"a"})}catch{}}function readEarliestSessionStart(directory){try{let filePath=path46.join(directory,".swarm","session",SESSION_START_FILE);if(!existsSync20(filePath))return null;let lines=readFileSync14(filePath,"utf-8").split(`
|
|
647
647
|
`),validStartMs=[];for(let line of lines){if(!line.trim())continue;try{let parsed=JSON.parse(line);if(typeof parsed.startMs==="number"&&Number.isFinite(parsed.startMs))validStartMs.push(parsed.startMs)}catch{}}if(validStartMs.length===0)return null;return new Date(Math.min(...validStartMs)).toISOString()}catch{return null}}var SESSION_START_FILE="session-start.jsonl";var init_session_start_store=()=>{};import{existsSync as existsSync21,lstatSync as lstatSync5,mkdirSync as mkdirSync17,readFileSync as readFileSync15,rmSync as rmSync3}from"node:fs";import*as os12 from"node:os";import*as path47 from"node:path";function resolveDataDir(){let platform=process.platform,home=process.env.HOME||os12.homedir();if(platform==="win32")return path47.join(process.env.LOCALAPPDATA||path47.join(home,"AppData","Local"),"opencode-swarm","Data");else if(platform==="darwin")return path47.join(home,"Library","Application Support","opencode-swarm");return path47.join(process.env.XDG_DATA_HOME||path47.join(home,".local","share"),"opencode-swarm")}function resolveLinkBaseDir(){return path47.join(resolveDataDir(),"links")}function resolveLinkDir(linkId){return path47.join(resolveLinkBaseDir(),linkId)}function sanitizeLinkId(name){if(typeof name!=="string")return null;let cleaned=name.trim().toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/-+/g,"-").replace(/^[-.]+|[-.]+$/g,"").slice(0,MAX_LINK_ID_LENGTH).replace(/[-.]+$/g,"");if(cleaned.length===0)return null;let base=cleaned.split(".")[0];if(WINDOWS_RESERVED_NAMES.has(base))return null;return cleaned}function resolveLinkPointerPath(directory){return path47.join(directory,".swarm",LINK_POINTER_FILENAME)}function readLinkPointer(directory){let pointerPath=resolveLinkPointerPath(directory);if(!existsSync21(pointerPath))return null;try{let raw=JSON.parse(readFileSync15(pointerPath,"utf-8"));if(!raw||typeof raw!=="object")return null;let obj=raw,linkId=obj.linkId;if(typeof linkId!=="string"||linkId.length===0)return null;let safeId=sanitizeLinkId(linkId);if(!safeId)return null;return{version:1,linkId:safeId,name:typeof obj.name==="string"?obj.name:void 0,createdAt:typeof obj.createdAt==="string"?obj.createdAt:new Date(0).toISOString(),source:obj.source==="auto"?"auto":"manual"}}catch{return null}}function getLinkedLocalKnowledgeStatus(directory){let localKnowledgePath=path47.join(directory,".swarm","knowledge.jsonl"),pointer=readLinkPointer(directory);if(!pointer)return{linked:!1,orphaned:!1,localKnowledgePath,resolvedKnowledgePath:localKnowledgePath,reason:"not_linked"};let resolvedKnowledgePath=path47.join(path47.resolve(resolveLinkDir(pointer.linkId)),"knowledge.jsonl");if(!existsSync21(localKnowledgePath))return{linked:!0,orphaned:!1,localKnowledgePath,resolvedKnowledgePath,reason:"local_missing"};try{if(lstatSync5(localKnowledgePath).isSymbolicLink())return{linked:!0,orphaned:!1,localKnowledgePath,resolvedKnowledgePath,reason:"local_symlink"}}catch{return{linked:!0,orphaned:!1,localKnowledgePath,resolvedKnowledgePath,reason:"local_missing"}}return{linked:!0,orphaned:!0,localKnowledgePath,resolvedKnowledgePath,reason:"local_regular_file"}}async function writeLinkPointer(directory,pointer){let swarmDir=path47.join(directory,".swarm");mkdirSync17(swarmDir,{recursive:!0});let pointerPath=resolveLinkPointerPath(directory);await atomicWriteFile(pointerPath,JSON.stringify(pointer,null,2)),invalidateKnowledgeStoreDirCache(directory)}async function removeLinkPointer(directory){let pointerPath=resolveLinkPointerPath(directory);try{rmSync3(pointerPath,{force:!0})}finally{invalidateKnowledgeStoreDirCache(directory)}}function resolveKnowledgeStoreDir(directory){let localSwarm=path47.join(directory,".swarm"),now=Date.now(),cached2=_resolutionCache.get(directory);if(cached2&&now<cached2.expires)return cached2.linkDir??localSwarm;let linkDir=null;try{let pointer=readLinkPointer(directory);if(pointer){linkDir=path47.resolve(resolveLinkDir(pointer.linkId));let orphanStatus=getLinkedLocalKnowledgeStatus(directory);if(orphanStatus.orphaned)warn("[knowledge-link] local knowledge file is orphaned by link store",{localKnowledgePath:orphanStatus.localKnowledgePath,resolvedKnowledgePath:orphanStatus.resolvedKnowledgePath})}}catch{linkDir=null}if(!_resolutionCache.has(directory)&&_resolutionCache.size>=MAX_CACHE_ENTRIES2){let oldest=_resolutionCache.keys().next().value;if(oldest!==void 0)_resolutionCache.delete(oldest)}return _resolutionCache.set(directory,{linkDir,expires:now+CACHE_TTL_MS}),linkDir??localSwarm}function invalidateKnowledgeStoreDirCache(directory){if(directory===void 0){_resolutionCache.clear();return}_resolutionCache.delete(directory)}function isLinked(directory){return readLinkPointer(directory)!==null}var LINK_POINTER_FILENAME="link.json",MAX_LINK_ID_LENGTH=64,WINDOWS_RESERVED_NAMES,CACHE_TTL_MS=2000,MAX_CACHE_ENTRIES2=500,_resolutionCache;var init_knowledge_link=__esm(()=>{init_task_file();init_logger();WINDOWS_RESERVED_NAMES=new Set(["con","prn","aux","nul","com0","com1","com2","com3","com4","com5","com6","com7","com8","com9","lpt0","lpt1","lpt2","lpt3","lpt4","lpt5","lpt6","lpt7","lpt8","lpt9"]);_resolutionCache=new Map});import{execFile as execFile2}from"node:child_process";function markSuggested(sessionId){if(_suggestedSessions.has(sessionId))return;if(_suggestedSessions.size>=MAX_SUGGESTED_SESSIONS){let oldest=_suggestedSessions.values().next().value;if(oldest!==void 0)_suggestedSessions.delete(oldest)}_suggestedSessions.add(sessionId)}function countWorktrees(directory){return new Promise((resolve25)=>{try{let child=execFile2("git",["-C",directory,"worktree","list","--porcelain"],{timeout:GIT_TIMEOUT_MS2,windowsHide:!0,encoding:"utf-8"},(err,stdout)=>{if(err||typeof stdout!=="string"){resolve25(0);return}let count=0;for(let line of stdout.split(`
|
|
648
|
-
`))if(line.startsWith("worktree "))count++;resolve25(count)});try{child.stdin?.end()}catch{}child.on("error",()=>resolve25(0))}catch{resolve25(0)}})}async function maybeSuggestWorktreeLink(directory,sessionId){try{if(!directory||!sessionId)return;if(_suggestedSessions.has(sessionId))return;if(markSuggested(sessionId),isLinked(directory))return;let worktrees=await countWorktrees(directory);if(worktrees>1)
|
|
648
|
+
`))if(line.startsWith("worktree "))count++;resolve25(count)});try{child.stdin?.end()}catch{}child.on("error",()=>resolve25(0))}catch{resolve25(0)}})}async function maybeSuggestWorktreeLink(directory,sessionId){try{if(!directory||!sessionId)return;if(_suggestedSessions.has(sessionId))return;if(markSuggested(sessionId),isLinked(directory))return;let worktrees=await countWorktrees(directory);if(worktrees>1)advisoryWarn(`[opencode-swarm] Detected ${worktrees} git worktrees of this repo. Run \`/swarm link\` in each to share swarm knowledge across them (or \`/swarm link <name>\` to share with similar projects).`)}catch{}}var GIT_TIMEOUT_MS2=1500,MAX_SUGGESTED_SESSIONS=500,_suggestedSessions;var init_worktree_link_suggestion=__esm(()=>{init_knowledge_link();init_warning_buffer();_suggestedSessions=new Set});class AgentRunContext{runId;activeToolCalls;activeAgent;delegationChains;agentSessions;environmentProfiles;toolAggregates;constructor(runId,toolAggregates){this.runId=runId,this.activeToolCalls=new Map,this.activeAgent=new Map,this.delegationChains=new Map,this.agentSessions=new Map,this.environmentProfiles=new Map,this.toolAggregates=toolAggregates}}var exports_pr_subscriptions={};__export(exports_pr_subscriptions,{updateSnapshot:()=>updateSnapshot,unsubscribe:()=>unsubscribe,sweepStale:()=>sweepStale,subscribe:()=>subscribe,setOnSubscriptionCreated:()=>setOnSubscriptionCreated,lookupByPr:()=>lookupByPr,listActive:()=>listActive,buildCorrelationId:()=>buildCorrelationId,PR_SUBSCRIPTIONS_FILE:()=>PR_SUBSCRIPTIONS_FILE});import*as fs22 from"node:fs";import*as path48 from"node:path";function setOnSubscriptionCreated(callback){onSubscriptionCreated=callback}function storePath2(directory){return validateSwarmPath(directory,PR_SUBSCRIPTIONS_FILE)}function ensureSwarmDir3(directory){fs22.mkdirSync(path48.resolve(directory,".swarm","pr-monitor"),{recursive:!0})}function buildCorrelationId(sessionID,repoFullName,prNumber){return`${sessionID}::${repoFullName}::${prNumber}`}function readAllRecords(directory){let raw;try{raw=fs22.readFileSync(storePath2(directory),"utf-8")}catch(err){if(err.code==="ENOENT")return[];return log(`[pr-monitor] readAllRecords failed: ${err instanceof Error?err.message:String(err)}`),[]}let folded=new Map;for(let line of raw.split(`
|
|
649
649
|
`)){let trimmed=line.trim();if(trimmed.length===0)continue;let parsedJson;try{parsedJson=JSON.parse(trimmed)}catch{continue}let result=RecordSchema2.safeParse(parsedJson);if(!result.success)continue;folded.set(result.data.correlationId,result.data)}return[...folded.values()]}function appendRecord2(directory,record2){let result=RecordSchema2.safeParse(record2);if(!result.success)throw Error(`Invalid subscription record: ${result.error.message}`);ensureSwarmDir3(directory),fs22.appendFileSync(storePath2(directory),`${JSON.stringify(record2)}
|
|
650
650
|
`,"utf-8")}async function subscribe(directory,input){if(!directory||directory.trim()==="")throw Error("directory is required");if(!input.sessionID||input.sessionID.trim()==="")throw Error("sessionID is required and must be non-empty");if(!input.repoFullName||input.repoFullName.trim()==="")throw Error("repoFullName is required and must be non-empty");if(!input.prUrl||input.prUrl.trim()==="")throw Error("prUrl is required and must be non-empty");if(!input.prNumber||!Number.isInteger(input.prNumber)||input.prNumber<=0)throw Error("prNumber is required and must be a positive integer");let correlationId=buildCorrelationId(input.sessionID,input.repoFullName,input.prNumber),now=Date.now();return withEvidenceLock(directory,PR_SUBSCRIPTIONS_FILE,STORE_LOCK_AGENT2,STORE_LOCK_TASK2,async()=>{let existing=readAllRecords(directory),match=existing.find((r)=>r.correlationId===correlationId&&r.status==="active");if(match)return onSubscriptionCreated?.(directory,match),match;if(input.maxSubscriptions!==void 0&&input.maxSubscriptions>0){let activeCount=existing.filter((r)=>r.status==="active").length;if(activeCount>=input.maxSubscriptions)throw Error(`PR subscription limit reached: ${activeCount}/${input.maxSubscriptions}`)}let record2={correlationId,sessionID:input.sessionID,prNumber:input.prNumber,repoFullName:input.repoFullName,prUrl:input.prUrl,lastCheckedAt:now,isWatching:!0,hasUnaddressedEvents:!1,status:"active",createdAt:now,updatedAt:now,errorCount:0};return appendRecord2(directory,record2),onSubscriptionCreated?.(directory,record2),record2})}async function unsubscribe(directory,correlationId){if(!correlationId)return null;return withEvidenceLock(directory,PR_SUBSCRIPTIONS_FILE,STORE_LOCK_AGENT2,STORE_LOCK_TASK2,async()=>{let match=readAllRecords(directory).find((r)=>r.correlationId===correlationId&&r.status==="active");if(!match)return null;let now=Date.now(),removed={...match,status:"removed",isWatching:!1,updatedAt:now};return appendRecord2(directory,removed),removed})}async function listActive(directory){return readAllRecords(directory).filter((r)=>r.status==="active")}async function lookupByPr(directory,repoFullName,prNumber){for(let record2 of readAllRecords(directory))if(record2.status==="active"&&record2.repoFullName===repoFullName&&record2.prNumber===prNumber)return record2;return null}async function updateSnapshot(directory,correlationId,updates){if(!correlationId)return null;return withEvidenceLock(directory,PR_SUBSCRIPTIONS_FILE,STORE_LOCK_AGENT2,STORE_LOCK_TASK2,async()=>{let match=readAllRecords(directory).find((r)=>r.correlationId===correlationId&&r.status==="active");if(!match)return null;let updated={...match,...updates,correlationId,sessionID:match.sessionID,repoFullName:match.repoFullName,prNumber:match.prNumber,prUrl:match.prUrl,createdAt:match.createdAt,updatedAt:Date.now()};return appendRecord2(directory,updated),updated})}async function sweepStale(directory,ttlDays,mergedPrs){if(!ttlDays||ttlDays<=0)return 0;let ttlMs=ttlDays*86400000,now=Date.now();try{return await withEvidenceLock(directory,PR_SUBSCRIPTIONS_FILE,STORE_LOCK_AGENT2,STORE_LOCK_TASK2,async()=>{let swept=0;for(let record2 of readAllRecords(directory)){if(record2.status!=="active")continue;let prKey=`${record2.repoFullName}::${record2.prNumber}`,isMerged=mergedPrs?.has(prKey)??!1,isStale=now-record2.updatedAt>ttlMs;if(isMerged){appendRecord2(directory,{...record2,status:"expired",isWatching:!1,updatedAt:now}),swept+=1,log(`[pr-monitor] Swept subscription: merged/closed: ${prKey}`);continue}if(isStale&&!record2.hasUnaddressedEvents)appendRecord2(directory,{...record2,status:"expired",isWatching:!1,updatedAt:now}),swept+=1,log(`[pr-monitor] Swept subscription: stale (TTL ${ttlDays}d): ${prKey}`)}return swept})}catch(err){return log(`[pr-monitor] sweepStale failed: ${err instanceof Error?err.message:String(err)}`),0}}var PR_SUBSCRIPTIONS_FILE="pr-monitor/subscriptions.jsonl",STORE_LOCK_AGENT2="pr-monitor",STORE_LOCK_TASK2="pr-subscriptions",onSubscriptionCreated=null,RecordSchema2;var init_pr_subscriptions=__esm(()=>{init_zod();init_lock();init_utils2();init_utils();RecordSchema2=exports_external.object({correlationId:exports_external.string().min(1),sessionID:exports_external.string().min(1),prNumber:exports_external.number().int().positive(),repoFullName:exports_external.string().regex(/^[^/]+\/[^/]+$/,"Must be owner/repo format"),prUrl:exports_external.string().min(1).regex(/^https:\/\/github\.com\/[^/]+\/[^/]+\/pull\/\d+$/,"Must be a valid GitHub PR URL"),headRefOid:exports_external.string().optional(),lastCheckedAt:exports_external.number(),lastCommentId:exports_external.string().optional(),lastCheckRunSet:exports_external.string().optional(),mergeableState:exports_external.string().optional(),mergeGroupRunStatus:exports_external.string().optional(),mergeGroupRunConclusion:exports_external.string().optional(),mergeGroupRunHtmlUrl:exports_external.string().optional(),isWatching:exports_external.boolean(),hasUnaddressedEvents:exports_external.boolean(),status:exports_external.enum(["active","removed","expired"]),createdAt:exports_external.number(),updatedAt:exports_external.number(),errorCount:exports_external.number().int().min(0),customPollIntervalSeconds:exports_external.number().int().positive().optional(),customFailureThreshold:exports_external.number().int().min(0).optional(),customCooldownSeconds:exports_external.number().int().min(0).optional()}).strict()});var exports_state={};__export(exports_state,{updateAgentEventTime:()=>updateAgentEventTime,sweepStaleSessions:()=>sweepStaleSessions,swarmState:()=>swarmState,startAgentSession:()=>startAgentSession,setSessionEnvironment:()=>setSessionEnvironment,setCriticalShownIds:()=>setCriticalShownIds,resetSwarmStatePreservingSingletons:()=>resetSwarmStatePreservingSingletons,resetSwarmState:()=>resetSwarmState,rehydrateSessionFromDisk:()=>rehydrateSessionFromDisk,rehydratePrSubscriptions:()=>rehydratePrSubscriptions,recordStageBCompletion:()=>recordStageBCompletion,recordPhaseAgentDispatch:()=>recordPhaseAgentDispatch,pruneOldWindows:()=>pruneOldWindows,maybeSweepStaleSessions:()=>maybeSweepStaleSessions,isCouncilGateActive:()=>isCouncilGateActive,hasBothStageBCompletions:()=>hasBothStageBCompletions,hasActiveTurboMode:()=>hasActiveTurboMode,hasActiveLeanTurbo:()=>hasActiveLeanTurbo,hasActiveFullAuto:()=>hasActiveFullAuto,hasActiveEpicMode:()=>hasActiveEpicMode,getTaskState:()=>getTaskState,getSessionEnvironment:()=>getSessionEnvironment,getRunContext:()=>getRunContext,getResolvedAutoProceed:()=>getResolvedAutoProceed,getAgentSession:()=>getAgentSession,getActiveWindow:()=>getActiveWindow,getActiveFullAutoSessionID:()=>getActiveFullAutoSessionID,ensureSessionEnvironment:()=>ensureSessionEnvironment,ensureAgentSession:()=>ensureAgentSession,endAgentSession:()=>endAgentSession,defaultRunContext:()=>defaultRunContext,clearCriticalShownIds:()=>clearCriticalShownIds,canAdvanceTaskState:()=>canAdvanceTaskState,buildRehydrationCache:()=>buildRehydrationCache,beginInvocation:()=>beginInvocation,applyRehydrationCache:()=>applyRehydrationCache,advanceTaskStateAndPersist:()=>advanceTaskStateAndPersist,advanceTaskState:()=>advanceTaskState,addKnowledgeAckDedup:()=>addKnowledgeAckDedup,_resetCouncilDisagreementWarnings:()=>_resetCouncilDisagreementWarnings,_internals:()=>_internals26,MAX_TRACKED_KNOWLEDGE_ACKS:()=>MAX_TRACKED_KNOWLEDGE_ACKS,MAX_TRACKED_CRITICAL_SHOWN:()=>MAX_TRACKED_CRITICAL_SHOWN,AgentRunContext:()=>AgentRunContext});import*as fs23 from"node:fs/promises";import*as path49 from"node:path";function getRunContext(runId){if(!runId)return defaultRunContext;return _runContexts.get(runId)??defaultRunContext}function resetSwarmState(){swarmState.activeToolCalls.clear(),swarmState.toolAggregates.clear(),swarmState.activeAgent.clear(),swarmState.delegationChains.clear(),swarmState.pendingEvents=0,swarmState.lastBudgetPct=0,swarmState.agentSessions.clear(),_lastIdleSweepAtMs=0,clearTrajectoryCache(),clearTrajectoryStepCounters(),swarmState.pendingRehydrations.clear(),swarmState.opencodeClient=null,swarmState.curatorInitAgentNames=[],swarmState.curatorPhaseAgentNames=[],swarmState.curatorPostmortemAgentNames=[],swarmState.curatorConsolidationAgentNames=[],swarmState.skillImproverAgentNames=[],swarmState.specWriterAgentNames=[],swarmState.currentCriticalShownIds.clear(),swarmState.knowledgeAckDedup.clear(),swarmState.generatedAgentNames=[],_rehydrationCache=null,swarmState.fullAutoEnabledInConfig=!1,swarmState.environmentProfiles.clear(),clearPendingCoderScope(),resetStandardWorktreeIsolationState(),resetRealtimeLearningNudgeState(),_councilDisagreementWarned.clear()}function resetSwarmStatePreservingSingletons(){let{opencodeClient:preservedOpencodeClient,fullAutoEnabledInConfig:preservedFullAutoEnabledInConfig,curatorInitAgentNames:preservedCuratorInitAgentNames,curatorPhaseAgentNames:preservedCuratorPhaseAgentNames,curatorPostmortemAgentNames:preservedCuratorPostmortemAgentNames,curatorConsolidationAgentNames:preservedCuratorConsolidationAgentNames,skillImproverAgentNames:preservedSkillImproverAgentNames,specWriterAgentNames:preservedSpecWriterAgentNames,generatedAgentNames:preservedGeneratedAgentNames}=swarmState;resetSwarmState(),swarmState.opencodeClient=preservedOpencodeClient,swarmState.fullAutoEnabledInConfig=preservedFullAutoEnabledInConfig,swarmState.curatorInitAgentNames=preservedCuratorInitAgentNames,swarmState.curatorPhaseAgentNames=preservedCuratorPhaseAgentNames,swarmState.curatorPostmortemAgentNames=preservedCuratorPostmortemAgentNames,swarmState.curatorConsolidationAgentNames=preservedCuratorConsolidationAgentNames,swarmState.skillImproverAgentNames=preservedSkillImproverAgentNames,swarmState.specWriterAgentNames=preservedSpecWriterAgentNames,swarmState.generatedAgentNames=preservedGeneratedAgentNames}function sweepStaleSessions(staleDurationMs=STALE_SESSION_TTL_MS,now=Date.now()){let staleIds=[];for(let[id,session]of swarmState.agentSessions)if(now-session.lastToolCallTime>staleDurationMs)staleIds.push(id);for(let id of staleIds)swarmState.agentSessions.delete(id),swarmState.delegationChains.delete(id);return staleIds}function maybeSweepStaleSessions(staleDurationMs=STALE_SESSION_TTL_MS,now=Date.now()){if(now-_lastIdleSweepAtMs<IDLE_SWEEP_COOLDOWN_MS)return[];return _lastIdleSweepAtMs=now,sweepStaleSessions(staleDurationMs,now)}function startAgentSession(sessionId,agentName,staleDurationMs=STALE_SESSION_TTL_MS,directory){let now=Date.now();sweepStaleSessions(staleDurationMs,now);let sessionState={agentName,lastToolCallTime:now,lastAgentEventTime:now,delegationActive:!1,activeInvocationId:0,lastInvocationIdByAgent:{},windows:{},lastCompactionHint:0,architectWriteCount:0,lastCoderDelegationTaskId:null,currentTaskId:null,gateLog:new Map,reviewerCallCount:new Map,lastGateFailure:null,partialGateWarningsIssuedForTask:new Set,selfFixAttempted:!1,selfCodingWarnedAtCount:0,catastrophicPhaseWarnings:new Set,lastPhaseCompleteTimestamp:0,lastPhaseCompletePhase:0,phaseAgentsDispatched:new Set,lastCompletedPhaseAgentsDispatched:new Set,qaSkipCount:0,qaSkipTaskIds:[],taskWorkflowStates:new Map,stageBCompletion:new Map,taskCouncilApproved:new Map,pendingCouncilRequirements:new Map,lastGateOutcome:null,declaredCoderScope:null,lastScopeViolation:null,scopeViolationDetected:!1,modifiedFilesThisCoderTask:[],turboMode:!1,turboStrategy:void 0,leanTurboActive:!1,leanTurboCurrentPhase:void 0,maxConcurrencyOverride:void 0,epicModeActive:!1,qaGateSessionOverrides:{},fullAutoMode:!1,fullAutoInteractionCount:0,fullAutoDeadlockCount:0,fullAutoLastQuestionHash:null,model_fallback_index:0,modelFallbackExhausted:!1,coderRevisions:0,revisionLimitHit:!1,loopDetectionWindow:[],pendingAdvisoryMessages:[],sessionRehydratedAt:0,prmPatternCounts:new Map,prmEscalationLevel:0,prmLastPatternDetected:null,prmTrajectoryStep:0,prmHardStopPending:!1,prSubscriptions:new Map};if(swarmState.agentSessions.set(sessionId,sessionState),directory){try{recordSessionStart(directory,now)}catch{}queueMicrotask(()=>{maybeSuggestWorktreeLink(directory,sessionId)})}if(telemetry.sessionStarted(sessionId,agentName),swarmState.activeAgent.set(sessionId,agentName),_internals26.applyRehydrationCache(sessionState),directory){let rehydrationPromise;rehydrationPromise=_internals26.rehydrateSessionFromDisk(directory,sessionState).then(async()=>{try{sessionState.prSubscriptions=await rehydratePrSubscriptions(sessionId,directory)}catch(err){warn("[state] PR subscription rehydration failed, starting with empty subscriptions:",err instanceof Error?err.message:String(err))}}).catch((err)=>{warn("[state] Rehydration failed:",err instanceof Error?err.message:String(err))}).finally(()=>{swarmState.pendingRehydrations.delete(rehydrationPromise)}),swarmState.pendingRehydrations.add(rehydrationPromise)}}function endAgentSession(sessionId){swarmState.agentSessions.delete(sessionId),clearRealtimeLearningNudgeSession(sessionId)}function getAgentSession(sessionId){return swarmState.agentSessions.get(sessionId)}function ensureAgentSession(sessionId,agentName,directory){let now=Date.now(),session=swarmState.agentSessions.get(sessionId);if(session){if(agentName&&agentName!==session.agentName){let oldName=session.agentName;if(session.agentName=agentName,telemetry.agentActivated(sessionId,agentName,oldName),session.delegationActive=!1,session.lastAgentEventTime=now,!session.windows)session.activeInvocationId=0,session.lastInvocationIdByAgent={},session.windows={}}if(!session.windows)session.activeInvocationId=0,session.lastInvocationIdByAgent={},session.windows={};if(session.lastCompactionHint===void 0)session.lastCompactionHint=0;if(session.architectWriteCount===void 0)session.architectWriteCount=0;if(session.lastCoderDelegationTaskId===void 0)session.lastCoderDelegationTaskId=null;if(session.currentTaskId===void 0)session.currentTaskId=null;if(!session.gateLog)session.gateLog=new Map;if(!session.reviewerCallCount)session.reviewerCallCount=new Map;if(session.lastGateFailure===void 0)session.lastGateFailure=null;if(!session.partialGateWarningsIssuedForTask)session.partialGateWarningsIssuedForTask=new Set;if(session.selfFixAttempted===void 0)session.selfFixAttempted=!1;if(session.selfCodingWarnedAtCount===void 0)session.selfCodingWarnedAtCount=0;if(!session.catastrophicPhaseWarnings)session.catastrophicPhaseWarnings=new Set;if(session.lastPhaseCompleteTimestamp===void 0)session.lastPhaseCompleteTimestamp=0;if(session.lastPhaseCompletePhase===void 0)session.lastPhaseCompletePhase=0;if(!session.phaseAgentsDispatched)session.phaseAgentsDispatched=new Set;if(!session.lastCompletedPhaseAgentsDispatched)session.lastCompletedPhaseAgentsDispatched=new Set;if(session.qaSkipCount===void 0)session.qaSkipCount=0;if(!session.qaSkipTaskIds)session.qaSkipTaskIds=[];if(!session.taskWorkflowStates)session.taskWorkflowStates=new Map;if(!session.stageBCompletion)session.stageBCompletion=new Map;if(!session.taskCouncilApproved)session.taskCouncilApproved=new Map;if(!session.pendingCouncilRequirements)session.pendingCouncilRequirements=new Map;if(session.lastGateOutcome===void 0)session.lastGateOutcome=null;if(session.declaredCoderScope===void 0)session.declaredCoderScope=null;if(session.lastScopeViolation===void 0)session.lastScopeViolation=null;if(session.modifiedFilesThisCoderTask===void 0)session.modifiedFilesThisCoderTask=[];if(session.scopeViolationDetected===void 0)session.scopeViolationDetected=!1;if(session.turboMode===void 0)session.turboMode=!1;if(session.turboStrategy===void 0)session.turboStrategy=void 0;if(session.leanTurboActive===void 0)session.leanTurboActive=!1;if(session.leanTurboCurrentPhase===void 0)session.leanTurboCurrentPhase=void 0;if(session.epicModeActive===void 0)session.epicModeActive=!1;if(session.qaGateSessionOverrides===void 0)session.qaGateSessionOverrides={};if(session.model_fallback_index===void 0)session.model_fallback_index=0;if(session.modelFallbackExhausted===void 0)session.modelFallbackExhausted=!1;if(session.loopDetectionWindow===void 0)session.loopDetectionWindow=[];if(session.pendingAdvisoryMessages===void 0)session.pendingAdvisoryMessages=[];if(session.coderRevisions===void 0)session.coderRevisions=0;if(session.revisionLimitHit===void 0)session.revisionLimitHit=!1;if(session.sessionRehydratedAt===void 0)session.sessionRehydratedAt=0;if(session.prmPatternCounts===void 0)session.prmPatternCounts=new Map;if(session.prmEscalationLevel===void 0)session.prmEscalationLevel=0;if(session.prmLastPatternDetected===void 0)session.prmLastPatternDetected=null;if(session.prmTrajectoryStep===void 0)session.prmTrajectoryStep=0;if(session.prmHardStopPending===void 0)session.prmHardStopPending=!1;if(!session.prSubscriptions)session.prSubscriptions=new Map;return session.lastToolCallTime=now,maybeSweepStaleSessions(),session}if(_internals26.startAgentSession(sessionId,agentName??"unknown",7200000,directory),session=swarmState.agentSessions.get(sessionId),!session)throw Error(`Failed to create guardrail session for ${sessionId}`);return session}function updateAgentEventTime(sessionId){let session=swarmState.agentSessions.get(sessionId);if(session)session.lastAgentEventTime=Date.now()}function beginInvocation(sessionId,agentName){let session=swarmState.agentSessions.get(sessionId);if(!session)throw Error(`Cannot begin invocation: session ${sessionId} does not exist`);let stripped=stripKnownSwarmPrefix(agentName);if(stripped===ORCHESTRATOR_NAME)return null;let newId=(session.lastInvocationIdByAgent[stripped]||0)+1;session.lastInvocationIdByAgent[stripped]=newId,session.activeInvocationId=newId;let now=Date.now(),window2={id:newId,agentName:stripped,startedAtMs:now,toolCalls:0,consecutiveErrors:0,hardLimitHit:!1,lastSuccessTimeMs:now,recentToolCalls:[],warningIssued:!1,warningReason:"",transientRetryCount:0},key=`${stripped}:${newId}`;return session.windows[key]=window2,pruneOldWindows(sessionId,86400000,50),telemetry.delegationBegin(sessionId,stripped,session.currentTaskId??"unknown"),window2}function getActiveWindow(sessionId){let session=swarmState.agentSessions.get(sessionId);if(!session||!session.windows)return;let key=`${stripKnownSwarmPrefix(session.agentName)}:${session.activeInvocationId}`;return session.windows[key]}function pruneOldWindows(sessionId,maxAgeMs=86400000,maxWindows=50){let session=swarmState.agentSessions.get(sessionId);if(!session||!session.windows)return;let now=Date.now(),toKeep=Object.entries(session.windows).filter(([_,window2])=>now-window2.startedAtMs<maxAgeMs).sort((a,b)=>b[1].startedAtMs-a[1].startedAtMs).slice(0,maxWindows);session.windows=Object.fromEntries(toKeep)}function recordPhaseAgentDispatch(sessionId,agentName){let session=swarmState.agentSessions.get(sessionId);if(!session)return;if(!session.phaseAgentsDispatched)session.phaseAgentsDispatched=new Set;let normalizedName=stripKnownSwarmPrefix(agentName);session.phaseAgentsDispatched.add(normalizedName)}function isValidTaskId2(taskId){if(taskId===null||taskId===void 0)return!1;if(typeof taskId!=="string")return!1;return taskId.trim().length>0}function advanceTaskState(session,taskId,newState,options,councilConfig){if(!isValidTaskId2(taskId))return;if(!session||!(session.taskWorkflowStates instanceof Map))throw Error("INVALID_SESSION: session.taskWorkflowStates must be a Map instance");let current=session.taskWorkflowStates.get(taskId)??"idle",currentIndex=STATE_ORDER.indexOf(current);if(STATE_ORDER.indexOf(newState)<=currentIndex)throw Error(`INVALID_TASK_STATE_TRANSITION: ${taskId} ${current} → ${newState}`);if(newState==="complete"&¤t!=="tests_run"){let councilEntry=session.taskCouncilApproved?.get(taskId),effectiveMinimum=councilConfig?.requireAllMembers?5:councilConfig?.minimumMembers??3,councilApproved=councilEntry?.verdict==="APPROVE"&&(councilEntry.quorumSize??0)>=effectiveMinimum,pastPreCheck=currentIndex>=STATE_ORDER.indexOf("pre_check_passed");if(!councilApproved||!pastPreCheck)throw Error(`INVALID_TASK_STATE_TRANSITION: ${taskId} cannot reach complete from ${current} — must pass through tests_run first (or have council APPROVE after pre_check)`)}if(session.taskWorkflowStates.set(taskId,newState),newState==="complete")session.stageBCompletion?.delete(taskId);if(options?.emitTelemetry!==!1)telemetry.taskStateChanged(options?.telemetrySessionId??session.agentName,taskId,newState,current)}function canAdvanceTaskState(session,taskId,newState,councilConfig){if(!isValidTaskId2(taskId))return!1;if(!session||!(session.taskWorkflowStates instanceof Map))return!1;let current=session.taskWorkflowStates.get(taskId)??"idle",currentIndex=STATE_ORDER.indexOf(current);if(STATE_ORDER.indexOf(newState)<=currentIndex)return!1;if(newState==="complete"&¤t!=="tests_run"){let councilEntry=session.taskCouncilApproved?.get(taskId),effectiveMinimum=councilConfig?.requireAllMembers?5:councilConfig?.minimumMembers??3,councilApproved=councilEntry?.verdict==="APPROVE"&&(councilEntry.quorumSize??0)>=effectiveMinimum,pastPreCheck=currentIndex>=STATE_ORDER.indexOf("pre_check_passed");if(!councilApproved||!pastPreCheck)return!1}return!0}async function advanceTaskStateAndPersist(session,taskId,newState,directory,options,councilConfig){if(newState==="coder_delegated"){if(await isTaskSettled(directory,taskId)){warn(`[advanceTaskStateAndPersist] refusing to re-dispatch settled task ${taskId}; skipping in-memory advance + persist`);return}}if(advanceTaskState(session,taskId,newState,options,councilConfig),newState!=="coder_delegated"&&newState!=="complete")return;let planStatus=newState==="complete"?"completed":"in_progress";try{await updateTaskStatus(directory,taskId,planStatus,{force:!1})}catch(err){warn(`[advanceTaskStateAndPersist] persist ${taskId} → ${planStatus} failed (in-memory state still advanced): ${err instanceof Error?err.message:String(err)}`)}}function getTaskState(session,taskId){if(!isValidTaskId2(taskId))return"idle";if(!session.taskWorkflowStates)session.taskWorkflowStates=new Map;return session.taskWorkflowStates.get(taskId)??"idle"}function recordStageBCompletion(session,taskId,agent){if(!isValidTaskId2(taskId))return;if(!session.stageBCompletion)session.stageBCompletion=new Map;let existing=session.stageBCompletion.get(taskId);if(existing)existing.add(agent);else session.stageBCompletion.set(taskId,new Set([agent]))}function hasBothStageBCompletions(session,taskId){if(!isValidTaskId2(taskId))return!1;let completions=session.stageBCompletion?.get(taskId);if(!completions)return!1;return completions.has("reviewer")&&completions.has("test_engineer")}async function isCouncilGateActive(directory,council,sessionOverrides={}){let enabled=council?.enabled===!0,plan=null;try{plan=await loadPlanJsonOnly(directory)}catch{plan=null}if(!plan)return!1;let planId=derivePlanId(plan),profile=null;try{profile=getProfile(directory,planId)}catch(err){let msg=err instanceof Error?err.message:String(err);if(!(msg.includes("SQLITE_CANTOPEN")||msg.includes("ENOENT")))warn(`[isCouncilGateActive] getProfile threw unexpectedly for plan ${planId}: ${msg}. Treating council as inactive.`);profile=null}if(!profile)return!1;let councilMode=getEffectiveGates(profile,sessionOverrides).council_mode===!0;if(enabled&&councilMode)return!0;if(enabled!==councilMode&&!_councilDisagreementWarned.has(planId))_councilDisagreementWarned.add(planId),warn(`[delegation-gate] Council mode mismatch for plan ${planId}: pluginConfig.council.enabled=${enabled}, QaGates.council_mode=${councilMode}. Falling back to Stage B (non-council) per-task advancement.`);return!1}function _resetCouncilDisagreementWarnings(){_councilDisagreementWarned.clear()}function planStatusToWorkflowState(status){switch(status){case"in_progress":return"coder_delegated";case"completed":return"complete";default:return"idle"}}function evidenceToWorkflowState(evidence){let gates=evidence.gates??{},requiredGates=evidence.required_gates??[];if(requiredGates.length>0){if(requiredGates.every((gate)=>gates[gate]!=null))return"complete"}if(gates.test_engineer!=null)return"tests_run";if(gates.reviewer!=null)return"reviewer_run";if(Object.keys(gates).length>0)return"coder_delegated";return"idle"}async function readPlanFromDisk(directory){try{let planPath=path49.join(directory,".swarm","plan.json"),content=await fs23.readFile(planPath,"utf-8"),parsed=JSON.parse(content);return PlanSchema.parse(parsed)}catch{return null}}async function readGateEvidenceFromDisk(directory){let evidenceMap=new Map;try{let evidenceDir=path49.join(directory,".swarm","evidence"),entries=await fs23.readdir(evidenceDir,{withFileTypes:!0});for(let entry of entries){if(!entry.isFile()||!entry.name.endsWith(".json"))continue;let taskId=entry.name.replace(/\.json$/,"");if(!/^\d+\.\d+(\.\d+)*$/.test(taskId))continue;try{let filePath=path49.join(evidenceDir,entry.name),content=await fs23.readFile(filePath,"utf-8"),parsed=JSON.parse(content);if(parsed&&typeof parsed.taskId==="string"&&Array.isArray(parsed.required_gates))evidenceMap.set(taskId,parsed)}catch{}}}catch{}return evidenceMap}async function buildRehydrationCache(directory){let planTaskStates=new Map,plan=await readPlanFromDisk(directory);if(plan)for(let phase of plan.phases??[])for(let task of phase.tasks??[])planTaskStates.set(task.id,planStatusToWorkflowState(task.status));let evidenceMap=await readGateEvidenceFromDisk(directory);_rehydrationCache={planTaskStates,evidenceMap}}function applyRehydrationCache(session){if(!_rehydrationCache)return;if(!session.taskWorkflowStates)session.taskWorkflowStates=new Map;if(!session.taskCouncilApproved)session.taskCouncilApproved=new Map;let{planTaskStates,evidenceMap}=_rehydrationCache;for(let[taskId,planState]of planTaskStates){let existingState=session.taskWorkflowStates.get(taskId),evidence=evidenceMap.get(taskId);if(evidence){let derivedState=evidenceToWorkflowState(evidence),existingIndex=existingState?STATE_ORDER.indexOf(existingState):-1;if(STATE_ORDER.indexOf(derivedState)>existingIndex)session.taskWorkflowStates.set(taskId,derivedState)}else{let existingIndex=existingState?STATE_ORDER.indexOf(existingState):-1;if(STATE_ORDER.indexOf(planState)>existingIndex)session.taskWorkflowStates.set(taskId,planState)}}let VALID_COUNCIL_VERDICTS=new Set(["APPROVE","REJECT","CONCERNS"]);for(let[taskId,evidence]of evidenceMap){if(session.taskCouncilApproved.has(taskId))continue;let council=evidence.gates?.council;if(!council)continue;let rawVerdict=council.verdict;if(!rawVerdict||typeof rawVerdict!=="string")continue;if(!VALID_COUNCIL_VERDICTS.has(rawVerdict))continue;let verdict=rawVerdict,roundNumber=council.roundNumber;if(typeof roundNumber!=="number"||!Number.isFinite(roundNumber))roundNumber=1;let rawQuorumSize=council.quorumSize,quorumSize=typeof rawQuorumSize==="number"&&Number.isFinite(rawQuorumSize)&&rawQuorumSize>=1?rawQuorumSize:1;session.taskCouncilApproved.set(taskId,{verdict,roundNumber,quorumSize})}}async function rehydrateSessionFromDisk(directory,session){await _internals26.buildRehydrationCache(directory),_internals26.applyRehydrationCache(session)}function hasActiveTurboMode(sessionID){if(sessionID)return swarmState.agentSessions.get(sessionID)?.turboMode===!0;for(let[_sessionId,session]of swarmState.agentSessions)if(session.turboMode===!0)return!0;return!1}function hasActiveFullAuto(sessionID){if(sessionID)return swarmState.agentSessions.get(sessionID)?.fullAutoMode===!0;for(let[_sessionId,session]of swarmState.agentSessions)if(session.fullAutoMode===!0)return!0;return!1}function getActiveFullAutoSessionID(){let activeId,activeLastToolCall=-1;for(let[id,session]of swarmState.agentSessions){if(session.fullAutoMode!==!0)continue;let lastToolCall=session.lastToolCallTime??0;if(activeId===void 0||lastToolCall>activeLastToolCall)activeId=id,activeLastToolCall=lastToolCall}return activeId}function hasActiveLeanTurbo(sessionID){if(sessionID){let session=swarmState.agentSessions.get(sessionID);return session?.turboMode===!0&&session?.turboStrategy==="lean"&&session?.leanTurboActive===!0}for(let[_sessionId,session]of swarmState.agentSessions)if(session.turboMode===!0&&session.turboStrategy==="lean"&&session.leanTurboActive===!0)return!0;return!1}function hasActiveEpicMode(sessionID){if(sessionID)return swarmState.agentSessions.get(sessionID)?.epicModeActive===!0;for(let[_sessionId,session]of swarmState.agentSessions)if(session.epicModeActive===!0)return!0;return!1}function getResolvedAutoProceed(session,planAutoProceed){return session.autoProceedOverride??planAutoProceed??!1}function setSessionEnvironment(sessionId,profile){swarmState.environmentProfiles.set(sessionId,profile)}function getSessionEnvironment(sessionId){return swarmState.environmentProfiles.get(sessionId)}function ensureSessionEnvironment(sessionId){let existing=swarmState.environmentProfiles.get(sessionId);if(existing)return existing;let profile=detectEnvironmentProfile();return swarmState.environmentProfiles.set(sessionId,profile),Promise.resolve().then(() => (init_telemetry(),exports_telemetry)).then(({telemetry:telemetry2})=>{telemetry2.environmentDetected(sessionId,profile.hostOS,profile.shellFamily,profile.executionMode)}).catch(()=>{}),profile}function setCriticalShownIds(sessionID,value){let map2=swarmState.currentCriticalShownIds;if(map2.has(sessionID))map2.delete(sessionID);if(map2.set(sessionID,value),map2.size>MAX_TRACKED_CRITICAL_SHOWN){let oldest=map2.keys().next().value;if(oldest!==void 0&&oldest!==sessionID)map2.delete(oldest)}}function clearCriticalShownIds(sessionID){return swarmState.currentCriticalShownIds.delete(sessionID)}function addKnowledgeAckDedup(key){let set2=swarmState.knowledgeAckDedup;if(set2.has(key))return;if(set2.add(key),set2.size>MAX_TRACKED_KNOWLEDGE_ACKS){let oldest=set2.values().next().value;if(oldest!==void 0)set2.delete(oldest)}}async function rehydratePrSubscriptions(sessionID,directory){let map2=new Map;try{let{listActive:listActive2}=await Promise.resolve().then(() => (init_pr_subscriptions(),exports_pr_subscriptions)),records=await listActive2(directory);for(let record2 of records){if(record2.sessionID!==sessionID)continue;let key=`${record2.repoFullName}::${record2.prNumber}`;map2.set(key,{prNumber:record2.prNumber,repoFullName:record2.repoFullName,prUrl:record2.prUrl,lastKnownStatus:record2.mergeableState??"unknown",lastPollTime:record2.lastCheckedAt,errorCount:record2.errorCount,isWatching:record2.isWatching})}}catch(err){warn(`[state] rehydratePrSubscriptions failed for session ${sessionID}: ${err instanceof Error?err.message:String(err)}`)}return map2}var _rehydrationCache=null,_councilDisagreementWarned,STATE_ORDER,_toolAggregates,defaultRunContext,_runContexts,swarmState,STALE_SESSION_TTL_MS=7200000,IDLE_SWEEP_COOLDOWN_MS=60000,_lastIdleSweepAtMs=0,MAX_TRACKED_CRITICAL_SHOWN=500,MAX_TRACKED_KNOWLEDGE_ACKS=5000,_internals26;var init_state2=__esm(()=>{init_constants();init_plan_schema();init_schema();init_qa_gate_profile();init_delegation_gate();init_realtime_learning_nudge();init_trajectory_step_state();init_manager();init_utils3();init_trajectory_store();init_session_start_store();init_worktree_link_suggestion();init_telemetry();init_logger();_councilDisagreementWarned=new Set,STATE_ORDER=["idle","coder_delegated","pre_check_passed","reviewer_run","tests_run","complete"],_toolAggregates=new Map,defaultRunContext=new AgentRunContext("default",_toolAggregates),_runContexts=new Map;swarmState={activeToolCalls:defaultRunContext.activeToolCalls,toolAggregates:defaultRunContext.toolAggregates,activeAgent:defaultRunContext.activeAgent,delegationChains:defaultRunContext.delegationChains,pendingEvents:0,opencodeClient:null,curatorInitAgentNames:[],curatorPhaseAgentNames:[],curatorPostmortemAgentNames:[],curatorConsolidationAgentNames:[],skillImproverAgentNames:[],specWriterAgentNames:[],currentCriticalShownIds:new Map,knowledgeAckDedup:new Set,generatedAgentNames:[],lastBudgetPct:0,agentSessions:defaultRunContext.agentSessions,pendingRehydrations:new Set,fullAutoEnabledInConfig:!1,environmentProfiles:defaultRunContext.environmentProfiles};_internals26={swarmState,resetSwarmState,ensureAgentSession,startAgentSession,getAgentSession,beginInvocation,getActiveWindow,advanceTaskState,getTaskState,hasActiveFullAuto,hasActiveTurboMode,hasActiveLeanTurbo,hasActiveEpicMode,buildRehydrationCache,applyRehydrationCache,rehydrateSessionFromDisk,isCouncilGateActive,defaultRunContext}});async function handleAutoProceedCommand(_directory,args2,sessionID){if(!sessionID||sessionID.trim()==="")return"Error: No active session context. Auto-proceed requires an active session. Use /swarm auto-proceed from within an OpenCode session, or start a session first.";let session=getAgentSession(sessionID);if(!session)return"Error: No active session. Auto-proceed requires an active session to operate.";if(stripKnownSwarmPrefix(session.agentName)!=="architect")return`Error: Auto-proceed can only be toggled from the architect session. Currently active session is: ${session.agentName}`;let arg=args2[0]?.toLowerCase(),wasUndefinedBefore=session.autoProceedOverride===void 0,newAutoProceedOverride;if(arg==="on")newAutoProceedOverride=!0;else if(arg==="off")newAutoProceedOverride=!1;else if(arg===void 0)newAutoProceedOverride=!session.autoProceedOverride;else return'Error: Invalid argument for /swarm auto-proceed. Valid options: "on", "off", or omit the argument to toggle.';if(session.autoProceedOverride=newAutoProceedOverride,arg==="on"||arg==="off"||arg===void 0&&wasUndefinedBefore)session.autoProceedNudgeDone=!0;if(newAutoProceedOverride)return"Auto-proceed is now ON. Phase boundaries will advance automatically.";else return"Auto-proceed is now OFF. You will be asked before advancing to the next phase."}var init_auto_proceed=__esm(()=>{init_schema();init_state2()});import*as fs24 from"node:fs";import*as os13 from"node:os";import*as path50 from"node:path";function buildDelegationCostFields(input={}){let extracted=extractUsageAndCost(input.raw),usage=extracted.usage,model=extracted.model??input.model,reportedCost=extracted.cost_usd;if(reportedCost!==null)return{...usage,cost_usd:roundUsd(reportedCost),cost_source:"reported",model,gate:input.gate,retry_index:input.retry_index};let estimated=estimateCostUsd(usage,model,input.pricing);if(estimated!==null)return{...usage,cost_usd:roundUsd(estimated),cost_source:"estimated",model,gate:input.gate,retry_index:input.retry_index};return{...usage,cost_usd:null,cost_source:"unavailable",model,gate:input.gate,retry_index:input.retry_index}}function summarizeTelemetryCosts(directory){let summary=createEmptySummary();for(let event of readTelemetryEvents(directory)){if(event.event!=="delegation_end")continue;addDelegationEvent(summary,event)}return finalizeSummary(summary)}function readTelemetryEvents(directory){let swarmDir=path50.join(directory,".swarm"),files=[path50.join(swarmDir,"telemetry.jsonl.1"),path50.join(swarmDir,"telemetry.jsonl")],tmpDir=fs24.mkdtempSync(path50.join(os13.tmpdir(),"telemetry-snapshot-")),snapshotFiles=[];try{for(let file2 of files){if(!fs24.existsSync(file2))continue;let snap=path50.join(tmpDir,path50.basename(file2));try{fs24.copyFileSync(file2,snap),snapshotFiles.push(snap)}catch{}}}catch{}let events=[];for(let file2 of snapshotFiles){let content="";try{content=fs24.readFileSync(file2,"utf-8")}catch{continue}for(let line of content.split(/\r?\n/)){let trimmed=line.trim();if(!trimmed)continue;try{let parsed=JSON.parse(trimmed);if(isRecord(parsed))events.push(parsed)}catch{}}}try{for(let f of snapshotFiles)try{fs24.unlinkSync(f)}catch{}fs24.rmdirSync(tmpDir)}catch{}return events}function estimateCostUsd(usage,model,pricing){if(!model)return null;let table={...BUNDLED_MODEL_PRICING,...pricing?.models??{}},entry=table[model]??table[model.toLowerCase()];if(!entry)return null;let cost=usage.tokens_input/1e6*entry.input_per_million+usage.tokens_output/1e6*entry.output_per_million+usage.tokens_reasoning/1e6*(entry.reasoning_per_million??entry.output_per_million)+usage.tokens_cache/1e6*(entry.cache_per_million??entry.input_per_million);return cost>0?cost:null}function extractUsageAndCost(raw){let candidates=collectCandidateRecords(raw),usage={...ZERO_USAGE},cost_usd=null,model;for(let candidate of candidates){model??=readModelIdentifier(candidate),cost_usd??=readNumber(candidate,["cost_usd","total_cost_usd","cost","totalCost"]);let directInput=readNumber(candidate,["tokens_input","input_tokens","input","prompt_tokens"]),directOutput=readNumber(candidate,["tokens_output","output_tokens","output","completion_tokens"]),directReasoning=readNumber(candidate,["tokens_reasoning","reasoning_tokens","reasoning"]),directCache=readNumber(candidate,["tokens_cache","cache_tokens","cache_read_input_tokens","cached_input_tokens","cache_write_input_tokens","cache"]),nestedCache=readCacheTokens(candidate);usage.tokens_input||=directInput??0,usage.tokens_output||=directOutput??0,usage.tokens_reasoning||=directReasoning??0,usage.tokens_cache||=directCache??nestedCache??0}return{usage,cost_usd,model}}function collectCandidateRecords(raw){let records=[],visit=(value,depth)=>{if(depth>3||!isRecord(value))return;records.push(value);for(let key of["usage","tokens","cache","cost","metadata","data","info","message","assistant","task","part","response","output"])visit(value[key],depth+1)};return visit(raw,0),records}function readNumber(record2,keys){for(let key of keys){let value=record2[key];if(typeof value==="number"&&Number.isFinite(value)&&value>=0)return value;if(typeof value==="string"&&value.trim()!==""){let parsed=Number(value);if(Number.isFinite(parsed)&&parsed>=0)return parsed}}return null}function readString(record2,keys){for(let key of keys){let value=record2[key];if(typeof value==="string"&&value.trim()!=="")return value.trim()}return}function readModelIdentifier(record2){let direct=readString(record2,["model","model_id"]);if(direct)return direct;let modelID=readString(record2,["modelID"]),providerID=readString(record2,["providerID"]);if(modelID&&providerID)return`${providerID}/${modelID}`;return modelID}function readCacheTokens(record2){let cacheRecord=isRecord(record2.cache)?record2.cache:record2,read=readNumber(cacheRecord,["read","cache_read_input_tokens"]),write=readNumber(cacheRecord,["write","cache_write_input_tokens","write_input_tokens"]);if(read===null&&write===null)return null;return(read??0)+(write??0)}function isRecord(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}function createEmptySummary(){return{total_cost_usd:0,total_reported_usd:0,total_estimated_usd:0,total_input_tokens:0,total_output_tokens:0,total_reasoning_tokens:0,total_cache_tokens:0,delegations:0,unavailable_delegations:0,by_agent:[],by_task:[],by_gate:[],by_retry:[],by_source:{reported:{delegations:0,cost_usd:0},estimated:{delegations:0,cost_usd:0},unavailable:{delegations:0,cost_usd:0}}}}function addDelegationEvent(summary,event){let costSource=parseCostSource(event.cost_source),cost=readNumber(event,["cost_usd"])??0,usage={tokens_input:readNumber(event,["tokens_input"])??0,tokens_output:readNumber(event,["tokens_output"])??0,tokens_reasoning:readNumber(event,["tokens_reasoning"])??0,tokens_cache:readNumber(event,["tokens_cache"])??0};if(summary.delegations++,summary.total_cost_usd+=cost,summary.total_input_tokens+=usage.tokens_input,summary.total_output_tokens+=usage.tokens_output,summary.total_reasoning_tokens+=usage.tokens_reasoning,summary.total_cache_tokens+=usage.tokens_cache,summary.by_source[costSource].delegations++,summary.by_source[costSource].cost_usd+=cost,costSource==="reported")summary.total_reported_usd+=cost;if(costSource==="estimated")summary.total_estimated_usd+=cost;if(costSource==="unavailable")summary.unavailable_delegations++;addRow(summary.by_agent,String(event.agentName??event.agent??"unknown"),{cost,costSource,usage}),addRow(summary.by_task,String(event.taskId??event.task_id??"unknown"),{cost,costSource,usage}),addRow(summary.by_gate,String(event.gate??"unknown"),{cost,costSource,usage}),addRow(summary.by_retry,String(readNumber(event,["retry_index","retryIndex"])??0),{cost,costSource,usage})}function addRow(rows,name,input){let row=rows.find((candidate)=>candidate.name===name);if(!row)row={name,delegations:0,cost_usd:0,input_tokens:0,output_tokens:0,reasoning_tokens:0,cache_tokens:0,unavailable_delegations:0},rows.push(row);if(row.delegations++,row.cost_usd+=input.cost,row.input_tokens+=input.usage.tokens_input,row.output_tokens+=input.usage.tokens_output,row.reasoning_tokens+=input.usage.tokens_reasoning,row.cache_tokens+=input.usage.tokens_cache,input.costSource==="unavailable")row.unavailable_delegations++}function finalizeSummary(summary){summary.total_cost_usd=roundUsd(summary.total_cost_usd),summary.total_reported_usd=roundUsd(summary.total_reported_usd),summary.total_estimated_usd=roundUsd(summary.total_estimated_usd);for(let source of Object.values(summary.by_source))source.cost_usd=roundUsd(source.cost_usd);for(let rows of[summary.by_agent,summary.by_task,summary.by_gate,summary.by_retry]){for(let row of rows)row.cost_usd=roundUsd(row.cost_usd);rows.sort((a,b)=>b.cost_usd-a.cost_usd||b.delegations-a.delegations)}return summary}function parseCostSource(value){return value==="reported"||value==="estimated"||value==="unavailable"?value:"unavailable"}function roundUsd(value){return Math.round(value*1e6)/1e6}var ZERO_USAGE,BUNDLED_MODEL_PRICING;var init_cost_accounting=__esm(()=>{ZERO_USAGE={tokens_input:0,tokens_output:0,tokens_reasoning:0,tokens_cache:0},BUNDLED_MODEL_PRICING={}});async function handleBenchmarkCommand(directory,args2){let cumulative=args2.includes("--cumulative");if(args2.includes("--ci-gate"))cumulative=!0;let maxCostUsd=parseMaxCostUsd(args2),mode=cumulative?"cumulative":"in-memory",costSummary=cumulative?summarizeTelemetryCosts(directory):void 0,agentMap=new Map;for(let[,s]of swarmState.agentSessions){let e=agentMap.get(s.agentName)||{toolCalls:0,hardLimits:0,warnings:0},windows=Object.values(s.windows);e.toolCalls+=windows.reduce((sum,w)=>sum+w.toolCalls,0),e.hardLimits+=windows.filter((w)=>w.hardLimitHit).length,e.warnings+=windows.filter((w)=>w.warningIssued).length,agentMap.set(s.agentName,e)}let agentHealth=Array.from(agentMap.entries()).map(([a,v])=>({agent:a,...v})),toolPerf=[];for(let[,a]of swarmState.toolAggregates){let successRate=a.count?a.successCount/a.count*100:0;toolPerf.push({tool:a.tool,calls:a.count,successRate:Math.round(successRate*10)/10,avg:a.count?Math.round(a.totalDuration/a.count):0})}toolPerf.sort((a,b)=>b.calls-a.calls);let delegationCount=0;for(let c of swarmState.delegationChains.values())delegationCount+=c.length;let quality,qualityMetrics;if(cumulative){let reviewPasses=0,reviewFails=0,testPasses=0,testFails=0,additions=0,deletions=0,totalComplexityDelta=0,totalPublicApiDelta=0,totalDuplicationRatio=0,totalTestToCodeRatio=0,qualityEvidenceCount=0;for(let tid of await listEvidenceTaskIds(directory)){let result;try{result=await loadEvidence(directory,tid)}catch(_evidenceErr){warn("benchmark: skipping corrupt or unreadable evidence for task",tid);continue}if(result.status!=="found")continue;for(let e of result.bundle.entries){if(!isValidEvidenceType(e.type)){warn(`Unknown evidence type '${e.type}' in task ${tid}, skipping`);continue}if(e.type==="review"){if(e.verdict==="approved")reviewPasses++;else if(e.verdict==="rejected")reviewFails++}else if(e.type==="test")testPasses+=e.tests_passed,testFails+=e.tests_failed;else if(e.type==="diff")additions+=e.additions,deletions+=e.deletions;else if(e.type==="quality_budget"){let qe=e;totalComplexityDelta+=qe.metrics.complexity_delta,totalPublicApiDelta+=qe.metrics.public_api_delta,totalDuplicationRatio+=qe.metrics.duplication_ratio*100,totalTestToCodeRatio+=qe.metrics.test_to_code_ratio*100,qualityEvidenceCount++}}}let totalReviews=reviewPasses+reviewFails,totalTests=testPasses+testFails;if(quality={reviewPassRate:totalReviews?Math.round(reviewPasses/totalReviews*1000)/10:null,testPassRate:totalTests?Math.round(testPasses/totalTests*1000)/10:null,totalReviews,testsPassed:testPasses,testsFailed:testFails,additions,deletions},qualityEvidenceCount>0)qualityMetrics={complexityDelta:Math.round(totalComplexityDelta/qualityEvidenceCount*10)/10,publicApiDelta:Math.round(totalPublicApiDelta/qualityEvidenceCount*10)/10,duplicationRatio:Math.round(totalDuplicationRatio/qualityEvidenceCount*10)/10,testToCodeRatio:Math.round(totalTestToCodeRatio/qualityEvidenceCount*10)/10,thresholds:{maxComplexityDelta:CI.max_complexity_delta,maxPublicApiDelta:CI.max_public_api_delta,maxDuplicationRatio:CI.max_duplication_ratio,minTestToCodeRatio:CI.min_test_to_code_ratio},hasEvidence:!0};else qualityMetrics={complexityDelta:0,publicApiDelta:0,duplicationRatio:0,testToCodeRatio:0,thresholds:{maxComplexityDelta:CI.max_complexity_delta,maxPublicApiDelta:CI.max_public_api_delta,maxDuplicationRatio:CI.max_duplication_ratio,minTestToCodeRatio:CI.min_test_to_code_ratio},hasEvidence:!1}}let ciGate;if(args2.includes("--ci-gate")){let totalCalls=0,totalFailures=0;for(let[,a]of swarmState.toolAggregates)totalCalls+=a.count,totalFailures+=a.failureCount;let agentErrorRate=totalCalls?totalFailures/totalCalls*100:0,maxHardLimits=0;for(let v of agentMap.values())if(v.hardLimits>maxHardLimits)maxHardLimits=v.hardLimits;let hasQualityEvidence=qualityMetrics?.hasEvidence??!1,complexityDelta=qualityMetrics?.complexityDelta??0,publicApiDelta=qualityMetrics?.publicApiDelta??0,duplicationRatio=qualityMetrics?.duplicationRatio??0,testToCodeRatio=qualityMetrics?.testToCodeRatio??0,checks3=[{name:"Review pass rate",value:quality?.reviewPassRate??0,threshold:CI.review_pass_rate,operator:">=",passed:(quality?.reviewPassRate??0)>=CI.review_pass_rate},{name:"Test pass rate",value:quality?.testPassRate??0,threshold:CI.test_pass_rate,operator:">=",passed:(quality?.testPassRate??0)>=CI.test_pass_rate},{name:"Agent error rate",value:Math.round(agentErrorRate*10)/10,threshold:CI.max_agent_error_rate,operator:"<=",passed:agentErrorRate<=CI.max_agent_error_rate},{name:"Hard limit hits",value:maxHardLimits,threshold:CI.max_hard_limit_hits,operator:"<=",passed:maxHardLimits<=CI.max_hard_limit_hits},{name:"Complexity Delta",value:complexityDelta,threshold:CI.max_complexity_delta,operator:"<=",passed:!hasQualityEvidence||complexityDelta<=CI.max_complexity_delta},{name:"Public API Delta",value:publicApiDelta,threshold:CI.max_public_api_delta,operator:"<=",passed:!hasQualityEvidence||publicApiDelta<=CI.max_public_api_delta},{name:"Duplication Ratio",value:duplicationRatio,threshold:CI.max_duplication_ratio,operator:"<=",passed:!hasQualityEvidence||duplicationRatio<=CI.max_duplication_ratio},{name:"Test-to-Code Ratio",value:testToCodeRatio,threshold:CI.min_test_to_code_ratio,operator:">=",passed:!hasQualityEvidence||testToCodeRatio>=CI.min_test_to_code_ratio}];if(maxCostUsd!==null)checks3.push({name:"Total cost",value:costSummary?.total_cost_usd??0,threshold:maxCostUsd,operator:"<=",passed:(costSummary?.total_cost_usd??0)<=maxCostUsd});ciGate={passed:checks3.every((c)=>c.passed),checks:checks3}}let lines=[`## Swarm Benchmark (mode: ${mode})`,"","### Agent Health"];if(!agentHealth.length)lines.push("No agent sessions recorded");else for(let{agent,toolCalls,hardLimits,warnings}of agentHealth){let parts=[`${toolCalls} tool calls`];if(warnings>0)parts.push(`${warnings} warning${warnings>1?"s":""}`);parts.push(hardLimits?`${hardLimits} hard limit hit${hardLimits>1?"s":""}`:"0 hard limits"),lines.push(`- ${hardLimits?"⚠️":"✅"} **${agent}**: ${parts.join(", ")}`)}if(lines.push("","### Tool Performance"),!toolPerf.length)lines.push("No tool data recorded");else{lines.push("| Tool | Calls | Success Rate | Avg Duration |","|------|-------|-------------|-------------|");for(let{tool,calls,successRate,avg}of toolPerf)lines.push(`| ${tool} | ${calls} | ${successRate}% | ${avg}ms |`)}if(lines.push("","### Delegations",delegationCount?`Total: ${delegationCount} delegations`:"No delegations recorded",""),quality){if(lines.push("### Quality Signals"),!quality.totalReviews&&!quality.testsPassed&&!quality.additions)lines.push("No evidence data found");else{if(quality.reviewPassRate!==null)lines.push(`- Review pass rate: ${quality.reviewPassRate}% (${quality.totalReviews}) ${quality.reviewPassRate>=70?"✅":"❌"}`);else lines.push("- Review pass rate: N/A (no reviews)");if(quality.testPassRate!==null)lines.push(`- Test pass rate: ${quality.testPassRate}% (${quality.testsPassed}/${quality.testsPassed+quality.testsFailed}) ${quality.testPassRate>=80?"✅":"❌"}`);else lines.push("- Test pass rate: N/A (no tests)");lines.push(`- Code churn: +${quality.additions} / -${quality.deletions} lines`)}lines.push("")}if(qualityMetrics?.hasEvidence)lines.push("### Quality Metrics"),lines.push(`- Complexity Delta: ${qualityMetrics.complexityDelta} (max: ${qualityMetrics.thresholds.maxComplexityDelta}) ${qualityMetrics.complexityDelta<=qualityMetrics.thresholds.maxComplexityDelta?"✅":"❌"}`),lines.push(`- Public API Delta: ${qualityMetrics.publicApiDelta} (max: ${qualityMetrics.thresholds.maxPublicApiDelta}) ${qualityMetrics.publicApiDelta<=qualityMetrics.thresholds.maxPublicApiDelta?"✅":"❌"}`),lines.push(`- Duplication Ratio: ${qualityMetrics.duplicationRatio}% (max: ${qualityMetrics.thresholds.maxDuplicationRatio}%) ${qualityMetrics.duplicationRatio<=qualityMetrics.thresholds.maxDuplicationRatio?"✅":"❌"}`),lines.push(`- Test-to-Code Ratio: ${qualityMetrics.testToCodeRatio}% (min: ${qualityMetrics.thresholds.minTestToCodeRatio}%) ${qualityMetrics.testToCodeRatio>=qualityMetrics.thresholds.minTestToCodeRatio?"✅":"❌"}`),lines.push("");if(costSummary)lines.push("### Cost Signals"),lines.push(`- Total tracked cost: $${costSummary.total_cost_usd.toFixed(6)} (${costSummary.delegations} delegations)`,`- Reported: $${costSummary.total_reported_usd.toFixed(6)}; estimated: $${costSummary.total_estimated_usd.toFixed(6)}; unavailable: ${costSummary.unavailable_delegations}`),lines.push("");if(ciGate){lines.push("### CI Gate",ciGate.passed?"✅ PASSED":"❌ FAILED");for(let c of ciGate.checks){let valueStr;if(c.name==="Complexity Delta"||c.name==="Public API Delta")valueStr=`${c.value}`;else if(c.name==="Total cost")valueStr=`$${c.value.toFixed(6)}`;else valueStr=`${c.value}%`;let thresholdStr=c.name==="Complexity Delta"||c.name==="Public API Delta"?`${c.threshold}`:c.name==="Total cost"?`$${c.threshold.toFixed(6)}`:`${c.threshold}%`;lines.push(`- ${c.name}: ${valueStr} ${c.operator} ${thresholdStr} ${c.passed?"✅":"❌"}`)}lines.push("")}let json2={mode,timestamp:new Date().toISOString(),agent_health:agentHealth.map((a)=>({agent:a.agent,tool_calls:a.toolCalls,hard_limit_hits:a.hardLimits,warnings:a.warnings})),tool_performance:toolPerf.map((t)=>({tool:t.tool,calls:t.calls,success_rate:t.successRate,avg_duration_ms:t.avg})),delegations:delegationCount};if(quality)json2.quality={review_pass_rate:quality.reviewPassRate,test_pass_rate:quality.testPassRate,total_reviews:quality.totalReviews,total_tests_passed:quality.testsPassed,total_tests_failed:quality.testsFailed,additions:quality.additions,deletions:quality.deletions};if(qualityMetrics)json2.quality_metrics={complexity_delta:qualityMetrics.complexityDelta,public_api_delta:qualityMetrics.publicApiDelta,duplication_ratio:qualityMetrics.duplicationRatio,test_to_code_ratio:qualityMetrics.testToCodeRatio,thresholds:qualityMetrics.thresholds,has_evidence:qualityMetrics.hasEvidence};if(costSummary)json2.costs={total_cost_usd:costSummary.total_cost_usd,total_reported_usd:costSummary.total_reported_usd,total_estimated_usd:costSummary.total_estimated_usd,total_input_tokens:costSummary.total_input_tokens,total_output_tokens:costSummary.total_output_tokens,total_reasoning_tokens:costSummary.total_reasoning_tokens,total_cache_tokens:costSummary.total_cache_tokens,delegations:costSummary.delegations,unavailable_delegations:costSummary.unavailable_delegations};if(ciGate)json2.ci_gate={passed:ciGate.passed,checks:ciGate.checks.map((c)=>({name:c.name,value:c.value,threshold:c.threshold,operator:c.operator,passed:c.passed}))};return lines.push("[BENCHMARK_JSON]",JSON.stringify(json2,null,2),"[/BENCHMARK_JSON]"),lines.join(`
|
|
651
651
|
`)}function parseMaxCostUsd(args2){let index=args2.indexOf("--max-cost-usd");if(index===-1)return null;let raw=args2[index+1];if(!raw||raw.startsWith("--"))throw Error("Invalid --max-cost-usd value: expected a non-negative number.");let parsed=Number(raw);if(!Number.isFinite(parsed)||parsed<0)throw Error("Invalid --max-cost-usd value: expected a non-negative number.");return parsed}var CI;var init_benchmark=__esm(()=>{init_manager2();init_cost_accounting();init_state2();init_utils();CI={review_pass_rate:70,test_pass_rate:80,max_agent_error_rate:20,max_hard_limit_hits:1,max_complexity_delta:5,max_public_api_delta:10,max_duplication_ratio:5,min_test_to_code_ratio:30}});function sanitizeTopic(raw){let normalized=raw.replace(/\s+/g," ").trim().replace(/\[\s*MODE\s*:[^\]]*\]/gi,"").replace(/\s+/g," ").trim(),MAX_TOPIC_LEN=2000;if(normalized.length<=2000)return normalized;return`${normalized.slice(0,2000)}…`}async function handleBrainstormCommand(_directory,args2){let description=sanitizeTopic(args2.join(" "));if(description)return`[MODE: BRAINSTORM] ${description}`;return"[MODE: BRAINSTORM] Please enter MODE: BRAINSTORM and begin the structured brainstorm workflow (CONTEXT SCAN → DIALOGUE → APPROACHES → DESIGN SECTIONS → SPEC WRITE + SELF-REVIEW → QA GATE SELECTION → TRANSITION)."}function $constructor2(name,initializer3,params){function init(inst,def){var _a2;Object.defineProperty(inst,"_zod",{value:inst._zod??{},enumerable:!1}),(_a2=inst._zod).traits??(_a2.traits=new Set),inst._zod.traits.add(name),initializer3(inst,def);for(let k in _.prototype)if(!(k in inst))Object.defineProperty(inst,k,{value:_.prototype[k].bind(inst)});inst._zod.constr=_,inst._zod.def=def}let Parent=params?.Parent??Object;class Definition extends Parent{}Object.defineProperty(Definition,"name",{value:name});function _(def){var _a2;let inst=params?.Parent?new Definition:this;init(inst,def),(_a2=inst._zod).deferred??(_a2.deferred=[]);for(let fn2 of inst._zod.deferred)fn2();return inst}return Object.defineProperty(_,"init",{value:init}),Object.defineProperty(_,Symbol.hasInstance,{value:(inst)=>{if(params?.Parent&&inst instanceof params.Parent)return!0;return inst?._zod?.traits?.has(name)}}),Object.defineProperty(_,"name",{value:name}),_}function config2(newConfig){if(newConfig)Object.assign(globalConfig2,newConfig);return globalConfig2}var NEVER2,$brand2,$ZodAsyncError2,$ZodEncodeError2,globalConfig2;var init_core4=__esm(()=>{NEVER2=Object.freeze({status:"aborted"});$brand2=Symbol("zod_brand");$ZodAsyncError2=class $ZodAsyncError2 extends Error{constructor(){super("Encountered Promise during synchronous parse. Use .parseAsync() instead.")}};$ZodEncodeError2=class $ZodEncodeError2 extends Error{constructor(name){super(`Encountered unidirectional transform during encode: ${name}`);this.name="ZodEncodeError"}};globalConfig2={}});var exports_util2={};__export(exports_util2,{unwrapMessage:()=>unwrapMessage2,uint8ArrayToHex:()=>uint8ArrayToHex2,uint8ArrayToBase64url:()=>uint8ArrayToBase64url2,uint8ArrayToBase64:()=>uint8ArrayToBase642,stringifyPrimitive:()=>stringifyPrimitive2,shallowClone:()=>shallowClone2,safeExtend:()=>safeExtend2,required:()=>required2,randomString:()=>randomString2,propertyKeyTypes:()=>propertyKeyTypes2,promiseAllObject:()=>promiseAllObject2,primitiveTypes:()=>primitiveTypes2,prefixIssues:()=>prefixIssues2,pick:()=>pick2,partial:()=>partial2,optionalKeys:()=>optionalKeys2,omit:()=>omit2,objectClone:()=>objectClone2,numKeys:()=>numKeys2,nullish:()=>nullish3,normalizeParams:()=>normalizeParams2,mergeDefs:()=>mergeDefs2,merge:()=>merge2,jsonStringifyReplacer:()=>jsonStringifyReplacer2,joinValues:()=>joinValues2,issue:()=>issue2,isPlainObject:()=>isPlainObject4,isObject:()=>isObject2,hexToUint8Array:()=>hexToUint8Array2,getSizableOrigin:()=>getSizableOrigin2,getParsedType:()=>getParsedType2,getLengthableOrigin:()=>getLengthableOrigin2,getEnumValues:()=>getEnumValues2,getElementAtPath:()=>getElementAtPath2,floatSafeRemainder:()=>floatSafeRemainder2,finalizeIssue:()=>finalizeIssue2,extend:()=>extend2,escapeRegex:()=>escapeRegex3,esc:()=>esc2,defineLazy:()=>defineLazy2,createTransparentProxy:()=>createTransparentProxy2,cloneDef:()=>cloneDef2,clone:()=>clone2,cleanRegex:()=>cleanRegex2,cleanEnum:()=>cleanEnum2,captureStackTrace:()=>captureStackTrace2,cached:()=>cached2,base64urlToUint8Array:()=>base64urlToUint8Array2,base64ToUint8Array:()=>base64ToUint8Array2,assignProp:()=>assignProp2,assertNotEqual:()=>assertNotEqual2,assertNever:()=>assertNever2,assertIs:()=>assertIs2,assertEqual:()=>assertEqual2,assert:()=>assert2,allowsEval:()=>allowsEval2,aborted:()=>aborted2,NUMBER_FORMAT_RANGES:()=>NUMBER_FORMAT_RANGES2,Class:()=>Class2,BIGINT_FORMAT_RANGES:()=>BIGINT_FORMAT_RANGES2});function assertEqual2(val){return val}function assertNotEqual2(val){return val}function assertIs2(_arg){}function assertNever2(_x){throw Error()}function assert2(_){}function getEnumValues2(entries){let numericValues=Object.values(entries).filter((v)=>typeof v==="number");return Object.entries(entries).filter(([k,_])=>numericValues.indexOf(+k)===-1).map(([_,v])=>v)}function joinValues2(array2,separator="|"){return array2.map((val)=>stringifyPrimitive2(val)).join(separator)}function jsonStringifyReplacer2(_,value){if(typeof value==="bigint")return value.toString();return value}function cached2(getter){return{get value(){{let value=getter();return Object.defineProperty(this,"value",{value}),value}throw Error("cached value already set")}}}function nullish3(input){return input===null||input===void 0}function cleanRegex2(source){let start=source.startsWith("^")?1:0,end=source.endsWith("$")?source.length-1:source.length;return source.slice(start,end)}function floatSafeRemainder2(val,step){let valDecCount=(val.toString().split(".")[1]||"").length,stepString=step.toString(),stepDecCount=(stepString.split(".")[1]||"").length;if(stepDecCount===0&&/\d?e-\d?/.test(stepString)){let match=stepString.match(/\d?e-(\d?)/);if(match?.[1])stepDecCount=Number.parseInt(match[1])}let decCount=valDecCount>stepDecCount?valDecCount:stepDecCount,valInt=Number.parseInt(val.toFixed(decCount).replace(".","")),stepInt=Number.parseInt(step.toFixed(decCount).replace(".",""));return valInt%stepInt/10**decCount}function defineLazy2(object2,key,getter){let value=void 0;Object.defineProperty(object2,key,{get(){if(value===EVALUATING2)return;if(value===void 0)value=EVALUATING2,value=getter();return value},set(v){Object.defineProperty(object2,key,{value:v})},configurable:!0})}function objectClone2(obj){return Object.create(Object.getPrototypeOf(obj),Object.getOwnPropertyDescriptors(obj))}function assignProp2(target,prop,value){Object.defineProperty(target,prop,{value,writable:!0,enumerable:!0,configurable:!0})}function mergeDefs2(...defs){let mergedDescriptors={};for(let def of defs){let descriptors=Object.getOwnPropertyDescriptors(def);Object.assign(mergedDescriptors,descriptors)}return Object.defineProperties({},mergedDescriptors)}function cloneDef2(schema){return mergeDefs2(schema._zod.def)}function getElementAtPath2(obj,path51){if(!path51)return obj;return path51.reduce((acc,key)=>acc?.[key],obj)}function promiseAllObject2(promisesObj){let keys=Object.keys(promisesObj),promises4=keys.map((key)=>promisesObj[key]);return Promise.all(promises4).then((results)=>{let resolvedObj={};for(let i=0;i<keys.length;i++)resolvedObj[keys[i]]=results[i];return resolvedObj})}function randomString2(length=10){let str="";for(let i=0;i<length;i++)str+="abcdefghijklmnopqrstuvwxyz"[Math.floor(Math.random()*26)];return str}function esc2(str){return JSON.stringify(str)}function isObject2(data){return typeof data==="object"&&data!==null&&!Array.isArray(data)}function isPlainObject4(o){if(isObject2(o)===!1)return!1;let ctor=o.constructor;if(ctor===void 0)return!0;let prot=ctor.prototype;if(isObject2(prot)===!1)return!1;if(Object.prototype.hasOwnProperty.call(prot,"isPrototypeOf")===!1)return!1;return!0}function shallowClone2(o){if(isPlainObject4(o))return{...o};if(Array.isArray(o))return[...o];return o}function numKeys2(data){let keyCount=0;for(let key in data)if(Object.prototype.hasOwnProperty.call(data,key))keyCount++;return keyCount}function escapeRegex3(str){return str.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function clone2(inst,def,params){let cl=new inst._zod.constr(def??inst._zod.def);if(!def||params?.parent)cl._zod.parent=inst;return cl}function normalizeParams2(_params){let params=_params;if(!params)return{};if(typeof params==="string")return{error:()=>params};if(params?.message!==void 0){if(params?.error!==void 0)throw Error("Cannot specify both `message` and `error` params");params.error=params.message}if(delete params.message,typeof params.error==="string")return{...params,error:()=>params.error};return params}function createTransparentProxy2(getter){let target;return new Proxy({},{get(_,prop,receiver){return target??(target=getter()),Reflect.get(target,prop,receiver)},set(_,prop,value,receiver){return target??(target=getter()),Reflect.set(target,prop,value,receiver)},has(_,prop){return target??(target=getter()),Reflect.has(target,prop)},deleteProperty(_,prop){return target??(target=getter()),Reflect.deleteProperty(target,prop)},ownKeys(_){return target??(target=getter()),Reflect.ownKeys(target)},getOwnPropertyDescriptor(_,prop){return target??(target=getter()),Reflect.getOwnPropertyDescriptor(target,prop)},defineProperty(_,prop,descriptor){return target??(target=getter()),Reflect.defineProperty(target,prop,descriptor)}})}function stringifyPrimitive2(value){if(typeof value==="bigint")return value.toString()+"n";if(typeof value==="string")return`"${value}"`;return`${value}`}function optionalKeys2(shape){return Object.keys(shape).filter((k)=>{return shape[k]._zod.optin==="optional"&&shape[k]._zod.optout==="optional"})}function pick2(schema,mask){let currDef=schema._zod.def,def=mergeDefs2(schema._zod.def,{get shape(){let newShape={};for(let key in mask){if(!(key in currDef.shape))throw Error(`Unrecognized key: "${key}"`);if(!mask[key])continue;newShape[key]=currDef.shape[key]}return assignProp2(this,"shape",newShape),newShape},checks:[]});return clone2(schema,def)}function omit2(schema,mask){let currDef=schema._zod.def,def=mergeDefs2(schema._zod.def,{get shape(){let newShape={...schema._zod.def.shape};for(let key in mask){if(!(key in currDef.shape))throw Error(`Unrecognized key: "${key}"`);if(!mask[key])continue;delete newShape[key]}return assignProp2(this,"shape",newShape),newShape},checks:[]});return clone2(schema,def)}function extend2(schema,shape){if(!isPlainObject4(shape))throw Error("Invalid input to extend: expected a plain object");let checks3=schema._zod.def.checks;if(checks3&&checks3.length>0)throw Error("Object schemas containing refinements cannot be extended. Use `.safeExtend()` instead.");let def=mergeDefs2(schema._zod.def,{get shape(){let _shape={...schema._zod.def.shape,...shape};return assignProp2(this,"shape",_shape),_shape},checks:[]});return clone2(schema,def)}function safeExtend2(schema,shape){if(!isPlainObject4(shape))throw Error("Invalid input to safeExtend: expected a plain object");let def={...schema._zod.def,get shape(){let _shape={...schema._zod.def.shape,...shape};return assignProp2(this,"shape",_shape),_shape},checks:schema._zod.def.checks};return clone2(schema,def)}function merge2(a,b){let def=mergeDefs2(a._zod.def,{get shape(){let _shape={...a._zod.def.shape,...b._zod.def.shape};return assignProp2(this,"shape",_shape),_shape},get catchall(){return b._zod.def.catchall},checks:[]});return clone2(a,def)}function partial2(Class2,schema,mask){let def=mergeDefs2(schema._zod.def,{get shape(){let oldShape=schema._zod.def.shape,shape={...oldShape};if(mask)for(let key in mask){if(!(key in oldShape))throw Error(`Unrecognized key: "${key}"`);if(!mask[key])continue;shape[key]=Class2?new Class2({type:"optional",innerType:oldShape[key]}):oldShape[key]}else for(let key in oldShape)shape[key]=Class2?new Class2({type:"optional",innerType:oldShape[key]}):oldShape[key];return assignProp2(this,"shape",shape),shape},checks:[]});return clone2(schema,def)}function required2(Class2,schema,mask){let def=mergeDefs2(schema._zod.def,{get shape(){let oldShape=schema._zod.def.shape,shape={...oldShape};if(mask)for(let key in mask){if(!(key in shape))throw Error(`Unrecognized key: "${key}"`);if(!mask[key])continue;shape[key]=new Class2({type:"nonoptional",innerType:oldShape[key]})}else for(let key in oldShape)shape[key]=new Class2({type:"nonoptional",innerType:oldShape[key]});return assignProp2(this,"shape",shape),shape},checks:[]});return clone2(schema,def)}function aborted2(x,startIndex=0){if(x.aborted===!0)return!0;for(let i=startIndex;i<x.issues.length;i++)if(x.issues[i]?.continue!==!0)return!0;return!1}function prefixIssues2(path51,issues){return issues.map((iss)=>{var _a2;return(_a2=iss).path??(_a2.path=[]),iss.path.unshift(path51),iss})}function unwrapMessage2(message){return typeof message==="string"?message:message?.message}function finalizeIssue2(iss,ctx,config3){let full={...iss,path:iss.path??[]};if(!iss.message){let message=unwrapMessage2(iss.inst?._zod.def?.error?.(iss))??unwrapMessage2(ctx?.error?.(iss))??unwrapMessage2(config3.customError?.(iss))??unwrapMessage2(config3.localeError?.(iss))??"Invalid input";full.message=message}if(delete full.inst,delete full.continue,!ctx?.reportInput)delete full.input;return full}function getSizableOrigin2(input){if(input instanceof Set)return"set";if(input instanceof Map)return"map";if(input instanceof File)return"file";return"unknown"}function getLengthableOrigin2(input){if(Array.isArray(input))return"array";if(typeof input==="string")return"string";return"unknown"}function issue2(...args2){let[iss,input,inst]=args2;if(typeof iss==="string")return{message:iss,code:"custom",input,inst};return{...iss}}function cleanEnum2(obj){return Object.entries(obj).filter(([k,_])=>{return Number.isNaN(Number.parseInt(k,10))}).map((el)=>el[1])}function base64ToUint8Array2(base643){let binaryString=atob(base643),bytes=new Uint8Array(binaryString.length);for(let i=0;i<binaryString.length;i++)bytes[i]=binaryString.charCodeAt(i);return bytes}function uint8ArrayToBase642(bytes){let binaryString="";for(let i=0;i<bytes.length;i++)binaryString+=String.fromCharCode(bytes[i]);return btoa(binaryString)}function base64urlToUint8Array2(base64url3){let base643=base64url3.replace(/-/g,"+").replace(/_/g,"/"),padding="=".repeat((4-base643.length%4)%4);return base64ToUint8Array2(base643+padding)}function uint8ArrayToBase64url2(bytes){return uint8ArrayToBase642(bytes).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function hexToUint8Array2(hex3){let cleanHex=hex3.replace(/^0x/,"");if(cleanHex.length%2!==0)throw Error("Invalid hex string length");let bytes=new Uint8Array(cleanHex.length/2);for(let i=0;i<cleanHex.length;i+=2)bytes[i/2]=Number.parseInt(cleanHex.slice(i,i+2),16);return bytes}function uint8ArrayToHex2(bytes){return Array.from(bytes).map((b)=>b.toString(16).padStart(2,"0")).join("")}class Class2{constructor(..._args){}}var EVALUATING2,captureStackTrace2,allowsEval2,getParsedType2=(data)=>{let t=typeof data;switch(t){case"undefined":return"undefined";case"string":return"string";case"number":return Number.isNaN(data)?"nan":"number";case"boolean":return"boolean";case"function":return"function";case"bigint":return"bigint";case"symbol":return"symbol";case"object":if(Array.isArray(data))return"array";if(data===null)return"null";if(data.then&&typeof data.then==="function"&&data.catch&&typeof data.catch==="function")return"promise";if(typeof Map<"u"&&data instanceof Map)return"map";if(typeof Set<"u"&&data instanceof Set)return"set";if(typeof Date<"u"&&data instanceof Date)return"date";if(typeof File<"u"&&data instanceof File)return"file";return"object";default:throw Error(`Unknown data type: ${t}`)}},propertyKeyTypes2,primitiveTypes2,NUMBER_FORMAT_RANGES2,BIGINT_FORMAT_RANGES2;var init_util2=__esm(()=>{EVALUATING2=Symbol("evaluating");captureStackTrace2="captureStackTrace"in Error?Error.captureStackTrace:(..._args)=>{};allowsEval2=cached2(()=>{if(typeof navigator<"u"&&navigator?.userAgent?.includes("Cloudflare"))return!1;try{return new Function(""),!0}catch(_){return!1}});propertyKeyTypes2=new Set(["string","number","symbol"]),primitiveTypes2=new Set(["string","number","bigint","boolean","symbol","undefined"]);NUMBER_FORMAT_RANGES2={safeint:[Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER],int32:[-2147483648,2147483647],uint32:[0,4294967295],float32:[-340282346638528860000000000000000000000,340282346638528860000000000000000000000],float64:[-Number.MAX_VALUE,Number.MAX_VALUE]},BIGINT_FORMAT_RANGES2={int64:[BigInt("-9223372036854775808"),BigInt("9223372036854775807")],uint64:[BigInt(0),BigInt("18446744073709551615")]}});function flattenError2(error49,mapper=(issue3)=>issue3.message){let fieldErrors={},formErrors=[];for(let sub of error49.issues)if(sub.path.length>0)fieldErrors[sub.path[0]]=fieldErrors[sub.path[0]]||[],fieldErrors[sub.path[0]].push(mapper(sub));else formErrors.push(mapper(sub));return{formErrors,fieldErrors}}function formatError2(error49,_mapper){let mapper=_mapper||function(issue3){return issue3.message},fieldErrors={_errors:[]},processError=(error50)=>{for(let issue3 of error50.issues)if(issue3.code==="invalid_union"&&issue3.errors.length)issue3.errors.map((issues)=>processError({issues}));else if(issue3.code==="invalid_key")processError({issues:issue3.issues});else if(issue3.code==="invalid_element")processError({issues:issue3.issues});else if(issue3.path.length===0)fieldErrors._errors.push(mapper(issue3));else{let curr=fieldErrors,i=0;while(i<issue3.path.length){let el=issue3.path[i];if(i!==issue3.path.length-1)curr[el]=curr[el]||{_errors:[]};else curr[el]=curr[el]||{_errors:[]},curr[el]._errors.push(mapper(issue3));curr=curr[el],i++}}};return processError(error49),fieldErrors}function treeifyError2(error49,_mapper){let mapper=_mapper||function(issue3){return issue3.message},result={errors:[]},processError=(error50,path51=[])=>{var _a2,_b;for(let issue3 of error50.issues)if(issue3.code==="invalid_union"&&issue3.errors.length)issue3.errors.map((issues)=>processError({issues},issue3.path));else if(issue3.code==="invalid_key")processError({issues:issue3.issues},issue3.path);else if(issue3.code==="invalid_element")processError({issues:issue3.issues},issue3.path);else{let fullpath=[...path51,...issue3.path];if(fullpath.length===0){result.errors.push(mapper(issue3));continue}let curr=result,i=0;while(i<fullpath.length){let el=fullpath[i],terminal=i===fullpath.length-1;if(typeof el==="string")curr.properties??(curr.properties={}),(_a2=curr.properties)[el]??(_a2[el]={errors:[]}),curr=curr.properties[el];else curr.items??(curr.items=[]),(_b=curr.items)[el]??(_b[el]={errors:[]}),curr=curr.items[el];if(terminal)curr.errors.push(mapper(issue3));i++}}};return processError(error49),result}function toDotPath2(_path){let segs=[],path51=_path.map((seg)=>typeof seg==="object"?seg.key:seg);for(let seg of path51)if(typeof seg==="number")segs.push(`[${seg}]`);else if(typeof seg==="symbol")segs.push(`[${JSON.stringify(String(seg))}]`);else if(/[^\w$]/.test(seg))segs.push(`[${JSON.stringify(seg)}]`);else{if(segs.length)segs.push(".");segs.push(seg)}return segs.join("")}function prettifyError2(error49){let lines=[],issues=[...error49.issues].sort((a,b)=>(a.path??[]).length-(b.path??[]).length);for(let issue3 of issues)if(lines.push(`✖ ${issue3.message}`),issue3.path?.length)lines.push(` → at ${toDotPath2(issue3.path)}`);return lines.join(`
|
|
@@ -1096,16 +1096,16 @@ RULES:
|
|
|
1096
1096
|
`))return warn("[knowledge-validator] unarchiveEntry: invalid entryId rejected"),{restored:!1,reason:"not_found"};let storeDir=resolveKnowledgeStoreDir(directory),knowledgePath=resolveSwarmKnowledgePath(directory),swarmDir=storeDir;await mkdir8(swarmDir,{recursive:!0});let release;try{release=await import_proper_lockfile3.default.lock(swarmDir,{retries:{retries:5,minTimeout:100,maxTimeout:500},stale:5000});let entries=await readKnowledge(knowledgePath),target=entries.find((e)=>e.id===entryId);if(!target)return{restored:!1,reason:"not_found"};if(target.status!=="archived")return{restored:!1,reason:"not_archived"};let validation=validateLesson(target.lesson,[],{category:target.category,scope:target.scope,confidence:target.confidence});if(!validation.valid)return warn(`[knowledge-validator] unarchiveEntry: entry ${entryId} failed re-validation: ${validation.reason}`),{restored:!1,reason:"invalid_lesson"};let restoredStatus=target.archived_from??"candidate",finalStatus=new Set(["candidate","established","promoted"]).has(restoredStatus)?restoredStatus:"candidate",{archived_from:_af,archived_at:_at,recent_negative_phase_count:_rnpc,last_demotion_phase:_ldp,...rest}=target,restored={...rest,status:finalStatus,updated_at:new Date().toISOString(),recent_negative_phase_count:0,last_demotion_phase:void 0},next=entries.map((e)=>e.id===entryId?restored:e),jsonlContent=next.length>0?`${next.map((e)=>JSON.stringify(e)).join(`
|
|
1097
1097
|
`)}
|
|
1098
1098
|
`:"";return await atomicWriteFile(knowledgePath,jsonlContent),{restored:!0,restored_to:finalStatus}}finally{if(release)await release()}}var import_proper_lockfile3,DANGEROUS_COMMAND_ERROR_PATTERNS,DANGEROUS_COMMAND_WARNING_PATTERNS,DANGEROUS_COMMAND_PATTERNS,SECURITY_DEGRADING_PATTERNS,INVISIBLE_FORMAT_CHARS,INJECTION_PATTERNS,VALID_CATEGORIES,TECH_REFERENCE_WORDS,ACTION_VERB_WORDS,NEGATION_PAIRS,ACTIONABLE_STRING_MAX=200,ACTIONABLE_LIST_MAX=20,RETIRED_SKILL_HISTORY_MAX=50,NAME_PATTERN,SOURCE_REF_FORBIDDEN,ALLOWED_SKILL_PATH_PREFIXES,VALID_DIRECTIVE_PRIORITIES,_internals29;var init_knowledge_validator=__esm(()=>{init_task_file();init_logger();init_knowledge_link();init_knowledge_store();import_proper_lockfile3=__toESM(require_proper_lockfile(),1),DANGEROUS_COMMAND_ERROR_PATTERNS=[/\brm\s+-rf\b/,/\bsudo\s+rm\b/,/\bmkfs\b/,/\bdd\s+if=/,/:\(\)\s*\{/,/\bchmod\s+-R\s+777\b/i,/\bdeltree\b/,/\brmdir\s+\/s\b/],DANGEROUS_COMMAND_WARNING_PATTERNS=[/\bformat\b/,/\bkill\s+-9\b/,/\bpkill\b/,/\bkillall\b/,/`[^`]*`/,/\$\([^)]*\)/],DANGEROUS_COMMAND_PATTERNS=[...DANGEROUS_COMMAND_ERROR_PATTERNS,...DANGEROUS_COMMAND_WARNING_PATTERNS],SECURITY_DEGRADING_PATTERNS=[/disable\s+.{0,50}firewall/i,/turn\s+off\s+.{0,50}security/i,/skip\s+.{0,50}auth/i,/bypass\s+.{0,50}auth/i,/ignore\s+.{0,50}certificate/i,/disable\s+.{0,50}tls/i,/disable\s+.{0,50}ssl/i,/no\s+.{0,50}validation/i,/disable\s+.{0,50}2fa/i,/remove\s+.{0,50}password/i],INVISIBLE_FORMAT_CHARS=/[\u00AD\u200B-\u200F\u202A-\u202E\u2060-\u2064\u2066-\u2069\uFEFF]/g,INJECTION_PATTERNS=[/[\x00-\x08\x0b-\x0c\x0e-\x1f\x7f\x0d]/,/[\u00AD\u200B-\u200F\u202A-\u202E\u2060-\u2064\u2066-\u2069\uFEFF]/,/^system\s*:/i,/<script/i,/javascript:/i,/\beval\(/i,/\b__proto__\b/,/\bconstructor\[/,/\.prototype\[/],VALID_CATEGORIES=new Set(["process","architecture","tooling","security","testing","debugging","performance","integration","todo","other"]),TECH_REFERENCE_WORDS=new Set(["git","docker","typescript","bun","vitest","node","python","react","sql","api","hook","test","schema","config","file","function","class","module","import","export"]),ACTION_VERB_WORDS=new Set(["use","avoid","prefer","run","check","always","never","ensure","call","write","add","remove","update","set","enable","disable"]),NEGATION_PAIRS=[["always","never"],["must","must not"],["must","should not"],["enable","disable"],["use","avoid"],["use","don't use"],["recommended","not recommended"]];NAME_PATTERN=/^[a-z][a-z0-9_]{0,63}$/,SOURCE_REF_FORBIDDEN=/(\.\.\/|\.\.\\|\0|[\x00-\x1f\x7f])/,ALLOWED_SKILL_PATH_PREFIXES=[".opencode/skills/generated/",".swarm/skills/proposals/",".swarm/skills/candidates/"],VALID_DIRECTIVE_PRIORITIES=new Set(["low","medium","high","critical"]);_internals29={validateLesson,auditEntryHealth,quarantineEntry,restoreEntry,unarchiveEntry,extractContextWords,hasSignificantOverlap}});var exports_knowledge_store={};__export(exports_knowledge_store,{wordBigrams:()=>wordBigrams,transactKnowledge:()=>transactKnowledge,transactFile:()=>transactFile,sweepStaleTodos:()=>sweepStaleTodos,sweepAgedEntries:()=>sweepAgedEntries,rewriteKnowledge:()=>rewriteKnowledge,resolveSwarmRetractionsPath:()=>resolveSwarmRetractionsPath,resolveSwarmRejectedPath:()=>resolveSwarmRejectedPath,resolveSwarmKnowledgePath:()=>resolveSwarmKnowledgePath,resolveHiveRejectedPath:()=>resolveHiveRejectedPath,resolveHiveKnowledgePath:()=>resolveHiveKnowledgePath,resolveHiveEventsPath:()=>resolveHiveEventsPath,readRetractionRecords:()=>readRetractionRecords,readRejectedLessons:()=>readRejectedLessons,readKnowledge:()=>readKnowledge,normalizeEntry:()=>normalizeEntry,normalize:()=>normalize5,jaccardBigram:()=>jaccardBigram,inferTags:()=>inferTags2,getPlatformConfigDir:()=>getPlatformConfigDir,getArchivedKnowledgeIds:()=>getArchivedKnowledgeIds,findNearDuplicate:()=>findNearDuplicate,enforceKnowledgeCap:()=>enforceKnowledgeCap,confirmEntriesPhase:()=>confirmEntriesPhase,computeOutcomeSignal:()=>computeOutcomeSignal,computeConfidence:()=>computeConfidence,bumpKnowledgeConfidenceBatch:()=>bumpKnowledgeConfidenceBatch,appendRetractionRecord:()=>appendRetractionRecord,appendRejectedLesson:()=>appendRejectedLesson,appendKnowledgeWithCapEnforcement:()=>appendKnowledgeWithCapEnforcement,appendKnowledge:()=>appendKnowledge,_internals:()=>_internals30,OUTCOME_SIGNAL_SMOOTHING:()=>OUTCOME_SIGNAL_SMOOTHING,MAX_CONFIRMED_BY:()=>MAX_CONFIRMED_BY});import{existsSync as existsSync25}from"node:fs";import{appendFile as appendFile6,mkdir as mkdir9,readFile as readFile9}from"node:fs/promises";import*as os15 from"node:os";import*as path55 from"node:path";function getPlatformConfigDir(){let platform=process.platform,home=process.env.HOME||os15.homedir();if(platform==="win32")return path55.join(process.env.LOCALAPPDATA||path55.join(home,"AppData","Local"),"opencode-swarm","config");else if(platform==="darwin")return path55.join(home,"Library","Application Support","opencode-swarm");else return path55.join(process.env.XDG_CONFIG_HOME||path55.join(home,".config"),"opencode-swarm")}function resolveSwarmKnowledgePath(directory){return path55.join(resolveKnowledgeStoreDir(directory),"knowledge.jsonl")}function resolveSwarmRejectedPath(directory){return path55.join(resolveKnowledgeStoreDir(directory),"knowledge-rejected.jsonl")}function resolveSwarmRetractionsPath(directory){return path55.join(resolveKnowledgeStoreDir(directory),"knowledge-retractions.jsonl")}function resolveHiveKnowledgePath(){let platform=process.platform,home=process.env.HOME||os15.homedir(),dataDir;if(platform==="win32")dataDir=path55.join(process.env.LOCALAPPDATA||path55.join(home,"AppData","Local"),"opencode-swarm","Data");else if(platform==="darwin")dataDir=path55.join(home,"Library","Application Support","opencode-swarm");else dataDir=path55.join(process.env.XDG_DATA_HOME||path55.join(home,".local","share"),"opencode-swarm");return path55.join(dataDir,"shared-learnings.jsonl")}function resolveHiveRejectedPath(){let hivePath=resolveHiveKnowledgePath();return path55.join(path55.dirname(hivePath),"shared-learnings-rejected.jsonl")}function resolveHiveEventsPath(){let hivePath=resolveHiveKnowledgePath();return path55.join(path55.dirname(hivePath),"shared-knowledge-events.jsonl")}function parseKnowledgeContent(content,max){let results=[];for(let line of content.split(`
|
|
1099
|
-
`)){if(Number.isFinite(max)&&results.length>=max)break;let trimmed=line.trim();if(!trimmed)continue;try{results.push(normalizeEntry(JSON.parse(trimmed)))}catch{
|
|
1099
|
+
`)){if(Number.isFinite(max)&&results.length>=max)break;let trimmed=line.trim();if(!trimmed)continue;try{results.push(normalizeEntry(JSON.parse(trimmed)))}catch{log(`[knowledge-store] Skipping corrupted JSONL line: ${trimmed.slice(0,80)}`)}}return results}async function readKnowledge(filePath,maxEntries){let resolvedPath=path55.resolve(filePath),cap=maxEntries!==void 0&&maxEntries>0?maxEntries:void 0;if(cap!==void 0){if(!existsSync25(resolvedPath))return[];let content=await readFile9(resolvedPath,"utf-8");return parseKnowledgeContent(content,cap)}return await readCachedParsedFile(resolvedPath,KNOWLEDGE_JSONL_CACHE_NAMESPACE,async()=>{if(!existsSync25(resolvedPath))return null;return await readFile9(resolvedPath,"utf-8")},(content)=>parseKnowledgeContent(content,1/0))??[]}function normalizeEntry(raw){if(!raw||typeof raw!=="object")return raw;let obj=raw;if(!("retrieval_outcomes"in obj))return raw;let ro=obj.retrieval_outcomes;if(!ro||typeof ro!=="object")ro={},obj.retrieval_outcomes=ro;if(typeof ro.shown_count!=="number")ro.shown_count=typeof ro.applied_count==="number"?ro.applied_count:0;if(typeof ro.acknowledged_count!=="number")ro.acknowledged_count=0;if(typeof ro.applied_explicit_count!=="number")ro.applied_explicit_count=0;if(typeof ro.ignored_count!=="number")ro.ignored_count=0;if(typeof ro.violated_count!=="number")ro.violated_count=0;if(typeof ro.contradicted_count!=="number")ro.contradicted_count=0;if(typeof ro.succeeded_after_shown_count!=="number")ro.succeeded_after_shown_count=typeof ro.succeeded_after_count==="number"?ro.succeeded_after_count:0;if(typeof ro.failed_after_shown_count!=="number")ro.failed_after_shown_count=typeof ro.failed_after_count==="number"?ro.failed_after_count:0;try{if(typeof obj.encounter_score!=="number"||Number.isNaN(obj.encounter_score))obj.encounter_score=0}catch{try{Object.defineProperty(obj,"encounter_score",{value:0,writable:!0,configurable:!0,enumerable:!0})}catch{}}if(typeof obj.recent_negative_phase_count!=="number")obj.recent_negative_phase_count=0;let arrayFields=["triggers","required_actions","forbidden_actions","applies_to_agents","applies_to_tools","verification_checks","source_refs","source_knowledge_ids"];for(let f of arrayFields){let v=obj[f];if(v!==void 0&&!Array.isArray(v))delete obj[f]}if(!Array.isArray(obj.tags))obj.tags=[];return raw}async function readRejectedLessons(directory){return readKnowledge(resolveSwarmRejectedPath(directory))}async function readRetractionRecords(directory){return readKnowledge(resolveSwarmRetractionsPath(directory))}async function appendRetractionRecord(directory,record3){await appendKnowledge(resolveSwarmRetractionsPath(directory),record3)}async function appendKnowledge(filePath,entry){let dir=path55.dirname(filePath);await mkdir9(dir,{recursive:!0});let release=null;try{release=await import_proper_lockfile4.default.lock(dir,{retries:{retries:5,minTimeout:100,maxTimeout:500},stale:5000}),await appendFile6(filePath,`${JSON.stringify(entry)}
|
|
1100
1100
|
`,"utf-8")}finally{if(release)try{await release()}catch{}}}async function rewriteKnowledge(filePath,entries){let dir=path55.dirname(filePath);await mkdir9(dir,{recursive:!0});let release=null;try{release=await import_proper_lockfile4.default.lock(dir,{retries:{retries:5,minTimeout:100,maxTimeout:500},stale:5000});let content=entries.map((e)=>JSON.stringify(e)).join(`
|
|
1101
1101
|
`)+(entries.length>0?`
|
|
1102
1102
|
`:"");await atomicWriteFile(filePath,content)}finally{if(release)try{await release()}catch{}}}async function transactFile(filePath,read,write,mutate){let dir=path55.dirname(filePath);try{await mkdir9(dir,{recursive:!0})}catch{return!1}let release=null;try{release=await import_proper_lockfile4.default.lock(dir,{retries:{retries:5,minTimeout:100,maxTimeout:500},stale:5000});let data=await read(filePath),result=mutate(data);if(result===null)return!1;return await write(filePath,result),!0}finally{if(release)try{await release()}catch{}}}async function transactKnowledge(filePath,mutate){return transactFile(filePath,readKnowledge,async(fp,entries)=>{let content=entries.map((e)=>JSON.stringify(e)).join(`
|
|
1103
1103
|
`)+(entries.length>0?`
|
|
1104
1104
|
`:"");await atomicWriteFile(fp,content)},mutate)}async function getArchivedKnowledgeIds(directory){let archived=new Set,swarmPath=resolveSwarmKnowledgePath(directory);try{let lines=(await readFile9(swarmPath,"utf-8")).split(`
|
|
1105
1105
|
`).filter((l)=>l.trim());for(let line of lines)try{let entry=JSON.parse(line);if(!isActiveStatus(entry.status))archived.add(entry.id)}catch{}}catch{}let hivePath=resolveHiveKnowledgePath();try{let lines=(await readFile9(hivePath,"utf-8")).split(`
|
|
1106
|
-
`).filter((l)=>l.trim());for(let line of lines)try{let entry=JSON.parse(line);if(!isActiveStatus(entry.status))archived.add(entry.id)}catch{}}catch{}return archived}async function appendKnowledgeWithCapEnforcement(filePath,entry,maxEntries){return transactKnowledge(filePath,(entries)=>{let updated=[...entries,entry];if(updated.length>maxEntries)return selectKnowledgeCapSurvivors(updated,maxEntries);return updated})}async function enforceKnowledgeCap(filePath,maxEntries){await transactKnowledge(filePath,(entries)=>{if(entries.length<=maxEntries)return null;return selectKnowledgeCapSurvivors(entries,maxEntries)})}function selectKnowledgeCapSurvivors(entries,maxEntries){if(entries.length<=maxEntries)return entries;if(maxEntries<=0)return[];let candidates=entries.map((entry,index)=>{let maybeKnowledge=entry;return{entry,index,status:maybeKnowledge.status,outcomeSignal:computeOutcomeSignal(maybeKnowledge.retrieval_outcomes)}}),evictable=candidates.every((c)=>c.status==="promoted")?candidates:candidates.filter((c)=>c.status!=="promoted"),targetDropCount=entries.length-maxEntries,dropCount=Math.min(targetDropCount,evictable.length);if(dropCount<=0)return entries;let drop=new Set([...evictable].sort((a,b)=>{let inactiveDelta=getKnowledgeCapStatusPriority(a.status)-getKnowledgeCapStatusPriority(b.status);if(inactiveDelta!==0)return inactiveDelta;let signalDelta=a.outcomeSignal-b.outcomeSignal;if(signalDelta!==0)return signalDelta;return a.index-b.index}).slice(0,dropCount).map((c)=>c.index));return candidates.filter((c)=>!drop.has(c.index)).map((c)=>c.entry)}function getKnowledgeCapStatusPriority(status){if(!isActiveStatus(status))return 0;return 1}async function sweepAgedEntries(filePath,defaultMaxPhases){let result={scanned:0,aged:0,archived:0,removed:0,skipped_promoted:0};return await transactKnowledge(filePath,(entries)=>{if(result.scanned=entries.length,entries.length===0)return null;let now=new Date().toISOString(),mutated=!1;for(let entry of entries){if(entry.status==="archived")continue;if(entry.status==="promoted"){result.skipped_promoted++;continue}entry.phases_alive=(entry.phases_alive??0)+1,result.aged++,mutated=!0;let ttl=entry.max_phases??defaultMaxPhases;if(entry.phases_alive>ttl)entry.archived_from=entry.status,entry.archived_at=now,entry.status="archived",entry.updated_at=now,result.archived++}return mutated?entries:null}),result}async function sweepStaleTodos(filePath,todoMaxPhases){let result={scanned:0,aged:0,archived:0,removed:0,skipped_promoted:0};return await transactKnowledge(filePath,(entries)=>{if(result.scanned=entries.length,entries.length===0)return null;let kept=entries.filter((e)=>{if(e.category!=="todo"||e.status==="promoted")return!0;if((e.phases_alive??0)>todoMaxPhases)return result.removed++,!1;return!0});return result.removed>0?kept:null}),result}async function appendRejectedLesson(directory,lesson,maxEntries=20){let filePath=resolveSwarmRejectedPath(directory);await transactKnowledge(filePath,(existing)=>{let updated=[...existing,lesson];if(updated.length>maxEntries)return updated.slice(updated.length-maxEntries);return updated})}function normalize5(text){return(typeof text==="string"?text:String(text??"")).toLowerCase().replace(/[^\w\s]/g," ").replace(/\s+/g," ").trim()}function wordBigrams(text){let words=normalize5(text).split(" ").filter(Boolean),bigrams=new Set;for(let i=0;i<words.length-1;i++)bigrams.add(`${words[i]} ${words[i+1]}`);return bigrams}function jaccardBigram(a,b){if(a.size===0&&b.size===0)return 1;let aArr=Array.from(a),intersection3=new Set(aArr.filter((x)=>b.has(x))),union3=new Set([...aArr,...Array.from(b)]);return intersection3.size/union3.size}function findNearDuplicate(candidate,entries,threshold=0.6){let candidateBigrams=wordBigrams(candidate);return entries.find((entry)=>{let entryBigrams=wordBigrams(entry.lesson);return jaccardBigram(candidateBigrams,entryBigrams)>=threshold})}function computeConfidence(confirmedByCount,autoGenerated){let score=0.5;if(score+=Math.min(confirmedByCount,3)*0.1,!autoGenerated)score+=0.1;return Math.min(score,1)}async function confirmEntriesPhase(directory,ids,phaseNumber,projectName){if(ids.length===0)return;let knowledgePath=resolveSwarmKnowledgePath(directory);await transactKnowledge(knowledgePath,(current)=>{let idSet=new Set(ids),changed=!1,now=new Date().toISOString();for(let entry of current){if(!idSet.has(entry.id))continue;if(reinforceSwarmKnowledgeEntry(entry,{phase_number:phaseNumber,confirmed_at:now,project_name:projectName}).reinforced){let records=entry.confirmed_by??[];if(records.length>MAX_CONFIRMED_BY)entry.confirmed_by=[...records].sort((a,b)=>a.confirmed_at.localeCompare(b.confirmed_at)).slice(-MAX_CONFIRMED_BY),entry.confidence=computeConfidence(new Set(entry.confirmed_by.map((r)=>r.phase_number).filter((n)=>Number.isInteger(n))).size,entry.auto_generated??!1);changed=!0}}return changed?current:null}).catch(()=>{})}function computeOutcomeSignal(outcomes){if(!outcomes)return 0;let positives=(outcomes.applied_explicit_count??0)+(outcomes.succeeded_after_shown_count??0),negatives=(outcomes.ignored_count??0)+(outcomes.violated_count??0)+(outcomes.contradicted_count??0)+(outcomes.failed_after_shown_count??0),total=positives+negatives;if(total===0)return 0;return(positives-negatives)/(total+OUTCOME_SIGNAL_SMOOTHING)}function inferTags2(lesson){let lower=lesson.toLowerCase(),tags=[];if(/(^|\s)(?:todo|remember|don't?(?:\s+)?forget)(?:\s|:|,|$)/i.test(lesson))tags.push("todo");if(/\b(?:typescript|ts)\b/.test(lower))tags.push("typescript");if(/\b(?:javascript|js)\b/.test(lower))tags.push("javascript");if(/\b(?:python)\b/.test(lower))tags.push("python");if(/\b(?:bun|node|deno)\b/.test(lower))tags.push("runtime");if(/\b(?:react|vue|svelte|angular)\b/.test(lower))tags.push("frontend");if(/\b(?:git|github|gitlab)\b/.test(lower))tags.push("git");if(/\b(?:docker|kubernetes|k8s)\b/.test(lower))tags.push("container");if(/\b(?:sql|postgres|mysql|sqlite)\b/.test(lower))tags.push("database");if(/\b(?:test|spec|vitest|jest|mocha)\b/.test(lower))tags.push("testing");if(/\b(?:ci|cd|pipeline|workflow|action)\b/.test(lower))tags.push("ci-cd");if(/\b(?:security|auth|token|password|encrypt)\b/.test(lower))tags.push("security");if(/\b(?:performance|latency|throughput|cache)\b/.test(lower))tags.push("performance");if(/\b(?:api|rest|graphql|grpc|endpoint)\b/.test(lower))tags.push("api");if(/\b(?:swarm|architect|agent|hook|plan)\b/.test(lower))tags.push("opencode-swarm");return Array.from(new Set(tags))}async function bumpKnowledgeConfidenceBatch(directory,deltas,options){if(deltas.length===0)return;let swarmPath=resolveSwarmKnowledgePath(directory),hivePath=resolveHiveKnowledgePath(),touchedSwarm=[],touchedHive=[];try{touchedSwarm.push(...await applyConfidenceDeltas(swarmPath,deltas));let swarmIds=new Set(touchedSwarm.map((e)=>e.id)),hiveOnly=deltas.filter((d)=>!swarmIds.has(d.id));if(hiveOnly.length>0)touchedHive.push(...await applyConfidenceDeltas(hivePath,hiveOnly));await applyConfidenceFloorAction(directory,[...touchedSwarm,...touchedHive],options).catch((err)=>{console.warn("[knowledge-store] confidence-floor action sweep failed (best-effort):",err instanceof Error?err.message:String(err))})}catch(err){console.warn("[knowledge-store] bumpKnowledgeConfidenceBatch failed (fail-open):",err instanceof Error?err.message:String(err))}}async function applyConfidenceFloorAction(directory,touched,options){let action=options?.floorAction??"demote";if(action==="none"||touched.length===0)return;let minOutcomes=options?.floorMinOutcomes??3,signalThreshold=options?.floorSignalThreshold??0,FLOOR_EPSILON=0.000000001,atFloor=touched.filter((e)=>e.confidence<=CONFIDENCE_FLOOR+FLOOR_EPSILON),recovered=touched.filter((e)=>e.confidence>CONFIDENCE_FLOOR+FLOOR_EPSILON&&e.confidence_floor_demoted);if(atFloor.length===0&&recovered.length===0)return;let{readKnowledgeCounterRollups,effectiveRetrievalOutcomes}=await Promise.resolve().then(() => (init_knowledge_events(),exports_knowledge_events)),rollups=await readKnowledgeCounterRollups(directory),flagIds=new Set;for(let e of atFloor){let outcomes=effectiveRetrievalOutcomes(e.retrieval_outcomes,rollups?.get(e.id)),signal=computeOutcomeSignal(outcomes),totalEvidence=(outcomes.applied_explicit_count??0)+(outcomes.succeeded_after_shown_count??0)+(outcomes.ignored_count??0)+(outcomes.violated_count??0)+(outcomes.contradicted_count??0)+(outcomes.failed_after_shown_count??0);if(signal<signalThreshold&&totalEvidence>=minOutcomes)flagIds.add(e.id)}for(let e of recovered)flagIds.add(e.id);if(flagIds.size===0)return;let swarmPath=resolveSwarmKnowledgePath(directory),hivePath=resolveHiveKnowledgePath(),toQuarantine=[];await transactKnowledge(swarmPath,(swarmEntries)=>{let now=new Date().toISOString();for(let entry of swarmEntries){if(!flagIds.has(entry.id))continue;if(atFloor.find((e)=>e.id===entry.id)){if(entry.confidence_floor_demoted=!0,action==="quarantine")toQuarantine.push({id:entry.id,tier:"swarm"})}else entry.confidence_floor_demoted=!1;entry.updated_at=now}return swarmEntries}).catch((err)=>{console.warn("[knowledge-store] confidence-floor swarm flag transaction failed (best-effort):",err instanceof Error?err.message:String(err))});let hiveFlagIds=new Set;for(let e of atFloor)if(e.tier==="hive"&&flagIds.has(e.id))hiveFlagIds.add(e.id);for(let e of recovered)if(e.tier==="hive"&&flagIds.has(e.id))hiveFlagIds.add(e.id);if(hiveFlagIds.size>0)await transactKnowledge(hivePath,(hiveEntries)=>{let now=new Date().toISOString();for(let entry of hiveEntries){if(!hiveFlagIds.has(entry.id))continue;if(atFloor.find((e)=>e.id===entry.id))entry.confidence_floor_demoted=!0;else entry.confidence_floor_demoted=!1;entry.updated_at=now}return hiveEntries}).catch((err)=>{console.warn("[knowledge-store] confidence-floor hive flag transaction failed (best-effort):",err instanceof Error?err.message:String(err))});if(action==="quarantine"&&toQuarantine.length>0){let{quarantineEntry:quarantineEntry2}=await Promise.resolve().then(() => (init_knowledge_validator(),exports_knowledge_validator));for(let{id}of toQuarantine)await quarantineEntry2(directory,id,"confidence_floor_negative_outcome","auto").catch((err)=>{console.warn("[knowledge-store] confidence-floor quarantine failed (best-effort):",err instanceof Error?err.message:String(err))})}}async function applyConfidenceDeltas(filePath,deltas){let idDeltaMap=new Map;for(let d of deltas){let existing=idDeltaMap.get(d.id);idDeltaMap.set(d.id,existing!==void 0?existing+d.delta:d.delta)}let touched=[],release=null;try{let dir=path55.dirname(filePath);await mkdir9(dir,{recursive:!0}),release=await import_proper_lockfile4.default.lock(dir,{retries:{retries:5,minTimeout:100,maxTimeout:500},stale:5000});let entries=await readKnowledge(filePath);if(entries.length===0)return[];let now=new Date().toISOString(),mutated=!1;for(let entry of entries){let delta=idDeltaMap.get(entry.id);if(delta===void 0)continue;entry.confidence=Math.max(CONFIDENCE_FLOOR,Math.min(CONFIDENCE_CEILING,entry.confidence+delta)),entry.updated_at=now,mutated=!0,touched.push(entry)}if(mutated){let content=entries.map((e)=>JSON.stringify(e)).join(`
|
|
1106
|
+
`).filter((l)=>l.trim());for(let line of lines)try{let entry=JSON.parse(line);if(!isActiveStatus(entry.status))archived.add(entry.id)}catch{}}catch{}return archived}async function appendKnowledgeWithCapEnforcement(filePath,entry,maxEntries){return transactKnowledge(filePath,(entries)=>{let updated=[...entries,entry];if(updated.length>maxEntries)return selectKnowledgeCapSurvivors(updated,maxEntries);return updated})}async function enforceKnowledgeCap(filePath,maxEntries){await transactKnowledge(filePath,(entries)=>{if(entries.length<=maxEntries)return null;return selectKnowledgeCapSurvivors(entries,maxEntries)})}function selectKnowledgeCapSurvivors(entries,maxEntries){if(entries.length<=maxEntries)return entries;if(maxEntries<=0)return[];let candidates=entries.map((entry,index)=>{let maybeKnowledge=entry;return{entry,index,status:maybeKnowledge.status,outcomeSignal:computeOutcomeSignal(maybeKnowledge.retrieval_outcomes)}}),evictable=candidates.every((c)=>c.status==="promoted")?candidates:candidates.filter((c)=>c.status!=="promoted"),targetDropCount=entries.length-maxEntries,dropCount=Math.min(targetDropCount,evictable.length);if(dropCount<=0)return entries;let drop=new Set([...evictable].sort((a,b)=>{let inactiveDelta=getKnowledgeCapStatusPriority(a.status)-getKnowledgeCapStatusPriority(b.status);if(inactiveDelta!==0)return inactiveDelta;let signalDelta=a.outcomeSignal-b.outcomeSignal;if(signalDelta!==0)return signalDelta;return a.index-b.index}).slice(0,dropCount).map((c)=>c.index));return candidates.filter((c)=>!drop.has(c.index)).map((c)=>c.entry)}function getKnowledgeCapStatusPriority(status){if(!isActiveStatus(status))return 0;return 1}async function sweepAgedEntries(filePath,defaultMaxPhases){let result={scanned:0,aged:0,archived:0,removed:0,skipped_promoted:0};return await transactKnowledge(filePath,(entries)=>{if(result.scanned=entries.length,entries.length===0)return null;let now=new Date().toISOString(),mutated=!1;for(let entry of entries){if(entry.status==="archived")continue;if(entry.status==="promoted"){result.skipped_promoted++;continue}entry.phases_alive=(entry.phases_alive??0)+1,result.aged++,mutated=!0;let ttl=entry.max_phases??defaultMaxPhases;if(entry.phases_alive>ttl)entry.archived_from=entry.status,entry.archived_at=now,entry.status="archived",entry.updated_at=now,result.archived++}return mutated?entries:null}),result}async function sweepStaleTodos(filePath,todoMaxPhases){let result={scanned:0,aged:0,archived:0,removed:0,skipped_promoted:0};return await transactKnowledge(filePath,(entries)=>{if(result.scanned=entries.length,entries.length===0)return null;let kept=entries.filter((e)=>{if(e.category!=="todo"||e.status==="promoted")return!0;if((e.phases_alive??0)>todoMaxPhases)return result.removed++,!1;return!0});return result.removed>0?kept:null}),result}async function appendRejectedLesson(directory,lesson,maxEntries=20){let filePath=resolveSwarmRejectedPath(directory);await transactKnowledge(filePath,(existing)=>{let updated=[...existing,lesson];if(updated.length>maxEntries)return updated.slice(updated.length-maxEntries);return updated})}function normalize5(text){return(typeof text==="string"?text:String(text??"")).toLowerCase().replace(/[^\w\s]/g," ").replace(/\s+/g," ").trim()}function wordBigrams(text){let words=normalize5(text).split(" ").filter(Boolean),bigrams=new Set;for(let i=0;i<words.length-1;i++)bigrams.add(`${words[i]} ${words[i+1]}`);return bigrams}function jaccardBigram(a,b){if(a.size===0&&b.size===0)return 1;let aArr=Array.from(a),intersection3=new Set(aArr.filter((x)=>b.has(x))),union3=new Set([...aArr,...Array.from(b)]);return intersection3.size/union3.size}function findNearDuplicate(candidate,entries,threshold=0.6){let candidateBigrams=wordBigrams(candidate);return entries.find((entry)=>{let entryBigrams=wordBigrams(entry.lesson);return jaccardBigram(candidateBigrams,entryBigrams)>=threshold})}function computeConfidence(confirmedByCount,autoGenerated){let score=0.5;if(score+=Math.min(confirmedByCount,3)*0.1,!autoGenerated)score+=0.1;return Math.min(score,1)}async function confirmEntriesPhase(directory,ids,phaseNumber,projectName){if(ids.length===0)return;let knowledgePath=resolveSwarmKnowledgePath(directory);await transactKnowledge(knowledgePath,(current)=>{let idSet=new Set(ids),changed=!1,now=new Date().toISOString();for(let entry of current){if(!idSet.has(entry.id))continue;if(reinforceSwarmKnowledgeEntry(entry,{phase_number:phaseNumber,confirmed_at:now,project_name:projectName}).reinforced){let records=entry.confirmed_by??[];if(records.length>MAX_CONFIRMED_BY)entry.confirmed_by=[...records].sort((a,b)=>a.confirmed_at.localeCompare(b.confirmed_at)).slice(-MAX_CONFIRMED_BY),entry.confidence=computeConfidence(new Set(entry.confirmed_by.map((r)=>r.phase_number).filter((n)=>Number.isInteger(n))).size,entry.auto_generated??!1);changed=!0}}return changed?current:null}).catch(()=>{})}function computeOutcomeSignal(outcomes){if(!outcomes)return 0;let positives=(outcomes.applied_explicit_count??0)+(outcomes.succeeded_after_shown_count??0),negatives=(outcomes.ignored_count??0)+(outcomes.violated_count??0)+(outcomes.contradicted_count??0)+(outcomes.failed_after_shown_count??0),total=positives+negatives;if(total===0)return 0;return(positives-negatives)/(total+OUTCOME_SIGNAL_SMOOTHING)}function inferTags2(lesson){let lower=lesson.toLowerCase(),tags=[];if(/(^|\s)(?:todo|remember|don't?(?:\s+)?forget)(?:\s|:|,|$)/i.test(lesson))tags.push("todo");if(/\b(?:typescript|ts)\b/.test(lower))tags.push("typescript");if(/\b(?:javascript|js)\b/.test(lower))tags.push("javascript");if(/\b(?:python)\b/.test(lower))tags.push("python");if(/\b(?:bun|node|deno)\b/.test(lower))tags.push("runtime");if(/\b(?:react|vue|svelte|angular)\b/.test(lower))tags.push("frontend");if(/\b(?:git|github|gitlab)\b/.test(lower))tags.push("git");if(/\b(?:docker|kubernetes|k8s)\b/.test(lower))tags.push("container");if(/\b(?:sql|postgres|mysql|sqlite)\b/.test(lower))tags.push("database");if(/\b(?:test|spec|vitest|jest|mocha)\b/.test(lower))tags.push("testing");if(/\b(?:ci|cd|pipeline|workflow|action)\b/.test(lower))tags.push("ci-cd");if(/\b(?:security|auth|token|password|encrypt)\b/.test(lower))tags.push("security");if(/\b(?:performance|latency|throughput|cache)\b/.test(lower))tags.push("performance");if(/\b(?:api|rest|graphql|grpc|endpoint)\b/.test(lower))tags.push("api");if(/\b(?:swarm|architect|agent|hook|plan)\b/.test(lower))tags.push("opencode-swarm");return Array.from(new Set(tags))}async function bumpKnowledgeConfidenceBatch(directory,deltas,options){if(deltas.length===0)return;let swarmPath=resolveSwarmKnowledgePath(directory),hivePath=resolveHiveKnowledgePath(),touchedSwarm=[],touchedHive=[];try{touchedSwarm.push(...await applyConfidenceDeltas(swarmPath,deltas));let swarmIds=new Set(touchedSwarm.map((e)=>e.id)),hiveOnly=deltas.filter((d)=>!swarmIds.has(d.id));if(hiveOnly.length>0)touchedHive.push(...await applyConfidenceDeltas(hivePath,hiveOnly));await applyConfidenceFloorAction(directory,[...touchedSwarm,...touchedHive],options).catch((err)=>{log("[knowledge-store] confidence-floor action sweep failed (best-effort):",err instanceof Error?err.message:String(err))})}catch(err){log("[knowledge-store] bumpKnowledgeConfidenceBatch failed (fail-open):",err instanceof Error?err.message:String(err))}}async function applyConfidenceFloorAction(directory,touched,options){let action=options?.floorAction??"demote";if(action==="none"||touched.length===0)return;let minOutcomes=options?.floorMinOutcomes??3,signalThreshold=options?.floorSignalThreshold??0,FLOOR_EPSILON=0.000000001,atFloor=touched.filter((e)=>e.confidence<=CONFIDENCE_FLOOR+FLOOR_EPSILON),recovered=touched.filter((e)=>e.confidence>CONFIDENCE_FLOOR+FLOOR_EPSILON&&e.confidence_floor_demoted);if(atFloor.length===0&&recovered.length===0)return;let{readKnowledgeCounterRollups,effectiveRetrievalOutcomes}=await Promise.resolve().then(() => (init_knowledge_events(),exports_knowledge_events)),rollups=await readKnowledgeCounterRollups(directory),flagIds=new Set;for(let e of atFloor){let outcomes=effectiveRetrievalOutcomes(e.retrieval_outcomes,rollups?.get(e.id)),signal=computeOutcomeSignal(outcomes),totalEvidence=(outcomes.applied_explicit_count??0)+(outcomes.succeeded_after_shown_count??0)+(outcomes.ignored_count??0)+(outcomes.violated_count??0)+(outcomes.contradicted_count??0)+(outcomes.failed_after_shown_count??0);if(signal<signalThreshold&&totalEvidence>=minOutcomes)flagIds.add(e.id)}for(let e of recovered)flagIds.add(e.id);if(flagIds.size===0)return;let swarmPath=resolveSwarmKnowledgePath(directory),hivePath=resolveHiveKnowledgePath(),toQuarantine=[];await transactKnowledge(swarmPath,(swarmEntries)=>{let now=new Date().toISOString();for(let entry of swarmEntries){if(!flagIds.has(entry.id))continue;if(atFloor.find((e)=>e.id===entry.id)){if(entry.confidence_floor_demoted=!0,action==="quarantine")toQuarantine.push({id:entry.id,tier:"swarm"})}else entry.confidence_floor_demoted=!1;entry.updated_at=now}return swarmEntries}).catch((err)=>{log("[knowledge-store] confidence-floor swarm flag transaction failed (best-effort):",err instanceof Error?err.message:String(err))});let hiveFlagIds=new Set;for(let e of atFloor)if(e.tier==="hive"&&flagIds.has(e.id))hiveFlagIds.add(e.id);for(let e of recovered)if(e.tier==="hive"&&flagIds.has(e.id))hiveFlagIds.add(e.id);if(hiveFlagIds.size>0)await transactKnowledge(hivePath,(hiveEntries)=>{let now=new Date().toISOString();for(let entry of hiveEntries){if(!hiveFlagIds.has(entry.id))continue;if(atFloor.find((e)=>e.id===entry.id))entry.confidence_floor_demoted=!0;else entry.confidence_floor_demoted=!1;entry.updated_at=now}return hiveEntries}).catch((err)=>{log("[knowledge-store] confidence-floor hive flag transaction failed (best-effort):",err instanceof Error?err.message:String(err))});if(action==="quarantine"&&toQuarantine.length>0){let{quarantineEntry:quarantineEntry2}=await Promise.resolve().then(() => (init_knowledge_validator(),exports_knowledge_validator));for(let{id}of toQuarantine)await quarantineEntry2(directory,id,"confidence_floor_negative_outcome","auto").catch((err)=>{log("[knowledge-store] confidence-floor quarantine failed (best-effort):",err instanceof Error?err.message:String(err))})}}async function applyConfidenceDeltas(filePath,deltas){let idDeltaMap=new Map;for(let d of deltas){let existing=idDeltaMap.get(d.id);idDeltaMap.set(d.id,existing!==void 0?existing+d.delta:d.delta)}let touched=[],release=null;try{let dir=path55.dirname(filePath);await mkdir9(dir,{recursive:!0}),release=await import_proper_lockfile4.default.lock(dir,{retries:{retries:5,minTimeout:100,maxTimeout:500},stale:5000});let entries=await readKnowledge(filePath);if(entries.length===0)return[];let now=new Date().toISOString(),mutated=!1;for(let entry of entries){let delta=idDeltaMap.get(entry.id);if(delta===void 0)continue;entry.confidence=Math.max(CONFIDENCE_FLOOR,Math.min(CONFIDENCE_CEILING,entry.confidence+delta)),entry.updated_at=now,mutated=!0,touched.push(entry)}if(mutated){let content=entries.map((e)=>JSON.stringify(e)).join(`
|
|
1107
1107
|
`)+(entries.length>0?`
|
|
1108
|
-
`:"");await atomicWriteFile(filePath,content)}}catch(err){
|
|
1108
|
+
`:"");await atomicWriteFile(filePath,content)}}catch(err){log(`[knowledge-store] applyConfidenceDeltas failed on ${filePath} (fail-open):`,err instanceof Error?err.message:String(err))}finally{if(release)try{await release()}catch{}}return touched}var import_proper_lockfile4,KNOWLEDGE_JSONL_CACHE_NAMESPACE="knowledge-jsonl:normalized:v1",MAX_CONFIRMED_BY=50,OUTCOME_SIGNAL_SMOOTHING=4,CONFIDENCE_FLOOR=0.1,CONFIDENCE_CEILING=1,_internals30;var init_knowledge_store=__esm(()=>{init_task_file();init_logger();init_swarm_artifact_cache();init_knowledge_link();init_knowledge_reinforcement();init_knowledge_types();import_proper_lockfile4=__toESM(require_proper_lockfile(),1);_internals30={getPlatformConfigDir,resolveSwarmKnowledgePath,resolveSwarmRejectedPath,resolveHiveKnowledgePath,resolveHiveRejectedPath,resolveHiveEventsPath,readKnowledge,parseKnowledgeContent,readRejectedLessons,appendKnowledge,rewriteKnowledge,transactKnowledge,enforceKnowledgeCap,sweepAgedEntries,sweepStaleTodos,appendRejectedLesson,normalize:normalize5,wordBigrams,jaccardBigram,findNearDuplicate,computeConfidence,computeOutcomeSignal,selectKnowledgeCapSurvivors,inferTags:inferTags2,bumpKnowledgeConfidenceBatch,getArchivedKnowledgeIds}});var exports_knowledge_events={};__export(exports_knowledge_events,{resolveLegacyApplicationLogPath:()=>resolveLegacyApplicationLogPath,resolveKnowledgeEventsPath:()=>resolveKnowledgeEventsPath,resolveKnowledgeCounterBaselinePath:()=>resolveKnowledgeCounterBaselinePath,resolveHiveEventsPath:()=>resolveHiveEventsPath2,recordKnowledgeEvent:()=>recordKnowledgeEvent,recordHiveKnowledgeEvent:()=>recordHiveKnowledgeEvent,recomputeCounters:()=>recomputeCounters,readLegacyApplicationRecords:()=>readLegacyApplicationRecords,readKnowledgeEvents:()=>readKnowledgeEvents,readKnowledgeCounterRollups:()=>readKnowledgeCounterRollups,readHiveKnowledgeEvents:()=>readHiveKnowledgeEvents,newTraceId:()=>newTraceId,newEventId:()=>newEventId,effectiveRetrievalOutcomes:()=>effectiveRetrievalOutcomes,countViolationsInWindow:()=>countViolationsInWindow,countEntryViolationsInWindow:()=>countEntryViolationsInWindow,countEntryContradictionsInWindow:()=>countEntryContradictionsInWindow,applyKnowledgeVerdictFeedback:()=>applyKnowledgeVerdictFeedback,appendKnowledgeEvent:()=>appendKnowledgeEvent,appendHiveKnowledgeEvent:()=>appendHiveKnowledgeEvent,_internals:()=>_internals31,RECEIPT_EVENT_TYPES:()=>RECEIPT_EVENT_TYPES,MAX_VIOLATION_TIMESTAMPS:()=>MAX_VIOLATION_TIMESTAMPS,MAX_EVENT_LOG_ENTRIES:()=>MAX_EVENT_LOG_ENTRIES,KNOWLEDGE_EVENT_SCHEMA_VERSION:()=>KNOWLEDGE_EVENT_SCHEMA_VERSION});import{randomUUID as randomUUID5}from"node:crypto";import{existsSync as existsSync26}from"node:fs";import{appendFile as appendFile7,mkdir as mkdir10,readFile as readFile10,stat as stat7}from"node:fs/promises";import*as os16 from"node:os";import*as path56 from"node:path";function resolveKnowledgeEventsPath(directory){return path56.join(resolveKnowledgeStoreDir(directory),"knowledge-events.jsonl")}function resolveKnowledgeCounterBaselinePath(directory){return path56.join(resolveKnowledgeStoreDir(directory),"knowledge-counter-baseline.json")}function resolveHiveEventsPath2(){let platform=process.platform,home=process.env.HOME||os16.homedir(),dir;if(platform==="win32")dir=path56.join(process.env.LOCALAPPDATA||path56.join(home,"AppData","Local"),"opencode-swarm","Data");else if(platform==="darwin")dir=path56.join(home,"Library","Application Support","opencode-swarm");else dir=path56.join(process.env.XDG_DATA_HOME||path56.join(home,".local","share"),"opencode-swarm");return path56.join(dir,"shared-knowledge-events.jsonl")}function resolveLegacyApplicationLogPath(directory){return path56.join(resolveKnowledgeStoreDir(directory),"knowledge-application.jsonl")}function newTraceId(){return randomUUID5()}function newEventId(){return randomUUID5()}function withDefaults(event){return{schema_version:KNOWLEDGE_EVENT_SCHEMA_VERSION,...event,event_id:event.event_id||newEventId(),timestamp:event.timestamp||new Date().toISOString()}}async function appendKnowledgeEvent(directory,event){let populated=withDefaults(event),filePath=resolveKnowledgeEventsPath(directory),dirPath=path56.dirname(filePath);await mkdir10(dirPath,{recursive:!0});let release;try{release=await import_proper_lockfile5.default.lock(dirPath,{retries:{retries:200,minTimeout:10,maxTimeout:100}}),await appendFile7(filePath,`${JSON.stringify(populated)}
|
|
1109
1109
|
`,"utf-8");try{let lines=(await readFile10(filePath,"utf-8")).split(`
|
|
1110
1110
|
`).filter((line)=>line.trim().length>0);if(lines.length>MAX_EVENT_LOG_ENTRIES){let evicted=lines.slice(0,lines.length-MAX_EVENT_LOG_ENTRIES),trimmed=lines.slice(lines.length-MAX_EVENT_LOG_ENTRIES);await foldEvictedEventsIntoBaseline(directory,evicted,filePath),await atomicWriteFile(filePath,`${trimmed.join(`
|
|
1111
1111
|
`)}
|
|
@@ -1160,8 +1160,8 @@ ${revisionSection}`;return result}function buildLLMPrompt(currentContent,current
|
|
|
1160
1160
|
`).concat(preservedMarkers.length>0?`
|
|
1161
1161
|
`:"");try{_internals34.writeFileSync(tmpPath2,content2,"utf-8"),_internals34.renameSync(tmpPath2,resolved)}catch(writeErr){let msg=writeErr instanceof Error?writeErr.message:String(writeErr);try{if(_internals34.existsSync(tmpPath2))_internals34.writeFileSync(tmpPath2,"","utf-8")}catch{}return{pruned:0,remaining:0,error:msg}}}return{pruned:0,remaining:0}}let groups=new Map;for(let entry of entries){let list=groups.get(entry.skillPath);if(list)list.push(entry);else groups.set(entry.skillPath,[entry])}let pruned=0,surviving=[];if(groups.forEach((skillEntries)=>{if(skillEntries.length<=maxEntriesPerSkill){surviving.push(...skillEntries);return}skillEntries.sort((a,b)=>b.timestamp>a.timestamp?1:b.timestamp<a.timestamp?-1:0);let kept=skillEntries.slice(0,maxEntriesPerSkill);pruned+=skillEntries.length-kept.length,surviving.push(...kept)}),pruned===0)return{pruned:0,remaining:entries.length};let dir=path62.dirname(resolved),tmpPath=path62.join(dir,`skill-usage-${Date.now()}.tmp`),content=[...surviving.map((e)=>JSON.stringify(e)),...preservedMarkers].join(`
|
|
1162
1162
|
`).concat(`
|
|
1163
|
-
`);try{_internals34.writeFileSync(tmpPath,content,"utf-8"),_internals34.renameSync(tmpPath,resolved)}catch(writeErr){let msg=writeErr instanceof Error?writeErr.message:String(writeErr);try{if(_internals34.existsSync(tmpPath))_internals34.writeFileSync(tmpPath,"","utf-8")}catch{}return{pruned:0,remaining:entries.length,error:msg}}return{pruned,remaining:surviving.length}}async function resolveSourceKnowledgeIds(directory,skillPath){try{let cleanPath=skillPath;if(cleanPath.startsWith("file:"))cleanPath=cleanPath.slice(5);if(/\.\.[/\\]/.test(cleanPath))return[];let absolute=path62.normalize(path62.isAbsolute(cleanPath)?cleanPath:path62.resolve(directory,cleanPath)),baseDir=path62.normalize(path62.resolve(directory));if(!(process.platform==="win32"?absolute.toLowerCase().startsWith((baseDir+path62.sep).toLowerCase()):absolute.startsWith(baseDir+path62.sep)))return[];if(!_internals34.existsSync(absolute))return[];let content=_internals34.readFileSync(absolute,"utf-8");return parseGeneratedFromKnowledge(content)}catch(err){return
|
|
1164
|
-
`);for(let line of lines){let trimmed=line.trim();if(!trimmed.startsWith("-"))continue;let parts=trimmed.slice(1).trim().split(/\s+/);if(parts.length>0&&parts[0].length>0)ids.push(parts[0])}return ids}async function applySkillUsageFeedback(directory,options){let processed=0,bumps=0;try{let allEntries=readSkillUsageEntries(directory),alreadyProcessed=readFeedbackAppliedEntryIds(directory),actionable=allEntries.filter((e)=>{if(e.complianceVerdict!=="compliant"&&e.complianceVerdict!=="violated")return!1;if(options?.sinceTimestamp&&e.timestamp<=options.sinceTimestamp)return!1;if(alreadyProcessed.has(e.id))return!1;return!0});if(actionable.length===0)return{processed:0,bumps:0};let groups=new Map;for(let entry of actionable){let list=groups.get(entry.skillPath);if(list)list.push(entry);else groups.set(entry.skillPath,[entry])}let allDeltas=[],processedEntryIds=[];for(let[skillPath,entries]of Array.from(groups)){let compliantCount=0,violationCount=0;for(let entry of entries)if(entry.complianceVerdict==="compliant")compliantCount++;else if(entry.complianceVerdict==="violated")violationCount++;if(compliantCount===0&&violationCount===0)continue;let delta=compliantCount>violationCount?COMPLIANCE_BOOST:-VIOLATION_DECAY,sourceIds=await resolveSourceKnowledgeIds(directory,skillPath);if(sourceIds.length===0)continue;for(let id of sourceIds)allDeltas.push({id,delta});processedEntryIds.push(...entries.map((entry)=>entry.id)),processed++,bumps+=sourceIds.length}let aggregated=new Map;for(let{id,delta}of allDeltas)aggregated.set(id,(aggregated.get(id)??0)+delta);let clampedDeltas=Array.from(aggregated.entries()).map(([id,netDelta])=>({id,delta:Math.max(-VIOLATION_DECAY,Math.min(COMPLIANCE_BOOST,netDelta))}));if(clampedDeltas.length>0)await bumpKnowledgeConfidenceBatch(directory,clampedDeltas,options?.floorOptions),appendFeedbackAppliedMarker(directory,processedEntryIds)}catch(err){
|
|
1163
|
+
`);try{_internals34.writeFileSync(tmpPath,content,"utf-8"),_internals34.renameSync(tmpPath,resolved)}catch(writeErr){let msg=writeErr instanceof Error?writeErr.message:String(writeErr);try{if(_internals34.existsSync(tmpPath))_internals34.writeFileSync(tmpPath,"","utf-8")}catch{}return{pruned:0,remaining:entries.length,error:msg}}return{pruned,remaining:surviving.length}}async function resolveSourceKnowledgeIds(directory,skillPath){try{let cleanPath=skillPath;if(cleanPath.startsWith("file:"))cleanPath=cleanPath.slice(5);if(/\.\.[/\\]/.test(cleanPath))return[];let absolute=path62.normalize(path62.isAbsolute(cleanPath)?cleanPath:path62.resolve(directory,cleanPath)),baseDir=path62.normalize(path62.resolve(directory));if(!(process.platform==="win32"?absolute.toLowerCase().startsWith((baseDir+path62.sep).toLowerCase()):absolute.startsWith(baseDir+path62.sep)))return[];if(!_internals34.existsSync(absolute))return[];let content=_internals34.readFileSync(absolute,"utf-8");return parseGeneratedFromKnowledge(content)}catch(err){return log("[skill-usage-log] resolveSourceKnowledgeIds failed (fail-open):",err instanceof Error?err.message:String(err)),[]}}function parseGeneratedFromKnowledge(content){let frontmatterMatch=content.match(/^---\s*\n([\s\S]*?)\n---/);if(!frontmatterMatch)return[];let body=frontmatterMatch[1],ids=[],sectionRegex=/generated_from_knowledge\s*:\s*\n((?:\s+-\s+\S+[^\n]*\n?)+)/,sectionMatch=body.match(sectionRegex);if(!sectionMatch)return[];let lines=sectionMatch[1].split(`
|
|
1164
|
+
`);for(let line of lines){let trimmed=line.trim();if(!trimmed.startsWith("-"))continue;let parts=trimmed.slice(1).trim().split(/\s+/);if(parts.length>0&&parts[0].length>0)ids.push(parts[0])}return ids}async function applySkillUsageFeedback(directory,options){let processed=0,bumps=0;try{let allEntries=readSkillUsageEntries(directory),alreadyProcessed=readFeedbackAppliedEntryIds(directory),actionable=allEntries.filter((e)=>{if(e.complianceVerdict!=="compliant"&&e.complianceVerdict!=="violated")return!1;if(options?.sinceTimestamp&&e.timestamp<=options.sinceTimestamp)return!1;if(alreadyProcessed.has(e.id))return!1;return!0});if(actionable.length===0)return{processed:0,bumps:0};let groups=new Map;for(let entry of actionable){let list=groups.get(entry.skillPath);if(list)list.push(entry);else groups.set(entry.skillPath,[entry])}let allDeltas=[],processedEntryIds=[];for(let[skillPath,entries]of Array.from(groups)){let compliantCount=0,violationCount=0;for(let entry of entries)if(entry.complianceVerdict==="compliant")compliantCount++;else if(entry.complianceVerdict==="violated")violationCount++;if(compliantCount===0&&violationCount===0)continue;let delta=compliantCount>violationCount?COMPLIANCE_BOOST:-VIOLATION_DECAY,sourceIds=await resolveSourceKnowledgeIds(directory,skillPath);if(sourceIds.length===0)continue;for(let id of sourceIds)allDeltas.push({id,delta});processedEntryIds.push(...entries.map((entry)=>entry.id)),processed++,bumps+=sourceIds.length}let aggregated=new Map;for(let{id,delta}of allDeltas)aggregated.set(id,(aggregated.get(id)??0)+delta);let clampedDeltas=Array.from(aggregated.entries()).map(([id,netDelta])=>({id,delta:Math.max(-VIOLATION_DECAY,Math.min(COMPLIANCE_BOOST,netDelta))}));if(clampedDeltas.length>0)await bumpKnowledgeConfidenceBatch(directory,clampedDeltas,options?.floorOptions),appendFeedbackAppliedMarker(directory,processedEntryIds)}catch(err){log("[skill-usage-log] applySkillUsageFeedback failed (fail-open):",err instanceof Error?err.message:String(err))}return{processed,bumps}}var _internals34,TAIL_BYTES_DEFAULT=65536,MAX_TAIL_BYTES,SKILL_USAGE_LOG_ROTATE_BYTES=1048576,SKILL_USAGE_LOG_MAX_ENTRIES_PER_SKILL=500,COMPLIANCE_BOOST=0.05,VIOLATION_DECAY=0.1;var init_skill_usage_log=__esm(()=>{init_logger();init_knowledge_store();init_utils2();_internals34={generateId:()=>crypto5.randomUUID(),appendFileSync:fs28.appendFileSync.bind(fs28),readFileSync:fs28.readFileSync.bind(fs28),writeFileSync:fs28.writeFileSync.bind(fs28),renameSync:fs28.renameSync.bind(fs28),mkdirSync:fs28.mkdirSync.bind(fs28),existsSync:fs28.existsSync.bind(fs28),statSync:fs28.statSync.bind(fs28),openSync:fs28.openSync.bind(fs28),readSync:fs28.readSync.bind(fs28),closeSync:fs28.closeSync.bind(fs28),pruneSkillUsageLog,resolveSourceKnowledgeIds,applySkillUsageFeedback,parseGeneratedFromKnowledge,computeComplianceByVersion,normalizeComplianceVerdict,readFeedbackAppliedEntryIds,appendFeedbackAppliedMarker};MAX_TAIL_BYTES=TAIL_BYTES_DEFAULT});var exports_curator={};__export(exports_curator,{writeCuratorSummary:()=>writeCuratorSummary,runCuratorPhase:()=>runCuratorPhase,runCuratorInit:()=>runCuratorInit,readCuratorSummary:()=>readCuratorSummary,parseStructuredCuratorBlocks:()=>parseStructuredCuratorBlocks,parseKnowledgeRecommendationsWithDiagnostics:()=>parseKnowledgeRecommendationsWithDiagnostics,parseKnowledgeRecommendations:()=>parseKnowledgeRecommendations,normalizeRecommendationEntryIdToken:()=>normalizeRecommendationEntryIdToken,mergeCuratorPhaseSummary:()=>mergeCuratorPhaseSummary,filterPhaseEvents:()=>filterPhaseEvents,checkPhaseCompliance:()=>checkPhaseCompliance,applyCuratorKnowledgeUpdates:()=>applyCuratorKnowledgeUpdates,appendCuratorRecommendation:()=>appendCuratorRecommendation,_internals:()=>_internals35});import{randomUUID as randomUUID7}from"node:crypto";import*as fs29 from"node:fs";import*as path63 from"node:path";function normalizeRecommendationEntryIdToken(token){let trimmed=token.trim();if(UUID_V4.test(trimmed)||HEX_ID_PREFIX.test(trimmed))return trimmed;return}function resolveKnowledgeRecommendationIds(recommendations,entries){let diagnostics=[],activeEntries=entries.filter((entry)=>isActiveStatus(entry.status));return{recommendations:recommendations.map((recommendation)=>{let entryId=typeof recommendation.entry_id==="string"?normalizeRecommendationEntryIdToken(recommendation.entry_id):void 0;if(!entryId)return recommendation;if(activeEntries.some((entry)=>entry.id===entryId))return{...recommendation,entry_id:entryId};let matches=activeEntries.filter((entry)=>entry.id.startsWith(entryId));if(matches.length===1)return{...recommendation,entry_id:matches[0].id};return diagnostics.push({section:"RECOMMENDATION_ID",line:entryId,reason:matches.length===0?"entry_id not found":"entry_id prefix is ambiguous"}),null}).filter((rec)=>rec!==null),diagnostics}}function capPhaseDigests(digests){return digests.slice(-MAX_CURATOR_PHASE_DIGESTS)}function capComplianceObservations(observations){return observations.slice(-MAX_CURATOR_COMPLIANCE_OBSERVATIONS)}function canonicalizeJson(value){if(Array.isArray(value))return value.map(canonicalizeJson);if(value===null||typeof value!=="object")return value;return Object.fromEntries(Object.entries(value).sort(([left],[right])=>left.localeCompare(right)).map(([key,nested])=>[key,canonicalizeJson(nested)]))}function recommendationIdentity(recommendation){let stable={...recommendation};if(recommendation.action==="promote"&&recommendation.lesson.startsWith("Hive promotion:"))try{let parsedReason=JSON.parse(recommendation.reason);if(parsedReason!==null&&typeof parsedReason==="object"&&!Array.isArray(parsedReason)){let{timestamp:_volatileTimestamp,...stableReason}=parsedReason;stable.reason=stableReason}}catch{}return JSON.stringify(canonicalizeJson(stable))}function normalizeKnowledgeRecommendations(recommendations){let input=Array.isArray(recommendations)?recommendations.filter((entry)=>entry!==null&&typeof entry==="object"&&typeof entry.action==="string"&&typeof entry.lesson==="string"&&typeof entry.reason==="string"):[],seen=new Set,newestUnique=[];for(let index=input.length-1;index>=0;index--){let recommendation=input[index],identity=recommendationIdentity(recommendation);if(seen.has(identity))continue;seen.add(identity),newestUnique.push(recommendation)}return newestUnique.reverse().slice(-MAX_CURATOR_RECOMMENDATIONS)}function buildDigestFromPhaseDigests(digests){return digests.map((digest2)=>`### Phase ${digest2.phase}
|
|
1165
1165
|
${digest2.summary}`).join(`
|
|
1166
1166
|
|
|
1167
1167
|
`)}async function autoRetireSkills(directory,_curatorKnowledgePath,excludeSlugs){let observations=[];try{let skillListResult=await _internals35.listSkills(directory),usageEntries=_internals35.readSkillUsageEntries(directory),allArchivedIds=await _internals35.getArchivedKnowledgeIds(directory);for(let active of skillListResult.active){if(excludeSlugs?.has(active.slug))continue;let skillUsage=usageEntries.filter((e)=>{let p=e.skillPath;if(p.startsWith("file:"))p=p.slice(5);let normalizedUsage=p.replace(/\\/g,"/"),normalizedActive=active.path.replace(/\\/g,"/");if(normalizedUsage===normalizedActive)return!0;if(normalizedActive.endsWith(`/${normalizedUsage}`))return!0;if(normalizedUsage.endsWith(`/${normalizedActive}`))return!0;return!1}),violations=skillUsage.filter((e)=>e.complianceVerdict==="violated").length,violationRate=skillUsage.length>0?violations/skillUsage.length:0;if(violationRate>0.3){let reason=`auto-retire: violation rate ${(violationRate*100).toFixed(0)}% exceeds 30% threshold`;await _internals35.retireSkill(directory,active.slug,reason),observations.push(`Skill '${active.slug}' auto-retired: ${reason}`),warn(`[curator] ${observations[observations.length-1]}`);continue}let archivedSourceMatched=!1;if(allArchivedIds.size>0)try{let content=await _internals35.readFileAsync(active.path,"utf-8");archivedSourceMatched=(_internals35.parseDraftFrontmatter(content)?.sourceKnowledgeIds??[]).some((id)=>allArchivedIds.has(id))}catch{archivedSourceMatched=!1}if(archivedSourceMatched){let result=await _internals35.retireOrMarkStale(directory,path63.dirname(active.path),allArchivedIds);if(result.action==="retire")observations.push(`Skill '${active.slug}' auto-retired: all source knowledge entries archived`),warn(`[curator] ${observations[observations.length-1]}`);else if(result.action==="stale")observations.push(`Skill '${active.slug}' marked stale: some source knowledge entries archived`),warn(`[curator] ${observations[observations.length-1]}`)}}}catch(autoRetireErr){warn(`[curator] auto-retire health check failed: ${autoRetireErr instanceof Error?autoRetireErr.message:String(autoRetireErr)}`)}return observations}function parseKnowledgeRecommendations(llmOutput){return parseKnowledgeRecommendationsWithDiagnostics(llmOutput).recommendations}function parseKnowledgeRecommendationsWithDiagnostics(llmOutput){let recommendations=[],diagnostics=[],obsSection=llmOutput.match(/OBSERVATIONS:\s*\n([\s\S]*?)(?:\n\n|\n[A-Z_]+:|$)/);if(obsSection){let lines=obsSection[1].split(`
|
|
@@ -1729,8 +1729,8 @@ ${stackPrefix}`;return INFRASTRUCTURE_FAILURE_PATTERNS.some((pattern)=>pattern.t
|
|
|
1729
1729
|
`;await fs59.appendFile(trajectoryPath,line,"utf-8"),await truncateTrajectoryFile(trajectoryPath,maxLines)}catch{}try{await appendTrajectoryEntry(sessionId,entry,_directory,maxLines)}catch{}}}}function clearTrajectoryStep(sessionId){clearTrajectoryStepCounters(sessionId)}function summarizeArgs(args2,maxLength){if(!args2||Object.keys(args2).length===0)return"";let summaries=[];for(let[key,value]of Object.entries(args2)){if(SENSITIVE_FIELDS.has(key)||isSensitiveKey(key)){summaries.push(`${key}:[REDACTED]`);continue}if(value===null||value===void 0)summaries.push(`${key}:null`);else if(typeof value==="string"){let truncated=value.length>50?`${value.slice(0,50)}...`:value;summaries.push(`${key}:"${truncated}"`)}else if(typeof value==="number"||typeof value==="boolean")summaries.push(`${key}:${String(value)}`);else if(Array.isArray(value)){let itemSummary=value.length>3?`${value.slice(0,3).map(String).join(",")},...(+${value.length-3})`:value.map(String).join(",");summaries.push(`${key}:[${itemSummary}]`)}else if(typeof value==="object"){let keys=Object.keys(value);summaries.push(`${key}:{${keys.join(",")}}`)}else summaries.push(`${key}:${typeof value}`)}let summary=summaries.join(" ");return summary.length>maxLength?`${summary.slice(0,maxLength-3)}...`:summary}function deriveVerdict(output){if(output.metadata&&typeof output.metadata==="object"&&!Array.isArray(output.metadata)){let meta3=output.metadata;if(typeof meta3.verdict==="string"&&meta3.verdict.length>0)return meta3.verdict;if(meta3.success===!1||meta3.passed===!1)return"failure";if(meta3.success===!0||meta3.passed===!0)return"success"}let outputStr=String(output.output??"");if(outputStr.startsWith("Error:")||outputStr.startsWith("error:")||outputStr.startsWith("Error: "))return"failure";return"success"}var callStartTimes,SENSITIVE_FIELDS,SENSITIVE_SUBSTRINGS;var init_trajectory_logger=__esm(()=>{init_manager2();init_trajectory_store();init_state2();init_trajectory_step_state();init_utils2();callStartTimes=new Map,SENSITIVE_FIELDS=new Set(["password","token","secret","api_key","apikey","authorization","access_token","refresh_token","private_key","secret_key","credential","auth","bearer","x-api-key","session_id","cookie"]),SENSITIVE_SUBSTRINGS=["key","secret","token","password","auth","credential","private","certificate","bearer","session","cookie"]});function generateCourseCorrection(match,trajectory){let alert=`TRAJECTORY ALERT: ${match.pattern} detected (severity: ${match.severity}) at steps ${match.stepRange[0]}-${match.stepRange[1]}`,guidance=GUIDANCE_TEMPLATES[match.pattern],action=ACTION_TEMPLATES[match.pattern](match,trajectory);return{alert,category:match.category,guidance,action,pattern:match.pattern,stepRange:match.stepRange}}function formatCourseCorrectionForInjection(correction){return`${correction.alert}
|
|
1730
1730
|
CATEGORY: ${correction.category}
|
|
1731
1731
|
GUIDANCE: ${correction.guidance}
|
|
1732
|
-
ACTION: ${correction.action}`}var GUIDANCE_TEMPLATES,ACTION_TEMPLATES;var init_course_correction=__esm(()=>{GUIDANCE_TEMPLATES={repetition_loop:"Agent is repeating the same action on the same target. Consider consolidating changes, stepping back to review the approach, or delegating to a different agent.",ping_pong:"Agents are delegating back and forth without making progress. Consider having the architect take direct control or redefining the task boundaries.",expansion_drift:"Scope is expanding beyond the original task. Consider creating a follow-up task, reducing the current scope, or updating the spec.",stuck_on_test:"Repeated edit-test cycles detected. Consider reviewing the test expectations, checking for environmental issues, or seeking SME consultation.",context_thrash:"Agent is requesting increasingly large file sets. Consider focusing on the specific files needed for the current task or compacting context."},ACTION_TEMPLATES={repetition_loop:(match)=>{let agents=match.affectedAgents.length>0?match.affectedAgents.join(", "):"current agent";return`Stop repetitive edits to ${match.affectedTargets.length>0?match.affectedTargets.join(", "):"current target"} by ${agents}. Take a step back and consolidate the changes made so far before proceeding.`},ping_pong:()=>{return"Interrupt the delegation cycle. Architect should take direct control of the task or explicitly redefine which agent owns which subtask."},expansion_drift:()=>{return"Freeze current scope. Document what's been attempted and create a follow-up issue for additional work. Complete current task before expanding further."},stuck_on_test:(match)=>{return`Pause edit-test cycle. ${match.affectedAgents.length>0?match.affectedAgents.join(", "):"the agent"} should review test expectations, verify environment is clean, and consult SME if root cause is unclear.`},context_thrash:(match)=>{return`Restrict file access to only ${match.affectedTargets.length>0?match.affectedTargets.slice(0,3).join(", "):"requested files"}. Use targeted file selection instead of broad context requests.`}}});function createDefaultEscalationState(){return{patternCounts:new Map,escalationLevel:0,lastPatternDetected:null,hardStopPending:!1,correctionsPending:[]}}function cloneCourseCorrection(correction){return{...correction,stepRange:[...correction.stepRange]}}function cloneEscalationState(state){return{patternCounts:new Map(state.patternCounts),escalationLevel:state.escalationLevel,lastPatternDetected:state.lastPatternDetected?{...state.lastPatternDetected,stepRange:[...state.lastPatternDetected.stepRange],affectedAgents:[...state.lastPatternDetected.affectedAgents],affectedTargets:[...state.lastPatternDetected.affectedTargets]}:null,hardStopPending:state.hardStopPending,correctionsPending:state.correctionsPending.map(cloneCourseCorrection)}}function generateCorrection(match,level){let levelPrefix=level===1?"GUIDANCE":level===2?"STRONG GUIDANCE":"HARD STOP",alertTemplates={repetition_loop:`${levelPrefix}: Repetitive action loop detected`,ping_pong:`${levelPrefix}: Delegation ping-pong detected`,expansion_drift:`${levelPrefix}: Scope expansion drift detected`,stuck_on_test:`${levelPrefix}: Stuck in edit-test cycle`,context_thrash:`${levelPrefix}: Excessive context requests detected`},guidanceTemplates={repetition_loop:"Stop the repetitive loop. Consolidate changes and take a different approach.",ping_pong:"Interrupt the delegation cycle. Architect should take direct control.",expansion_drift:"Freeze scope expansion. Complete current task before adding more work.",stuck_on_test:"Pause edit-test cycle. Review test expectations and verify environment.",context_thrash:"Restrict file access. Use targeted selection instead of broad context requests."},actionTemplates={repetition_loop:"Consolidate changes and change approach immediately.",ping_pong:"Architect take direct control or redefine agent task boundaries.",expansion_drift:"Document progress and create follow-up issue for additional work.",stuck_on_test:"Review test expectations, verify environment, consult SME if needed.",context_thrash:"Restrict to only the specific files needed for the current task."};return{alert:alertTemplates[match.pattern],category:match.category,guidance:guidanceTemplates[match.pattern],action:actionTemplates[match.pattern],pattern:match.pattern,stepRange:match.stepRange}}class EscalationTracker{_sessionId;_state;constructor(sessionId,initialState){this._sessionId=sessionId,this._state=initialState??createDefaultEscalationState()}recordDetection(match){let newCount=(this._state.patternCounts.get(match.pattern)??0)+1;if(this._state.patternCounts.set(match.pattern,newCount),this._state.lastPatternDetected=match,newCount===1){let correction=generateCorrection(match,1);return this._state.correctionsPending.push(correction),this._state.escalationLevel=1,{level:1,correction,hardStop:!1}}else if(newCount===2){let correction=generateCorrection(match,2);return this._state.correctionsPending.push(correction),this._state.escalationLevel=2,telemetry.prmEscalationTriggered(this._sessionId,match.pattern,2,newCount),{level:2,correction,hardStop:!1}}else{let correction=generateCorrection(match,3);return this._state.correctionsPending.push(correction),this._state.escalationLevel=3,this._state.hardStopPending=!0,telemetry.prmHardStop(this._sessionId,match.pattern,3,newCount),{level:3,correction,hardStop:!0}}}getState(){return cloneEscalationState(this._state)}reset(){this._state=createDefaultEscalationState()}getPendingCorrections(){return this._state.correctionsPending.map(cloneCourseCorrection)}clearPendingCorrections(){this._state.correctionsPending=[]}isHardStopPending(){return this._state.hardStopPending}}var init_escalation=__esm(()=>{init_telemetry()});function sanitizeString2(input){if(!input||typeof input!=="string")return"";let result=input;result=result.replace(/[\n\r]/g,""),result=result.replace(/`/g,""),result=result.replace(/<[^>]*>/g,"");for(let pattern of INJECTION_PATTERNS2)result=result.replace(pattern,"[REDACTED]");if(result=result.trim(),result.length>200)result=`${result.slice(0,197)}...`;return result}function detectRepetitionLoop(trajectory,config3){let matches=[];if(trajectory.length<2)return matches;let windowSize=10,threshold=config3.pattern_thresholds?.repetition_loop??DEFAULT_THRESHOLDS.repetition_loop;for(let i=0;i<trajectory.length;i++){let windowStart=Math.max(0,i-windowSize+1),window2=trajectory.slice(windowStart,i+1),counts=new Map;for(let entry of window2){let key=`${entry.agent}|${entry.action}|${entry.target}`,existing=counts.get(key);if(existing)existing.count++,existing.endStep=entry.step;else counts.set(key,{count:1,startStep:entry.step,endStep:entry.step})}for(let[key,data]of counts)if(data.count>=threshold){let[agent,action,target]=key.split("|"),severity=data.count>=3?"high":"medium";matches.push({pattern:"repetition_loop",severity,category:"coordination_error",stepRange:[data.startStep,data.endStep],description:`Agent "${sanitizeString2(agent)}" performed "${sanitizeString2(action)}" on "${sanitizeString2(target)}" ${data.count} times within ${windowSize} steps`,affectedAgents:[sanitizeString2(agent)],affectedTargets:[sanitizeString2(target)],occurrenceCount:data.count})}}return matches}function detectPingPong(trajectory,config3){let matches=[],threshold=config3.pattern_thresholds?.ping_pong??DEFAULT_THRESHOLDS.ping_pong,minThreshold=3,effectiveThreshold=Math.max(threshold,3),delegateEntries=trajectory.filter((e)=>e.action==="delegate");if(delegateEntries.length<effectiveThreshold)return matches;let detectedPairs=new Set,i=0;while(i<delegateEntries.length){if(i+1>=delegateEntries.length)break;let firstAgent=delegateEntries[i].agent,secondAgent=delegateEntries[i+1].agent,target=delegateEntries[i].target;if(firstAgent===secondAgent){i++;continue}let endIndex=i+1;for(let j=i+2;j<delegateEntries.length;j++){let expectedAgent=(j-i)%2===0?firstAgent:secondAgent;if(delegateEntries[j].agent!==expectedAgent||delegateEntries[j].target!==target)break;endIndex=j}let patternLength=endIndex-i+1;if(patternLength>=effectiveThreshold){let pairKey2=`${[firstAgent,secondAgent].sort().join(",")}-${target}`;if(!detectedPairs.has(pairKey2)){detectedPairs.add(pairKey2);let roundTrips=Math.floor(patternLength/2);matches.push({pattern:"ping_pong",severity:"high",category:"coordination_error",stepRange:[delegateEntries[i].step,delegateEntries[endIndex].step],description:`Ping-pong delegation detected: "${sanitizeString2(firstAgent)}" and "${sanitizeString2(secondAgent)}" alternating on "${sanitizeString2(target)}"`,affectedAgents:[sanitizeString2(firstAgent),sanitizeString2(secondAgent)],affectedTargets:[sanitizeString2(target)],occurrenceCount:roundTrips})}i=endIndex+1}else i++}return matches}function detectExpansionDrift(trajectory,config3){let matches=[],threshold=config3.pattern_thresholds?.expansion_drift??DEFAULT_THRESHOLDS.expansion_drift,windowSize=Math.max(threshold,5),minTrajectoryLength=windowSize*2;if(trajectory.length<minTrajectoryLength)return matches;for(let i=windowSize*2;i<=trajectory.length;i+=windowSize){let recentWindow=trajectory.slice(i-windowSize,i),previousWindow=trajectory.slice(i-windowSize*2,i-windowSize),recentTargets=new Set(recentWindow.map((e)=>e.target)),previousTargets=new Set(previousWindow.map((e)=>e.target));if(previousTargets.size>0){let expansionRatio=recentTargets.size/previousTargets.size;if(expansionRatio>1.5)matches.push({pattern:"expansion_drift",severity:"medium",category:"specification_error",stepRange:[previousWindow[0].step,recentWindow[recentWindow.length-1].step],description:`Scope expansion detected: ${previousTargets.size} unique targets → ${recentTargets.size} unique targets (${expansionRatio.toFixed(1)}x increase)`,affectedAgents:[...new Set(recentWindow.map((e)=>sanitizeString2(e.agent)))],affectedTargets:[...recentTargets].map((t)=>sanitizeString2(t)),occurrenceCount:Math.floor(expansionRatio*10)/10})}}return matches}function detectStuckOnTest(trajectory,config3){let matches=[];if(trajectory.length<3)return matches;let threshold=config3.pattern_thresholds?.stuck_on_test??DEFAULT_THRESHOLDS.stuck_on_test,fileCycles=new Map;for(let i=0;i<trajectory.length;i++){let entry=trajectory[i];if(entry.action==="edit"){let existing=fileCycles.get(entry.target);if(existing){if(existing.edits++,existing.steps.push(entry.step),!existing.agents.includes(entry.agent))existing.agents.push(entry.agent)}else fileCycles.set(entry.target,{edits:1,tests:0,steps:[entry.step],agents:[entry.agent]})}else if(entry.action==="test"){let existing=fileCycles.get(entry.target);if(existing)existing.tests++}}for(let[file3,data]of fileCycles)if(data.edits>=threshold&&data.tests>=1){let cycleCount=0,lastEditStep=-1,lastTestStep=-1,cycleStart=-1,cycleEnd=-1;for(let i=0;i<trajectory.length;i++){let entry=trajectory[i];if(entry.target===file3){if(entry.action==="edit"){if(lastTestStep>lastEditStep&&lastEditStep>0){if(cycleCount++,cycleStart===-1)cycleStart=lastEditStep;cycleEnd=entry.step}lastEditStep=entry.step}else if(entry.action==="test"&&entry.result==="failure")lastTestStep=entry.step}}if(cycleCount>=threshold)matches.push({pattern:"stuck_on_test",severity:"high",category:"reasoning_error",stepRange:[cycleStart,cycleEnd],description:`Stuck on test detected: ${cycleCount} edit-test cycles on "${sanitizeString2(file3)}"`,affectedAgents:data.agents.map((a)=>sanitizeString2(a)),affectedTargets:[sanitizeString2(file3)],occurrenceCount:cycleCount})}return matches}function detectContextThrash(trajectory,config3){let matches=[];if(trajectory.length<2)return matches;let threshold=config3.pattern_thresholds?.context_thrash??DEFAULT_THRESHOLDS.context_thrash,seenTargets=new Set,cumulativeCounts=[];for(let entry of trajectory)seenTargets.add(entry.target),cumulativeCounts.push(seenTargets.size);let runStart=0,runLength=1;for(let i=1;i<=cumulativeCounts.length;i++)if(i<cumulativeCounts.length&&cumulativeCounts[i]>cumulativeCounts[i-1])runLength++;else{if(runLength>=threshold){let runEnd=i-1,priorCount=runStart>0?cumulativeCounts[runStart-1]:0,finalCount=cumulativeCounts[runEnd];matches.push({pattern:"context_thrash",severity:"medium",category:"coordination_error",stepRange:[trajectory[runStart].step,trajectory[runEnd].step],description:`Context thrash detected: unique targets grew monotonically from ${priorCount} to ${finalCount} over ${runLength} steps`,affectedAgents:[...new Set(trajectory.slice(runStart,runEnd+1).map((e)=>sanitizeString2(e.agent)))],affectedTargets:[...new Set(trajectory.slice(runStart,runEnd+1).map((e)=>sanitizeString2(e.target)))],occurrenceCount:runLength})}runStart=i,runLength=1}return matches}function detectPatterns(trajectory,config3,lastProcessedStep=0){let startTime=Date.now();if(config3.enabled===!1)return{matches:[],detectionTimeMs:0,patternsChecked:5};let allMatches=[];allMatches.push(...detectRepetitionLoop(trajectory,config3)),allMatches.push(...detectPingPong(trajectory,config3)),allMatches.push(...detectExpansionDrift(trajectory,config3)),allMatches.push(...detectStuckOnTest(trajectory,config3)),allMatches.push(...detectContextThrash(trajectory,config3));let detectionTimeMs=Date.now()-startTime,severityRank={critical:4,high:3,medium:2,low:1},dedupedMatches=new Map;for(let match of allMatches){let key=`${match.pattern}-${match.affectedAgents.join(",")}-${match.affectedTargets.join(",")}-${match.stepRange[0]}-${match.stepRange[1]}`,existing=dedupedMatches.get(key);if(!existing)dedupedMatches.set(key,match);else{let existingRank=severityRank[existing.severity]??0;if((severityRank[match.severity]??0)>existingRank)dedupedMatches.set(key,match)}}return{matches:Array.from(dedupedMatches.values()).filter((match)=>match.stepRange[1]>lastProcessedStep),detectionTimeMs,patternsChecked:5}}var INJECTION_PATTERNS2,DEFAULT_THRESHOLDS;var init_pattern_detector=__esm(()=>{INJECTION_PATTERNS2=[/\[SYSTEM\]/gi,/SYSTEM\s*OVERRIDE/gi,/IGNORE\s*PREVIOUS/gi,/IGNORE\s*ALL/gi,/NEW\s*INSTRUCTION/gi,/Override\s*instructions/gi,/\bJAILBREAK/gi,/\bDAN\s*MODE/gi,/\bBYPASS/gi];DEFAULT_THRESHOLDS={repetition_loop:2,ping_pong:2,expansion_drift:3,stuck_on_test:3,context_thrash:3}});import{promises as fs60}from"node:fs";import path116 from"node:path";function isPathSafe3(targetPath,basePath){let resolvedTarget=path116.resolve(targetPath),resolvedBase=path116.resolve(basePath),rel=path116.relative(resolvedBase,resolvedTarget);return!rel.startsWith("..")&&!path116.isAbsolute(rel)}function isWithinReplaysDir(targetPath){let parts=path116.resolve(targetPath).split(path116.sep);for(let i=0;i<parts.length-1;i++)if(parts[i]===".swarm"&&parts[i+1]==="replays")return!0;return!1}function sanitizeFilename(input){return input.replace(/[^a-zA-Z0-9_-]/g,"_")}async function startReplayRecording(sessionID,directory){try{let replayDir=path116.join(directory,".swarm","replays"),filename=`${sanitizeFilename(sessionID)}-${Date.now()}.jsonl`,filepath=path116.join(replayDir,filename);if(!isPathSafe3(filepath,replayDir))return console.warn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`),null;return await fs60.mkdir(replayDir,{recursive:!0}),filepath}catch(err){return console.warn(`[replay] Failed to start recording for session ${sessionID}: ${err}`),null}}async function recordReplayEntry(artifactPath,sessionID,entry){try{if(!isWithinReplaysDir(artifactPath)){console.warn(`[replay] Invalid artifact path - not within .swarm/replays/: ${artifactPath}`);return}let fullEntry={timestamp:new Date().toISOString(),sessionID,...entry},line=`${JSON.stringify(fullEntry)}
|
|
1733
|
-
`;await fs60.appendFile(artifactPath,line,"utf-8")}catch(err){
|
|
1732
|
+
ACTION: ${correction.action}`}var GUIDANCE_TEMPLATES,ACTION_TEMPLATES;var init_course_correction=__esm(()=>{GUIDANCE_TEMPLATES={repetition_loop:"Agent is repeating the same action on the same target. Consider consolidating changes, stepping back to review the approach, or delegating to a different agent.",ping_pong:"Agents are delegating back and forth without making progress. Consider having the architect take direct control or redefining the task boundaries.",expansion_drift:"Scope is expanding beyond the original task. Consider creating a follow-up task, reducing the current scope, or updating the spec.",stuck_on_test:"Repeated edit-test cycles detected. Consider reviewing the test expectations, checking for environmental issues, or seeking SME consultation.",context_thrash:"Agent is requesting increasingly large file sets. Consider focusing on the specific files needed for the current task or compacting context."},ACTION_TEMPLATES={repetition_loop:(match)=>{let agents=match.affectedAgents.length>0?match.affectedAgents.join(", "):"current agent";return`Stop repetitive edits to ${match.affectedTargets.length>0?match.affectedTargets.join(", "):"current target"} by ${agents}. Take a step back and consolidate the changes made so far before proceeding.`},ping_pong:()=>{return"Interrupt the delegation cycle. Architect should take direct control of the task or explicitly redefine which agent owns which subtask."},expansion_drift:()=>{return"Freeze current scope. Document what's been attempted and create a follow-up issue for additional work. Complete current task before expanding further."},stuck_on_test:(match)=>{return`Pause edit-test cycle. ${match.affectedAgents.length>0?match.affectedAgents.join(", "):"the agent"} should review test expectations, verify environment is clean, and consult SME if root cause is unclear.`},context_thrash:(match)=>{return`Restrict file access to only ${match.affectedTargets.length>0?match.affectedTargets.slice(0,3).join(", "):"requested files"}. Use targeted file selection instead of broad context requests.`}}});function createDefaultEscalationState(){return{patternCounts:new Map,escalationLevel:0,lastPatternDetected:null,hardStopPending:!1,correctionsPending:[]}}function cloneCourseCorrection(correction){return{...correction,stepRange:[...correction.stepRange]}}function cloneEscalationState(state){return{patternCounts:new Map(state.patternCounts),escalationLevel:state.escalationLevel,lastPatternDetected:state.lastPatternDetected?{...state.lastPatternDetected,stepRange:[...state.lastPatternDetected.stepRange],affectedAgents:[...state.lastPatternDetected.affectedAgents],affectedTargets:[...state.lastPatternDetected.affectedTargets]}:null,hardStopPending:state.hardStopPending,correctionsPending:state.correctionsPending.map(cloneCourseCorrection)}}function generateCorrection(match,level){let levelPrefix=level===1?"GUIDANCE":level===2?"STRONG GUIDANCE":"HARD STOP",alertTemplates={repetition_loop:`${levelPrefix}: Repetitive action loop detected`,ping_pong:`${levelPrefix}: Delegation ping-pong detected`,expansion_drift:`${levelPrefix}: Scope expansion drift detected`,stuck_on_test:`${levelPrefix}: Stuck in edit-test cycle`,context_thrash:`${levelPrefix}: Excessive context requests detected`},guidanceTemplates={repetition_loop:"Stop the repetitive loop. Consolidate changes and take a different approach.",ping_pong:"Interrupt the delegation cycle. Architect should take direct control.",expansion_drift:"Freeze scope expansion. Complete current task before adding more work.",stuck_on_test:"Pause edit-test cycle. Review test expectations and verify environment.",context_thrash:"Restrict file access. Use targeted selection instead of broad context requests."},actionTemplates={repetition_loop:"Consolidate changes and change approach immediately.",ping_pong:"Architect take direct control or redefine agent task boundaries.",expansion_drift:"Document progress and create follow-up issue for additional work.",stuck_on_test:"Review test expectations, verify environment, consult SME if needed.",context_thrash:"Restrict to only the specific files needed for the current task."};return{alert:alertTemplates[match.pattern],category:match.category,guidance:guidanceTemplates[match.pattern],action:actionTemplates[match.pattern],pattern:match.pattern,stepRange:match.stepRange}}class EscalationTracker{_sessionId;_state;constructor(sessionId,initialState){this._sessionId=sessionId,this._state=initialState??createDefaultEscalationState()}recordDetection(match){let newCount=(this._state.patternCounts.get(match.pattern)??0)+1;if(this._state.patternCounts.set(match.pattern,newCount),this._state.lastPatternDetected=match,newCount===1){let correction=generateCorrection(match,1);return this._state.correctionsPending.push(correction),this._state.escalationLevel=1,{level:1,correction,hardStop:!1}}else if(newCount===2){let correction=generateCorrection(match,2);return this._state.correctionsPending.push(correction),this._state.escalationLevel=2,telemetry.prmEscalationTriggered(this._sessionId,match.pattern,2,newCount),{level:2,correction,hardStop:!1}}else{let correction=generateCorrection(match,3);return this._state.correctionsPending.push(correction),this._state.escalationLevel=3,this._state.hardStopPending=!0,telemetry.prmHardStop(this._sessionId,match.pattern,3,newCount),{level:3,correction,hardStop:!0}}}getState(){return cloneEscalationState(this._state)}reset(){this._state=createDefaultEscalationState()}getPendingCorrections(){return this._state.correctionsPending.map(cloneCourseCorrection)}clearPendingCorrections(){this._state.correctionsPending=[]}isHardStopPending(){return this._state.hardStopPending}}var init_escalation=__esm(()=>{init_telemetry()});function sanitizeString2(input){if(!input||typeof input!=="string")return"";let result=input;result=result.replace(/[\n\r]/g,""),result=result.replace(/`/g,""),result=result.replace(/<[^>]*>/g,"");for(let pattern of INJECTION_PATTERNS2)result=result.replace(pattern,"[REDACTED]");if(result=result.trim(),result.length>200)result=`${result.slice(0,197)}...`;return result}function detectRepetitionLoop(trajectory,config3){let matches=[];if(trajectory.length<2)return matches;let windowSize=10,threshold=config3.pattern_thresholds?.repetition_loop??DEFAULT_THRESHOLDS.repetition_loop;for(let i=0;i<trajectory.length;i++){let windowStart=Math.max(0,i-windowSize+1),window2=trajectory.slice(windowStart,i+1),counts=new Map;for(let entry of window2){let key=`${entry.agent}|${entry.action}|${entry.target}`,existing=counts.get(key);if(existing)existing.count++,existing.endStep=entry.step;else counts.set(key,{count:1,startStep:entry.step,endStep:entry.step})}for(let[key,data]of counts)if(data.count>=threshold){let[agent,action,target]=key.split("|"),severity=data.count>=3?"high":"medium";matches.push({pattern:"repetition_loop",severity,category:"coordination_error",stepRange:[data.startStep,data.endStep],description:`Agent "${sanitizeString2(agent)}" performed "${sanitizeString2(action)}" on "${sanitizeString2(target)}" ${data.count} times within ${windowSize} steps`,affectedAgents:[sanitizeString2(agent)],affectedTargets:[sanitizeString2(target)],occurrenceCount:data.count})}}return matches}function detectPingPong(trajectory,config3){let matches=[],threshold=config3.pattern_thresholds?.ping_pong??DEFAULT_THRESHOLDS.ping_pong,minThreshold=3,effectiveThreshold=Math.max(threshold,3),delegateEntries=trajectory.filter((e)=>e.action==="delegate");if(delegateEntries.length<effectiveThreshold)return matches;let detectedPairs=new Set,i=0;while(i<delegateEntries.length){if(i+1>=delegateEntries.length)break;let firstAgent=delegateEntries[i].agent,secondAgent=delegateEntries[i+1].agent,target=delegateEntries[i].target;if(firstAgent===secondAgent){i++;continue}let endIndex=i+1;for(let j=i+2;j<delegateEntries.length;j++){let expectedAgent=(j-i)%2===0?firstAgent:secondAgent;if(delegateEntries[j].agent!==expectedAgent||delegateEntries[j].target!==target)break;endIndex=j}let patternLength=endIndex-i+1;if(patternLength>=effectiveThreshold){let pairKey2=`${[firstAgent,secondAgent].sort().join(",")}-${target}`;if(!detectedPairs.has(pairKey2)){detectedPairs.add(pairKey2);let roundTrips=Math.floor(patternLength/2);matches.push({pattern:"ping_pong",severity:"high",category:"coordination_error",stepRange:[delegateEntries[i].step,delegateEntries[endIndex].step],description:`Ping-pong delegation detected: "${sanitizeString2(firstAgent)}" and "${sanitizeString2(secondAgent)}" alternating on "${sanitizeString2(target)}"`,affectedAgents:[sanitizeString2(firstAgent),sanitizeString2(secondAgent)],affectedTargets:[sanitizeString2(target)],occurrenceCount:roundTrips})}i=endIndex+1}else i++}return matches}function detectExpansionDrift(trajectory,config3){let matches=[],threshold=config3.pattern_thresholds?.expansion_drift??DEFAULT_THRESHOLDS.expansion_drift,windowSize=Math.max(threshold,5),minTrajectoryLength=windowSize*2;if(trajectory.length<minTrajectoryLength)return matches;for(let i=windowSize*2;i<=trajectory.length;i+=windowSize){let recentWindow=trajectory.slice(i-windowSize,i),previousWindow=trajectory.slice(i-windowSize*2,i-windowSize),recentTargets=new Set(recentWindow.map((e)=>e.target)),previousTargets=new Set(previousWindow.map((e)=>e.target));if(previousTargets.size>0){let expansionRatio=recentTargets.size/previousTargets.size;if(expansionRatio>1.5)matches.push({pattern:"expansion_drift",severity:"medium",category:"specification_error",stepRange:[previousWindow[0].step,recentWindow[recentWindow.length-1].step],description:`Scope expansion detected: ${previousTargets.size} unique targets → ${recentTargets.size} unique targets (${expansionRatio.toFixed(1)}x increase)`,affectedAgents:[...new Set(recentWindow.map((e)=>sanitizeString2(e.agent)))],affectedTargets:[...recentTargets].map((t)=>sanitizeString2(t)),occurrenceCount:Math.floor(expansionRatio*10)/10})}}return matches}function detectStuckOnTest(trajectory,config3){let matches=[];if(trajectory.length<3)return matches;let threshold=config3.pattern_thresholds?.stuck_on_test??DEFAULT_THRESHOLDS.stuck_on_test,fileCycles=new Map;for(let i=0;i<trajectory.length;i++){let entry=trajectory[i];if(entry.action==="edit"){let existing=fileCycles.get(entry.target);if(existing){if(existing.edits++,existing.steps.push(entry.step),!existing.agents.includes(entry.agent))existing.agents.push(entry.agent)}else fileCycles.set(entry.target,{edits:1,tests:0,steps:[entry.step],agents:[entry.agent]})}else if(entry.action==="test"){let existing=fileCycles.get(entry.target);if(existing)existing.tests++}}for(let[file3,data]of fileCycles)if(data.edits>=threshold&&data.tests>=1){let cycleCount=0,lastEditStep=-1,lastTestStep=-1,cycleStart=-1,cycleEnd=-1;for(let i=0;i<trajectory.length;i++){let entry=trajectory[i];if(entry.target===file3){if(entry.action==="edit"){if(lastTestStep>lastEditStep&&lastEditStep>0){if(cycleCount++,cycleStart===-1)cycleStart=lastEditStep;cycleEnd=entry.step}lastEditStep=entry.step}else if(entry.action==="test"&&entry.result==="failure")lastTestStep=entry.step}}if(cycleCount>=threshold)matches.push({pattern:"stuck_on_test",severity:"high",category:"reasoning_error",stepRange:[cycleStart,cycleEnd],description:`Stuck on test detected: ${cycleCount} edit-test cycles on "${sanitizeString2(file3)}"`,affectedAgents:data.agents.map((a)=>sanitizeString2(a)),affectedTargets:[sanitizeString2(file3)],occurrenceCount:cycleCount})}return matches}function detectContextThrash(trajectory,config3){let matches=[];if(trajectory.length<2)return matches;let threshold=config3.pattern_thresholds?.context_thrash??DEFAULT_THRESHOLDS.context_thrash,seenTargets=new Set,cumulativeCounts=[];for(let entry of trajectory)seenTargets.add(entry.target),cumulativeCounts.push(seenTargets.size);let runStart=0,runLength=1;for(let i=1;i<=cumulativeCounts.length;i++)if(i<cumulativeCounts.length&&cumulativeCounts[i]>cumulativeCounts[i-1])runLength++;else{if(runLength>=threshold){let runEnd=i-1,priorCount=runStart>0?cumulativeCounts[runStart-1]:0,finalCount=cumulativeCounts[runEnd];matches.push({pattern:"context_thrash",severity:"medium",category:"coordination_error",stepRange:[trajectory[runStart].step,trajectory[runEnd].step],description:`Context thrash detected: unique targets grew monotonically from ${priorCount} to ${finalCount} over ${runLength} steps`,affectedAgents:[...new Set(trajectory.slice(runStart,runEnd+1).map((e)=>sanitizeString2(e.agent)))],affectedTargets:[...new Set(trajectory.slice(runStart,runEnd+1).map((e)=>sanitizeString2(e.target)))],occurrenceCount:runLength})}runStart=i,runLength=1}return matches}function detectPatterns(trajectory,config3,lastProcessedStep=0){let startTime=Date.now();if(config3.enabled===!1)return{matches:[],detectionTimeMs:0,patternsChecked:5};let allMatches=[];allMatches.push(...detectRepetitionLoop(trajectory,config3)),allMatches.push(...detectPingPong(trajectory,config3)),allMatches.push(...detectExpansionDrift(trajectory,config3)),allMatches.push(...detectStuckOnTest(trajectory,config3)),allMatches.push(...detectContextThrash(trajectory,config3));let detectionTimeMs=Date.now()-startTime,severityRank={critical:4,high:3,medium:2,low:1},dedupedMatches=new Map;for(let match of allMatches){let key=`${match.pattern}-${match.affectedAgents.join(",")}-${match.affectedTargets.join(",")}-${match.stepRange[0]}-${match.stepRange[1]}`,existing=dedupedMatches.get(key);if(!existing)dedupedMatches.set(key,match);else{let existingRank=severityRank[existing.severity]??0;if((severityRank[match.severity]??0)>existingRank)dedupedMatches.set(key,match)}}return{matches:Array.from(dedupedMatches.values()).filter((match)=>match.stepRange[1]>lastProcessedStep),detectionTimeMs,patternsChecked:5}}var INJECTION_PATTERNS2,DEFAULT_THRESHOLDS;var init_pattern_detector=__esm(()=>{INJECTION_PATTERNS2=[/\[SYSTEM\]/gi,/SYSTEM\s*OVERRIDE/gi,/IGNORE\s*PREVIOUS/gi,/IGNORE\s*ALL/gi,/NEW\s*INSTRUCTION/gi,/Override\s*instructions/gi,/\bJAILBREAK/gi,/\bDAN\s*MODE/gi,/\bBYPASS/gi];DEFAULT_THRESHOLDS={repetition_loop:2,ping_pong:2,expansion_drift:3,stuck_on_test:3,context_thrash:3}});import{promises as fs60}from"node:fs";import path116 from"node:path";function isPathSafe3(targetPath,basePath){let resolvedTarget=path116.resolve(targetPath),resolvedBase=path116.resolve(basePath),rel=path116.relative(resolvedBase,resolvedTarget);return!rel.startsWith("..")&&!path116.isAbsolute(rel)}function isWithinReplaysDir(targetPath){let parts=path116.resolve(targetPath).split(path116.sep);for(let i=0;i<parts.length-1;i++)if(parts[i]===".swarm"&&parts[i+1]==="replays")return!0;return!1}function sanitizeFilename(input){return input.replace(/[^a-zA-Z0-9_-]/g,"_")}async function startReplayRecording(sessionID,directory){try{let replayDir=path116.join(directory,".swarm","replays"),filename=`${sanitizeFilename(sessionID)}-${Date.now()}.jsonl`,filepath=path116.join(replayDir,filename);if(!isPathSafe3(filepath,replayDir))return advisoryWarn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`),null;return await fs60.mkdir(replayDir,{recursive:!0}),filepath}catch(err){return log(`[replay] Failed to start recording for session ${sessionID}: ${err}`),null}}async function recordReplayEntry(artifactPath,sessionID,entry){try{if(!isWithinReplaysDir(artifactPath)){log(`[replay] Invalid artifact path - not within .swarm/replays/: ${artifactPath}`);return}let fullEntry={timestamp:new Date().toISOString(),sessionID,...entry},line=`${JSON.stringify(fullEntry)}
|
|
1733
|
+
`;await fs60.appendFile(artifactPath,line,"utf-8")}catch(err){log(`[replay] Failed to record entry: ${err}`)}}var init_replay=__esm(()=>{init_warning_buffer();init_logger()});function resetPrmSessionState(session,sessionId){if(session.prmEscalationTracker=void 0,session.prmInitialized=!1,session.prmPatternCounts=new Map,session.prmEscalationLevel=0,session.prmLastPatternDetected=null,session.prmHardStopPending=!1,session.prmTrajectoryStep=0,session.replayArtifactPath=null,sessionId)_internals77.clearTrajectoryCache(sessionId)}function createPrmHook(config3,directory){async function toolAfter(context){if(!config3.enabled)return;let{sessionID}=context,session=_internals77.getAgentSession(sessionID);if(!session||!session.delegationActive)return;try{let cachedTrajectory=_internals77.getInMemoryTrajectory(sessionID),trajectory=cachedTrajectory.length>0?cachedTrajectory:await _internals77.readTrajectory(sessionID,directory),detectionResult=_internals77.detectPatterns(trajectory,config3,session.prmTrajectoryStep);if(detectionResult.matches.length===0)return;let sessionPrmState=session,escalationTracker=sessionPrmState.prmEscalationTracker;if(!sessionPrmState.replayArtifactPath)sessionPrmState.replayArtifactPath=await _internals77.startReplayRecording(sessionID,directory);let artifactPath=sessionPrmState.replayArtifactPath;if(!sessionPrmState.prmInitialized)sessionPrmState.prmInitialized=!0,_internals77.cleanupOldTrajectoryFiles(directory).catch(()=>{});if(!escalationTracker){let initialState=session.prmLastPatternDetected?{patternCounts:new Map(session.prmPatternCounts.entries()),escalationLevel:session.prmEscalationLevel,lastPatternDetected:session.prmLastPatternDetected,hardStopPending:session.prmHardStopPending,correctionsPending:[]}:void 0;escalationTracker=new EscalationTracker(sessionID,initialState),sessionPrmState.prmEscalationTracker=escalationTracker}let previousEscalationLevel=session.prmEscalationLevel;for(let match of detectionResult.matches){let correction=_internals77.generateCourseCorrection(match,trajectory),formattedCorrection=_internals77.formatCourseCorrectionForInjection(correction);if(!session.pendingAdvisoryMessages)session.pendingAdvisoryMessages=[];session.pendingAdvisoryMessages.push(formattedCorrection);let escalationLevel=0,hardStopPending=!1;if(config3.escalation_enabled!==!1){let escalationResult=escalationTracker.recordDetection(match);escalationLevel=escalationResult.level,hardStopPending=escalationResult.hardStop}if(session.prmPatternCounts.set(match.pattern,(session.prmPatternCounts.get(match.pattern)??0)+1),session.prmEscalationLevel=escalationLevel,session.prmLastPatternDetected=match,session.prmHardStopPending=hardStopPending,_internals77.telemetry.prmPatternDetected(sessionID,match.pattern,match.severity,match.category,match.stepRange),_internals77.telemetry.prmCourseCorrectionInjected(sessionID,match.pattern,escalationLevel),artifactPath)await _internals77.recordReplayEntry(artifactPath,sessionID,{type:"pattern_detected",data:{pattern:match.pattern,severity:match.severity,category:match.category,stepRange:match.stepRange,description:match.description,affectedAgents:match.affectedAgents,affectedTargets:match.affectedTargets,occurrenceCount:match.occurrenceCount}});if(artifactPath)await _internals77.recordReplayEntry(artifactPath,sessionID,{type:"course_correction",data:{pattern:correction.pattern,alert:correction.alert,category:correction.category,guidance:correction.guidance,action:correction.action,stepRange:correction.stepRange,escalationLevel}})}if(escalationTracker.clearPendingCorrections(),artifactPath&&session.prmEscalationLevel>previousEscalationLevel)await _internals77.recordReplayEntry(artifactPath,sessionID,{type:"escalation",data:{previousLevel:previousEscalationLevel,newLevel:session.prmEscalationLevel,hardStopPending:session.prmHardStopPending}});if(artifactPath&&session.prmHardStopPending&&previousEscalationLevel<3)await _internals77.recordReplayEntry(artifactPath,sessionID,{type:"hard_stop",data:{escalationLevel:session.prmEscalationLevel,triggeredAt:new Date().toISOString()}});if(trajectory.length>0)session.prmTrajectoryStep=trajectory[trajectory.length-1].step}catch(err){log(`[prm] toolAfter error for session ${sessionID}: ${err}`)}}return{toolAfter}}var _internals77;var init_prm=__esm(()=>{init_course_correction();init_escalation();init_pattern_detector();init_state2();init_telemetry();init_logger();init_course_correction();init_escalation();init_pattern_detector();init_replay();init_trajectory_store();_internals77={getAgentSession,readTrajectory,getInMemoryTrajectory,detectPatterns,generateCourseCorrection,formatCourseCorrectionForInjection,cleanupOldTrajectoryFiles,clearTrajectoryCache,recordReplayEntry,startReplayRecording,telemetry}});import*as fs61 from"node:fs";import*as path117 from"node:path";function errorMessage2(err){if(err instanceof Error)return err.message;return String(err)}async function handleResetSessionCommand(directory,_args){let results=[],statePath;try{if(statePath=validateSwarmPath(directory,"session/state.json"),fs61.existsSync(statePath))fs61.unlinkSync(statePath),results.push("✅ Deleted .swarm/session/state.json");else results.push("⏭️ state.json not found (already clean)")}catch{results.push("❌ Failed to delete state.json")}let sessionDir=statePath?path117.dirname(statePath):void 0,sessionFiles=[];if(sessionDir&&fs61.existsSync(sessionDir))try{sessionFiles=fs61.readdirSync(sessionDir)}catch(err){results.push(`❌ Failed to read session directory: ${errorMessage2(err)}`)}for(let file3 of sessionFiles){if(file3==="state.json")continue;let filePath=path117.join(sessionDir,file3);try{if(!fs61.existsSync(filePath))continue;if(!fs61.lstatSync(filePath).isFile())continue;fs61.unlinkSync(filePath),results.push(`✓ Deleted ${file3}`)}catch(err){results.push(`❌ Failed to delete ${file3}: ${errorMessage2(err)}`)}}let sessionCount=swarmState.agentSessions.size;for(let[sessionId,session]of swarmState.agentSessions)resetPrmSessionState(session,sessionId),clearTrajectoryStep(sessionId);swarmState.agentSessions.clear(),results.push(`✅ Cleared ${sessionCount} in-memory agent session(s)`);let chainCount=swarmState.delegationChains.size;swarmState.delegationChains.clear(),results.push(`✅ Cleared ${chainCount} delegation chain(s)`);let worktreesDir=path117.resolve(path117.dirname(directory),".swarm-worktrees");try{if(fs61.existsSync(worktreesDir))fs61.rmSync(worktreesDir,{recursive:!0,force:!0}),results.push("✅ Removed .swarm-worktrees/ directory")}catch(err){results.push(`⚠️ Failed to remove .swarm-worktrees/: ${errorMessage2(err)}`)}try{let branchResult=await _internals78.cleanupOrphanedBranches(directory,[]);if(branchResult.removed.length>0)results.push(`✅ Removed ${branchResult.removed.length} orphan swarm-lane branch(es)`);if(branchResult.errors.length>0)results.push(`⚠️ Failed to remove ${branchResult.errors.length} branch(es): ${branchResult.errors.map((e)=>e.error).join("; ")}`)}catch(err){results.push(`⚠️ Failed to cleanup orphan branches: ${errorMessage2(err)}`)}return["## Session State Reset","",...results,"","Session state cleared. Plan, evidence, and knowledge preserved.","","**All circuit breakers and revision limits have been cleared.** You can continue in this session — fresh state will be initialized automatically on the next tool call."].join(`
|
|
1734
1734
|
`)}var _internals78;var init_reset_session=__esm(()=>{init_trajectory_logger();init_utils2();init_prm();init_state2();init_merge();_internals78={cleanupOrphanedBranches}});import{mkdirSync as mkdirSync32,readdirSync as readdirSync18,renameSync as renameSync19,rmSync as rmSync8,statSync as statSync24}from"node:fs";import*as path118 from"node:path";function sanitizeSummaryId(id){if(!id||id.length===0)throw Error("Invalid summary ID: empty string");if(/\0/.test(id))throw Error("Invalid summary ID: contains null bytes");for(let i=0;i<id.length;i++)if(id.charCodeAt(i)<32)throw Error("Invalid summary ID: contains control characters");if(id.includes("..")||id.includes("../")||id.includes("..\\"))throw Error("Invalid summary ID: path traversal detected");if(!SUMMARY_ID_REGEX.test(id))throw Error(`Invalid summary ID: must match pattern ^S\\d+$, got "${id}"`);return id}async function storeSummary(directory,id,fullOutput,summaryText,maxStoredBytes){let sanitizedId=sanitizeSummaryId(id),preCheckEntry={id:sanitizedId,summaryText,fullOutput,timestamp:Date.now(),originalBytes:Buffer.byteLength(fullOutput,"utf8")},serializedSize=Buffer.byteLength(JSON.stringify(preCheckEntry),"utf8");if(serializedSize>maxStoredBytes)throw Error(`Summary entry size (${serializedSize} bytes) exceeds maximum (${maxStoredBytes} bytes)`);let relativePath=path118.join("summaries",`${sanitizedId}.json`),summaryPath=validateSwarmPath(directory,relativePath),summaryDir=path118.dirname(summaryPath),entry={id:sanitizedId,summaryText,fullOutput,timestamp:Date.now(),originalBytes:Buffer.byteLength(fullOutput,"utf8")},entryJson=JSON.stringify(entry);mkdirSync32(summaryDir,{recursive:!0});let tempPath=path118.join(summaryDir,`${sanitizedId}.json.tmp.${Date.now()}.${process.pid}`);try{await bunWrite(tempPath,entryJson),renameSync19(tempPath,summaryPath)}catch(error93){try{rmSync8(tempPath,{force:!0})}catch{}throw error93}}async function loadFullOutput(directory,id){let sanitizedId=sanitizeSummaryId(id),relativePath=path118.join("summaries",`${sanitizedId}.json`);validateSwarmPath(directory,relativePath);let content=await readSwarmFileAsync(directory,relativePath);if(content===null)return null;try{let parsed=JSON.parse(content);if(typeof parsed.fullOutput==="string")return parsed.fullOutput;return warn(`Summary entry ${sanitizedId} missing valid fullOutput field`),null}catch(error93){return warn(`Summary entry validation failed for ${sanitizedId}: ${error93 instanceof Error?error93.message:String(error93)}`),null}}var SUMMARY_ID_REGEX;var init_manager4=__esm(()=>{init_utils2();init_utils();init_bun_compat();SUMMARY_ID_REGEX=/^S\d+$/});async function handleRetrieveCommand(directory,args2){let summaryId=args2[0];if(!summaryId)return["## Swarm Retrieve","","Usage: `/swarm retrieve <id>`","","Example: `/swarm retrieve S1`","","Retrieves the full output that was replaced by a summary."].join(`
|
|
1735
1735
|
`);try{let fullOutput=await loadFullOutput(directory,summaryId);if(fullOutput===null)return`## Summary Not Found
|
|
1736
1736
|
|
|
@@ -1850,10 +1850,10 @@ INSTRUCTIONS: Re-summarise into a tighter format. Discard completed task details
|
|
|
1850
1850
|
[/CONTEXT COMPACTION]`}function buildEmergencyMessage(budgetPct,preserveLastN){return`[CONTEXT COMPACTION — EMERGENCY TIER]
|
|
1851
1851
|
`+`Context window is ${budgetPct.toFixed(1)}% used. EMERGENCY compaction required.
|
|
1852
1852
|
INSTRUCTIONS: Retain ONLY the system prompt, the current task context, and the last ${preserveLastN} conversation turns. Discard everything else. If you cannot complete the current task in the remaining context, escalate to the user.
|
|
1853
|
-
[/CONTEXT COMPACTION]`}function createCompactionService(config3,directory,injectMessage){return{toolAfter:async(_input,_output)=>{if(!config3.enabled)return;let budgetPct=swarmState.lastBudgetPct??0;if(budgetPct<=0)return;let sessionId=_input.sessionID,state=getSessionState(sessionId);try{if(budgetPct>=config3.emergencyThreshold&&budgetPct>state.lastEmergencyAt+5){state.lastEmergencyAt=budgetPct,state.emergencyCount++;let msg=buildEmergencyMessage(budgetPct,config3.preserveLastNTurns);appendSnapshot(directory,"emergency",budgetPct,msg),state.lastSnapshotAt=new Date().toISOString(),injectMessage(sessionId,msg);return}if(budgetPct>=config3.reflectionThreshold&&budgetPct>state.lastReflectionAt+5){state.lastReflectionAt=budgetPct,state.reflectionCount++;let msg=buildReflectionMessage(budgetPct);appendSnapshot(directory,"reflection",budgetPct,msg),state.lastSnapshotAt=new Date().toISOString(),injectMessage(sessionId,msg);return}if(budgetPct>=config3.observationThreshold&&budgetPct>state.lastObservationAt+5){state.lastObservationAt=budgetPct,state.observationCount++;let msg=buildObservationMessage(budgetPct);appendSnapshot(directory,"observation",budgetPct,msg),state.lastSnapshotAt=new Date().toISOString(),injectMessage(sessionId,msg)}}catch{}}}}function getCompactionMetrics(sessionId){if(sessionId){let state=getSessionState(sessionId);return{compactionCount:state.observationCount+state.reflectionCount+state.emergencyCount,lastSnapshotAt:state.lastSnapshotAt}}let total=0,lastSnapshot=null;for(let state of sessionStates.values())if(total+=state.observationCount+state.reflectionCount+state.emergencyCount,state.lastSnapshotAt&&(!lastSnapshot||state.lastSnapshotAt>lastSnapshot))lastSnapshot=state.lastSnapshotAt;return{compactionCount:total,lastSnapshotAt:lastSnapshot}}var sessionStates;var init_compaction_service=__esm(()=>{init_state2();sessionStates=new Map});async function readFileOrEmpty(filePath){for(let attempt=0;attempt<5;attempt++)try{return await readCachedTextFile(filePath,async()=>bunFile(filePath).text())??""}catch(err){if(err?.code!=="ENOENT"||attempt===4)return"";await new Promise((resolve48)=>setTimeout(resolve48,10))}return""}function estimateTokens2(text){if(!text||typeof text!=="string")return 0;return Math.ceil(text.length/3.5)}async function readBudgetState(directory){let content=await readSwarmFileAsync(directory,"session/budget-state.json");if(!content)return null;try{return JSON.parse(content)}catch{return null}}async function writeBudgetState(directory,state){try{let resolvedPath=validateSwarmPath(directory,"session/budget-state.json"),content=JSON.stringify(state,null,2);await bunWrite(resolvedPath,content)}catch(error93){
|
|
1853
|
+
[/CONTEXT COMPACTION]`}function createCompactionService(config3,directory,injectMessage){return{toolAfter:async(_input,_output)=>{if(!config3.enabled)return;let budgetPct=swarmState.lastBudgetPct??0;if(budgetPct<=0)return;let sessionId=_input.sessionID,state=getSessionState(sessionId);try{if(budgetPct>=config3.emergencyThreshold&&budgetPct>state.lastEmergencyAt+5){state.lastEmergencyAt=budgetPct,state.emergencyCount++;let msg=buildEmergencyMessage(budgetPct,config3.preserveLastNTurns);appendSnapshot(directory,"emergency",budgetPct,msg),state.lastSnapshotAt=new Date().toISOString(),injectMessage(sessionId,msg);return}if(budgetPct>=config3.reflectionThreshold&&budgetPct>state.lastReflectionAt+5){state.lastReflectionAt=budgetPct,state.reflectionCount++;let msg=buildReflectionMessage(budgetPct);appendSnapshot(directory,"reflection",budgetPct,msg),state.lastSnapshotAt=new Date().toISOString(),injectMessage(sessionId,msg);return}if(budgetPct>=config3.observationThreshold&&budgetPct>state.lastObservationAt+5){state.lastObservationAt=budgetPct,state.observationCount++;let msg=buildObservationMessage(budgetPct);appendSnapshot(directory,"observation",budgetPct,msg),state.lastSnapshotAt=new Date().toISOString(),injectMessage(sessionId,msg)}}catch{}}}}function getCompactionMetrics(sessionId){if(sessionId){let state=getSessionState(sessionId);return{compactionCount:state.observationCount+state.reflectionCount+state.emergencyCount,lastSnapshotAt:state.lastSnapshotAt}}let total=0,lastSnapshot=null;for(let state of sessionStates.values())if(total+=state.observationCount+state.reflectionCount+state.emergencyCount,state.lastSnapshotAt&&(!lastSnapshot||state.lastSnapshotAt>lastSnapshot))lastSnapshot=state.lastSnapshotAt;return{compactionCount:total,lastSnapshotAt:lastSnapshot}}var sessionStates;var init_compaction_service=__esm(()=>{init_state2();sessionStates=new Map});async function readFileOrEmpty(filePath){for(let attempt=0;attempt<5;attempt++)try{return await readCachedTextFile(filePath,async()=>bunFile(filePath).text())??""}catch(err){if(err?.code!=="ENOENT"||attempt===4)return"";await new Promise((resolve48)=>setTimeout(resolve48,10))}return""}function estimateTokens2(text){if(!text||typeof text!=="string")return 0;return Math.ceil(text.length/3.5)}async function readBudgetState(directory){let content=await readSwarmFileAsync(directory,"session/budget-state.json");if(!content)return null;try{return JSON.parse(content)}catch{return null}}async function writeBudgetState(directory,state){try{let resolvedPath=validateSwarmPath(directory,"session/budget-state.json"),content=JSON.stringify(state,null,2);await bunWrite(resolvedPath,content)}catch(error93){log("[context-budget] Failed to write budget state:",error93 instanceof Error?error93.message:String(error93))}}async function countEvents(directory){let content=await readSwarmFileAsync(directory,"events.jsonl");if(!content)return 0;return content.split(`
|
|
1854
1854
|
`).filter((line)=>line.trim().length>0).length}async function getPlanCursorContent(directory){let planContent=await readSwarmFileAsync(directory,"plan.md");if(!planContent)return"";let lines=planContent.split(`
|
|
1855
1855
|
`),cursorLines=[],inCurrentSection=!1;for(let line of lines){if(line.includes("in_progress")||line.includes("**Current**"))inCurrentSection=!0;if(inCurrentSection){if(cursorLines.push(line),cursorLines.length>30)break}}return cursorLines.join(`
|
|
1856
|
-
`)||planContent.substring(0,1000)}async function getContextBudgetReport(directory,assembledSystemPrompt,config3){validateDirectory(directory);let timestamp=new Date().toISOString(),systemPromptTokens=estimateTokens2(assembledSystemPrompt),planCursorContent=await getPlanCursorContent(directory),planCursorTokens=estimateTokens2(planCursorContent),knowledgeContent=await readFileOrEmpty(resolveSwarmKnowledgePath(directory)),knowledgeTokens=estimateTokens2(knowledgeContent),runMemoryContent=await readSwarmFileAsync(directory,"run-memory.jsonl"),runMemoryTokens=estimateTokens2(runMemoryContent||""),handoffContent=await readSwarmFileAsync(directory,"handoff.md"),handoffTokens=estimateTokens2(handoffContent||""),contextMdContent=await readSwarmFileAsync(directory,"context.md"),contextMdTokens=estimateTokens2(contextMdContent||""),swarmTotalTokens=systemPromptTokens+planCursorTokens+knowledgeTokens+runMemoryTokens+handoffTokens+contextMdTokens,estimatedTurnCount=await countEvents(directory),budgetPct=swarmTotalTokens/config3.budgetTokens*100,status,recommendation=null;if(budgetPct<config3.warningPct)status="ok";else if(budgetPct<config3.criticalPct)status="warning",recommendation="Consider wrapping up current phase and running /swarm handoff before starting new work.";else status="critical",recommendation="Run /swarm handoff and start a new session to avoid cost escalation.";let estimatedSessionTokens=swarmTotalTokens*Math.max(1,estimatedTurnCount);return{timestamp,systemPromptTokens,planCursorTokens,knowledgeTokens,runMemoryTokens,handoffTokens,contextMdTokens,swarmTotalTokens,estimatedTurnCount,estimatedSessionTokens,budgetPct,status,recommendation}}async function formatBudgetWarning(report,directory,config3){if(validateDirectory(directory),report.status==="ok")return null;if(!directory||directory.trim()==="")return formatWarningMessage(report);let state=await readBudgetState(directory)||{warningFiredAtTurn:null,criticalFiredAtTurn:null,lastInjectedAtTurn:null},currentTurn=report.estimatedTurnCount;if(report.status==="warning"){if(config3.warningMode==="once"&&state.warningFiredAtTurn!==null)return null;if(config3.warningMode==="interval"&&state.warningFiredAtTurn!==null&¤tTurn-state.warningFiredAtTurn<config3.warningIntervalTurns)return null;state.warningFiredAtTurn=currentTurn,state.lastInjectedAtTurn=currentTurn,await writeBudgetState(directory,state)}else if(report.status==="critical")state.criticalFiredAtTurn=currentTurn,state.lastInjectedAtTurn=currentTurn;return formatWarningMessage(report)}function formatWarningMessage(report){let budgetPctStr=report.budgetPct.toFixed(1),tokensPerTurn=report.swarmTotalTokens.toLocaleString();if(report.status==="warning")return`[CONTEXT BUDGET: ${budgetPctStr}% — swarm injecting ~${tokensPerTurn} tokens/turn. Consider wrapping current phase and running /swarm handoff before starting new work.]`;let costPerTurn=(report.swarmTotalTokens/1000*COST_PER_1K_TOKENS).toFixed(3);return`[CONTEXT BUDGET: ${budgetPctStr}% CRITICAL — swarm injecting ~${tokensPerTurn} tokens/turn. Run /swarm handoff and start a new session to avoid cost escalation. Estimated session cost scaling: ~$${costPerTurn}/turn at current context size.]`}var DEFAULT_CONTEXT_BUDGET_CONFIG,COST_PER_1K_TOKENS=0.003;var init_context_budget_service=__esm(()=>{init_knowledge_store();init_utils2();init_bun_compat();init_path_security();init_swarm_artifact_cache();DEFAULT_CONTEXT_BUDGET_CONFIG={enabled:!0,budgetTokens:40000,warningPct:70,criticalPct:90,warningMode:"once",warningIntervalTurns:20}});import*as fsSync9 from"node:fs";import{readFile as readFile27}from"node:fs/promises";import*as path123 from"node:path";function readSpecStalenessSnapshot(directory){try{let p=path123.join(directory,".swarm","spec-staleness.json");if(!fsSync9.existsSync(p))return{stale:!1};let raw=fsSync9.readFileSync(p,"utf-8"),parsed=JSON.parse(raw);return{stale:!0,reason:typeof parsed?.reason==="string"?parsed.reason:void 0,storedHash:typeof parsed?.specHash_plan==="string"?parsed.specHash_plan:void 0,currentHash:typeof parsed?.specHash_current==="string"||parsed?.specHash_current===null?parsed.specHash_current:void 0}}catch{return{stale:!1}}}async function getStatusData(directory,agents){let plan=await loadPlan(directory),status;if(plan&&plan.migration_status!=="migration_failed"){let currentPhase=extractCurrentPhaseFromPlan(plan)||"Unknown",completedTasks=0,totalTasks=0;for(let phase of plan.phases)for(let task of phase.tasks)if(totalTasks++,task.status==="completed")completedTasks++;let agentCount=Object.keys(agents).length,metrics=getCompactionMetrics();status={hasPlan:!0,currentPhase,completedTasks,totalTasks,agentCount,isLegacy:!1,turboMode:hasActiveTurboMode(),contextBudgetPct:swarmState.lastBudgetPct>0?swarmState.lastBudgetPct:null,compactionCount:metrics.compactionCount,lastSnapshotAt:metrics.lastSnapshotAt}}else{let planContent=await readSwarmFileAsync(directory,"plan.md");if(!planContent){let metrics=getCompactionMetrics();status={hasPlan:!1,currentPhase:"Unknown",completedTasks:0,totalTasks:0,agentCount:Object.keys(agents).length,isLegacy:!0,turboMode:hasActiveTurboMode(),contextBudgetPct:swarmState.lastBudgetPct>0?swarmState.lastBudgetPct:null,compactionCount:metrics.compactionCount,lastSnapshotAt:metrics.lastSnapshotAt}}else{let currentPhase=extractCurrentPhase(planContent)||"Unknown",completedTasks=(planContent.match(/^- \[x\]/gm)||[]).length,incompleteTasks=(planContent.match(/^- \[ \]/gm)||[]).length,totalTasks=completedTasks+incompleteTasks,agentCount=Object.keys(agents).length,metrics=getCompactionMetrics();status={hasPlan:!0,currentPhase,completedTasks,totalTasks,agentCount,isLegacy:!0,turboMode:hasActiveTurboMode(),contextBudgetPct:swarmState.lastBudgetPct>0?swarmState.lastBudgetPct:null,compactionCount:metrics.compactionCount,lastSnapshotAt:metrics.lastSnapshotAt}}}let drift=readSpecStalenessSnapshot(directory);if(drift.stale)status.specStale=!0,status.specStaleReason=drift.reason,status.specStaleStoredHash=drift.storedHash,status.specStaleCurrentHash=drift.currentHash;else if(plan&&plan._specStale)status.specStale=!0,status.specStaleReason=plan._specStaleReason;if(status.recentEscalations=await readRecentEscalations(directory),status.pendingProposals=await countProposals(directory),status.unactionableQueueDepth=await safeLineCount(resolveUnactionablePath(directory)),status.insightCandidatesPending=await safeLineCount(validateSwarmPath(directory,"insight-candidates.jsonl")),status.fullAutoActive=_internals80.hasActiveFullAuto(),status.fullAutoActive){let sid=_internals80.getActiveFullAutoSessionID();if(sid){let runState=_internals80.loadFullAutoRunState(directory,sid);if(runState?.lastEscalation)status.fullAutoEscalation={reason:runState.lastEscalation.reason,interactionCount:runState.lastEscalation.interactionCount,deadlockCount:runState.lastEscalation.deadlockCount,phase:runState.lastEscalation.phase}}}return enrichWithLeanTurbo(status,directory)}function enrichWithLeanTurbo(status,directory){let turboMode=hasActiveTurboMode(),leanActive=_internals80.hasActiveLeanTurbo(),turboStrategy="off";if(leanActive)turboStrategy="lean";else if(turboMode)turboStrategy="standard";if(status.turboStrategy=turboStrategy,!leanActive)return status;let leanSessionID=null;for(let[sessionId,session]of swarmState.agentSessions)if(session.turboStrategy==="lean"&&session.leanTurboActive===!0){leanSessionID=sessionId;break}if(leanSessionID){let runState=_internals80.loadLeanTurboRunState(directory,leanSessionID);if(runState){if(status.leanTurboPhase=runState.phase,status.leanMaxParallelCoders=runState.maxParallelCoders,status.leanPauseReason=runState.pauseReason,!Array.isArray(runState.lanes))runState.lanes=[];let activeLanes=0,completedLanes=0;for(let lane of runState.lanes){if(lane.status==="running")activeLanes++;if(lane.status==="completed")completedLanes++}if(status.leanActiveLaneCount=activeLanes,status.leanCompletedLanes=completedLanes,!Array.isArray(runState.degradedTasks))runState.degradedTasks=[],status.leanDegradedTasks=0;if(runState.degradedTasks.length>0){status.leanDegradedTasks=runState.degradedTasks.length;let summaryParts=[];for(let dt of runState.degradedTasks)summaryParts.push(`${dt.taskId} (${dt.reason})`);status.leanDegradationSummary=summaryParts.join("; ")}}}return status}function formatStatusMarkdown(status){let lines=["## Swarm Status","",`**Current Phase**: ${status.currentPhase}`,`**Tasks**: ${status.completedTasks}/${status.totalTasks} complete`,`**Agents**: ${status.agentCount} registered`];if(status.specStale){let reason=status.specStaleReason??"spec.md changed since plan saved",stored=status.specStaleStoredHash??"unknown",current=status.specStaleCurrentHash??"(spec.md missing)";lines.push("",`**Spec drift detected**: ${reason} (stored: ${stored}, current: ${current})`,"Run `/swarm clarify` to update the spec or `/swarm acknowledge-spec-drift` to dismiss.")}if(status.turboStrategy&&status.turboStrategy!=="off")if(lines.push(""),status.turboStrategy==="lean"){let parts=["lean"];if(status.leanTurboPhase!==void 0)parts.push(`Phase ${status.leanTurboPhase}`);if(status.leanActiveLaneCount!==void 0){let totalLanes=(status.leanActiveLaneCount??0)+(status.leanCompletedLanes??0);parts.push(`${status.leanActiveLaneCount}/${totalLanes} lanes active`)}if(status.leanDegradedTasks!==void 0&&status.leanDegradedTasks>0)parts.push(`${status.leanDegradedTasks} degraded`);if(lines.push(`**Turbo**: ${parts.join(", ")}`),status.leanDegradationSummary)lines.push(` - ${status.leanDegradationSummary}`);if(status.leanPauseReason)lines.push(`**Lean paused**: ${status.leanPauseReason}`)}else lines.push("**Turbo**: standard");else if(status.turboStrategy===void 0&&status.turboMode===!0)lines.push(""),lines.push("**TURBO MODE**: active");if(status.fullAutoActive){if(lines.push(""),lines.push("**Full-Auto**: active"),status.fullAutoEscalation){let e=status.fullAutoEscalation,phaseStr=e.phase!==void 0?` | Phase ${e.phase}`:"";lines.push(` - Escalation: ${e.reason} (interactions=${e.interactionCount}, deadlocks=${e.deadlockCount}${phaseStr})`)}}if(status.contextBudgetPct!==null&&status.contextBudgetPct>0){let pct=status.contextBudgetPct.toFixed(1),budgetTokens=DEFAULT_CONTEXT_BUDGET_CONFIG.budgetTokens,est=Math.round(status.contextBudgetPct/100*budgetTokens);if(lines.push("",`**Context**: ${pct}% used (est. ${est.toLocaleString()} / ${budgetTokens.toLocaleString()} tokens)`),status.compactionCount>0)lines.push(`**Compaction events**: ${status.compactionCount} triggered`);if(status.lastSnapshotAt)lines.push(`**Last snapshot**: ${status.lastSnapshotAt}`)}if(status.recentEscalations&&status.recentEscalations.length>0){lines.push("","**Recently Escalated (last 7 days)**:");for(let e of status.recentEscalations)lines.push(` - ${e.entry_id} (${e.from}→${e.to}) reason=${e.reason}`)}let proposals=status.pendingProposals??0,unactionable=status.unactionableQueueDepth??0,insights=status.insightCandidatesPending??0;if(proposals>0||unactionable>0||insights>0){if(lines.push("","**Learning Queues**:"),proposals>0)lines.push(` - Pending proposals: ${proposals} (review with \`/swarm skill list\`)`);if(unactionable>0)lines.push(` - Unactionable queue: ${unactionable} (inspect with \`/swarm knowledge unactionable\`)`);if(insights>0)lines.push(` - Insight candidates: ${insights} (consumed at phase end)`)}return lines.join(`
|
|
1856
|
+
`)||planContent.substring(0,1000)}async function getContextBudgetReport(directory,assembledSystemPrompt,config3){validateDirectory(directory);let timestamp=new Date().toISOString(),systemPromptTokens=estimateTokens2(assembledSystemPrompt),planCursorContent=await getPlanCursorContent(directory),planCursorTokens=estimateTokens2(planCursorContent),knowledgeContent=await readFileOrEmpty(resolveSwarmKnowledgePath(directory)),knowledgeTokens=estimateTokens2(knowledgeContent),runMemoryContent=await readSwarmFileAsync(directory,"run-memory.jsonl"),runMemoryTokens=estimateTokens2(runMemoryContent||""),handoffContent=await readSwarmFileAsync(directory,"handoff.md"),handoffTokens=estimateTokens2(handoffContent||""),contextMdContent=await readSwarmFileAsync(directory,"context.md"),contextMdTokens=estimateTokens2(contextMdContent||""),swarmTotalTokens=systemPromptTokens+planCursorTokens+knowledgeTokens+runMemoryTokens+handoffTokens+contextMdTokens,estimatedTurnCount=await countEvents(directory),budgetPct=swarmTotalTokens/config3.budgetTokens*100,status,recommendation=null;if(budgetPct<config3.warningPct)status="ok";else if(budgetPct<config3.criticalPct)status="warning",recommendation="Consider wrapping up current phase and running /swarm handoff before starting new work.";else status="critical",recommendation="Run /swarm handoff and start a new session to avoid cost escalation.";let estimatedSessionTokens=swarmTotalTokens*Math.max(1,estimatedTurnCount);return{timestamp,systemPromptTokens,planCursorTokens,knowledgeTokens,runMemoryTokens,handoffTokens,contextMdTokens,swarmTotalTokens,estimatedTurnCount,estimatedSessionTokens,budgetPct,status,recommendation}}async function formatBudgetWarning(report,directory,config3){if(validateDirectory(directory),report.status==="ok")return null;if(!directory||directory.trim()==="")return formatWarningMessage(report);let state=await readBudgetState(directory)||{warningFiredAtTurn:null,criticalFiredAtTurn:null,lastInjectedAtTurn:null},currentTurn=report.estimatedTurnCount;if(report.status==="warning"){if(config3.warningMode==="once"&&state.warningFiredAtTurn!==null)return null;if(config3.warningMode==="interval"&&state.warningFiredAtTurn!==null&¤tTurn-state.warningFiredAtTurn<config3.warningIntervalTurns)return null;state.warningFiredAtTurn=currentTurn,state.lastInjectedAtTurn=currentTurn,await writeBudgetState(directory,state)}else if(report.status==="critical")state.criticalFiredAtTurn=currentTurn,state.lastInjectedAtTurn=currentTurn;return formatWarningMessage(report)}function formatWarningMessage(report){let budgetPctStr=report.budgetPct.toFixed(1),tokensPerTurn=report.swarmTotalTokens.toLocaleString();if(report.status==="warning")return`[CONTEXT BUDGET: ${budgetPctStr}% — swarm injecting ~${tokensPerTurn} tokens/turn. Consider wrapping current phase and running /swarm handoff before starting new work.]`;let costPerTurn=(report.swarmTotalTokens/1000*COST_PER_1K_TOKENS).toFixed(3);return`[CONTEXT BUDGET: ${budgetPctStr}% CRITICAL — swarm injecting ~${tokensPerTurn} tokens/turn. Run /swarm handoff and start a new session to avoid cost escalation. Estimated session cost scaling: ~$${costPerTurn}/turn at current context size.]`}var DEFAULT_CONTEXT_BUDGET_CONFIG,COST_PER_1K_TOKENS=0.003;var init_context_budget_service=__esm(()=>{init_knowledge_store();init_utils2();init_bun_compat();init_logger();init_path_security();init_swarm_artifact_cache();DEFAULT_CONTEXT_BUDGET_CONFIG={enabled:!0,budgetTokens:40000,warningPct:70,criticalPct:90,warningMode:"once",warningIntervalTurns:20}});import*as fsSync9 from"node:fs";import{readFile as readFile27}from"node:fs/promises";import*as path123 from"node:path";function readSpecStalenessSnapshot(directory){try{let p=path123.join(directory,".swarm","spec-staleness.json");if(!fsSync9.existsSync(p))return{stale:!1};let raw=fsSync9.readFileSync(p,"utf-8"),parsed=JSON.parse(raw);return{stale:!0,reason:typeof parsed?.reason==="string"?parsed.reason:void 0,storedHash:typeof parsed?.specHash_plan==="string"?parsed.specHash_plan:void 0,currentHash:typeof parsed?.specHash_current==="string"||parsed?.specHash_current===null?parsed.specHash_current:void 0}}catch{return{stale:!1}}}async function getStatusData(directory,agents){let plan=await loadPlan(directory),status;if(plan&&plan.migration_status!=="migration_failed"){let currentPhase=extractCurrentPhaseFromPlan(plan)||"Unknown",completedTasks=0,totalTasks=0;for(let phase of plan.phases)for(let task of phase.tasks)if(totalTasks++,task.status==="completed")completedTasks++;let agentCount=Object.keys(agents).length,metrics=getCompactionMetrics();status={hasPlan:!0,currentPhase,completedTasks,totalTasks,agentCount,isLegacy:!1,turboMode:hasActiveTurboMode(),contextBudgetPct:swarmState.lastBudgetPct>0?swarmState.lastBudgetPct:null,compactionCount:metrics.compactionCount,lastSnapshotAt:metrics.lastSnapshotAt}}else{let planContent=await readSwarmFileAsync(directory,"plan.md");if(!planContent){let metrics=getCompactionMetrics();status={hasPlan:!1,currentPhase:"Unknown",completedTasks:0,totalTasks:0,agentCount:Object.keys(agents).length,isLegacy:!0,turboMode:hasActiveTurboMode(),contextBudgetPct:swarmState.lastBudgetPct>0?swarmState.lastBudgetPct:null,compactionCount:metrics.compactionCount,lastSnapshotAt:metrics.lastSnapshotAt}}else{let currentPhase=extractCurrentPhase(planContent)||"Unknown",completedTasks=(planContent.match(/^- \[x\]/gm)||[]).length,incompleteTasks=(planContent.match(/^- \[ \]/gm)||[]).length,totalTasks=completedTasks+incompleteTasks,agentCount=Object.keys(agents).length,metrics=getCompactionMetrics();status={hasPlan:!0,currentPhase,completedTasks,totalTasks,agentCount,isLegacy:!0,turboMode:hasActiveTurboMode(),contextBudgetPct:swarmState.lastBudgetPct>0?swarmState.lastBudgetPct:null,compactionCount:metrics.compactionCount,lastSnapshotAt:metrics.lastSnapshotAt}}}let drift=readSpecStalenessSnapshot(directory);if(drift.stale)status.specStale=!0,status.specStaleReason=drift.reason,status.specStaleStoredHash=drift.storedHash,status.specStaleCurrentHash=drift.currentHash;else if(plan&&plan._specStale)status.specStale=!0,status.specStaleReason=plan._specStaleReason;if(status.recentEscalations=await readRecentEscalations(directory),status.pendingProposals=await countProposals(directory),status.unactionableQueueDepth=await safeLineCount(resolveUnactionablePath(directory)),status.insightCandidatesPending=await safeLineCount(validateSwarmPath(directory,"insight-candidates.jsonl")),status.fullAutoActive=_internals80.hasActiveFullAuto(),status.fullAutoActive){let sid=_internals80.getActiveFullAutoSessionID();if(sid){let runState=_internals80.loadFullAutoRunState(directory,sid);if(runState?.lastEscalation)status.fullAutoEscalation={reason:runState.lastEscalation.reason,interactionCount:runState.lastEscalation.interactionCount,deadlockCount:runState.lastEscalation.deadlockCount,phase:runState.lastEscalation.phase}}}return enrichWithLeanTurbo(status,directory)}function enrichWithLeanTurbo(status,directory){let turboMode=hasActiveTurboMode(),leanActive=_internals80.hasActiveLeanTurbo(),turboStrategy="off";if(leanActive)turboStrategy="lean";else if(turboMode)turboStrategy="standard";if(status.turboStrategy=turboStrategy,!leanActive)return status;let leanSessionID=null;for(let[sessionId,session]of swarmState.agentSessions)if(session.turboStrategy==="lean"&&session.leanTurboActive===!0){leanSessionID=sessionId;break}if(leanSessionID){let runState=_internals80.loadLeanTurboRunState(directory,leanSessionID);if(runState){if(status.leanTurboPhase=runState.phase,status.leanMaxParallelCoders=runState.maxParallelCoders,status.leanPauseReason=runState.pauseReason,!Array.isArray(runState.lanes))runState.lanes=[];let activeLanes=0,completedLanes=0;for(let lane of runState.lanes){if(lane.status==="running")activeLanes++;if(lane.status==="completed")completedLanes++}if(status.leanActiveLaneCount=activeLanes,status.leanCompletedLanes=completedLanes,!Array.isArray(runState.degradedTasks))runState.degradedTasks=[],status.leanDegradedTasks=0;if(runState.degradedTasks.length>0){status.leanDegradedTasks=runState.degradedTasks.length;let summaryParts=[];for(let dt of runState.degradedTasks)summaryParts.push(`${dt.taskId} (${dt.reason})`);status.leanDegradationSummary=summaryParts.join("; ")}}}return status}function formatStatusMarkdown(status){let lines=["## Swarm Status","",`**Current Phase**: ${status.currentPhase}`,`**Tasks**: ${status.completedTasks}/${status.totalTasks} complete`,`**Agents**: ${status.agentCount} registered`];if(status.specStale){let reason=status.specStaleReason??"spec.md changed since plan saved",stored=status.specStaleStoredHash??"unknown",current=status.specStaleCurrentHash??"(spec.md missing)";lines.push("",`**Spec drift detected**: ${reason} (stored: ${stored}, current: ${current})`,"Run `/swarm clarify` to update the spec or `/swarm acknowledge-spec-drift` to dismiss.")}if(status.turboStrategy&&status.turboStrategy!=="off")if(lines.push(""),status.turboStrategy==="lean"){let parts=["lean"];if(status.leanTurboPhase!==void 0)parts.push(`Phase ${status.leanTurboPhase}`);if(status.leanActiveLaneCount!==void 0){let totalLanes=(status.leanActiveLaneCount??0)+(status.leanCompletedLanes??0);parts.push(`${status.leanActiveLaneCount}/${totalLanes} lanes active`)}if(status.leanDegradedTasks!==void 0&&status.leanDegradedTasks>0)parts.push(`${status.leanDegradedTasks} degraded`);if(lines.push(`**Turbo**: ${parts.join(", ")}`),status.leanDegradationSummary)lines.push(` - ${status.leanDegradationSummary}`);if(status.leanPauseReason)lines.push(`**Lean paused**: ${status.leanPauseReason}`)}else lines.push("**Turbo**: standard");else if(status.turboStrategy===void 0&&status.turboMode===!0)lines.push(""),lines.push("**TURBO MODE**: active");if(status.fullAutoActive){if(lines.push(""),lines.push("**Full-Auto**: active"),status.fullAutoEscalation){let e=status.fullAutoEscalation,phaseStr=e.phase!==void 0?` | Phase ${e.phase}`:"";lines.push(` - Escalation: ${e.reason} (interactions=${e.interactionCount}, deadlocks=${e.deadlockCount}${phaseStr})`)}}if(status.contextBudgetPct!==null&&status.contextBudgetPct>0){let pct=status.contextBudgetPct.toFixed(1),budgetTokens=DEFAULT_CONTEXT_BUDGET_CONFIG.budgetTokens,est=Math.round(status.contextBudgetPct/100*budgetTokens);if(lines.push("",`**Context**: ${pct}% used (est. ${est.toLocaleString()} / ${budgetTokens.toLocaleString()} tokens)`),status.compactionCount>0)lines.push(`**Compaction events**: ${status.compactionCount} triggered`);if(status.lastSnapshotAt)lines.push(`**Last snapshot**: ${status.lastSnapshotAt}`)}if(status.recentEscalations&&status.recentEscalations.length>0){lines.push("","**Recently Escalated (last 7 days)**:");for(let e of status.recentEscalations)lines.push(` - ${e.entry_id} (${e.from}→${e.to}) reason=${e.reason}`)}let proposals=status.pendingProposals??0,unactionable=status.unactionableQueueDepth??0,insights=status.insightCandidatesPending??0;if(proposals>0||unactionable>0||insights>0){if(lines.push("","**Learning Queues**:"),proposals>0)lines.push(` - Pending proposals: ${proposals} (review with \`/swarm skill list\`)`);if(unactionable>0)lines.push(` - Unactionable queue: ${unactionable} (inspect with \`/swarm knowledge unactionable\`)`);if(insights>0)lines.push(` - Insight candidates: ${insights} (consumed at phase end)`)}return lines.join(`
|
|
1857
1857
|
`)}async function handleStatusCommand(directory,agents){let statusData=await getStatusData(directory,agents);if(!statusData.hasPlan){if(statusData.specStale){let reason=statusData.specStaleReason??"spec.md changed since plan saved",stored=statusData.specStaleStoredHash??"unknown",current=statusData.specStaleCurrentHash??"(spec.md missing)";return["No active swarm plan found.","",`**Spec drift detected**: ${reason} (stored: ${stored}, current: ${current})`,"Run `/swarm clarify` to update the spec or `/swarm acknowledge-spec-drift` to dismiss."].join(`
|
|
1858
1858
|
`)}return"No active swarm plan found."}return formatStatusMarkdown(statusData)}async function safeLineCount(filePath){try{if(!fsSync9.existsSync(filePath))return 0;let content=await readFile27(filePath,"utf-8"),n=0;for(let line of content.split(`
|
|
1859
1859
|
`))if(line.trim())n++;return n}catch{return 0}}async function countProposals(directory){try{let proposalsDir=validateSwarmPath(directory,"skills/proposals");if(!fsSync9.existsSync(proposalsDir))return 0;let{readdir:readdir8}=await import("node:fs/promises");return(await readdir8(proposalsDir)).filter((f)=>f.endsWith(".md")).length}catch{return 0}}var _internals80;var init_status_service=__esm(()=>{init_state3();init_extractors();init_knowledge_escalator();init_knowledge_validator();init_utils2();init_manager();init_state2();init_state4();init_compaction_service();init_context_budget_service();_internals80={loadLeanTurboRunState,hasActiveLeanTurbo,hasActiveFullAuto,getActiveFullAutoSessionID,loadFullAutoRunState}});var init_status=__esm(()=>{init_status_service()});async function handleSyncPlanCommand(directory,_args){let plan=await loadPlan(directory);if(!plan)return`## Plan Sync Report
|
|
@@ -5566,7 +5566,7 @@ ${checkpointMsg}
|
|
|
5566
5566
|
Recommendation: Consider escalating to user or taking a different approach
|
|
5567
5567
|
The current fix strategy appears to be cycling without progress`;return{eventLogged,checkpointCreated,message}}var recentToolCallsBySession=new Map,lastSpiralTimestampBySession=new Map,MAX_RECENT_CALLS=20,SPIRAL_THRESHOLD=5,SPIRAL_WINDOW_MS=300000,SPIRAL_COOLDOWN_MS=60000,MAX_TRACKED_SESSIONS3=500;function recordToolCall(tool3,args2,sessionId){let argsHash=typeof args2==="string"?args2.slice(0,100):JSON.stringify(args2??"").slice(0,100),calls=recentToolCallsBySession.get(sessionId);if(!calls)calls=[],recentToolCallsBySession.set(sessionId,calls);if(calls.push({tool:tool3,argsHash,timestamp:Date.now()}),calls.length>MAX_RECENT_CALLS)calls.shift()}async function detectDebuggingSpiral(_directory,sessionId){let now=Date.now(),lastTrigger=lastSpiralTimestampBySession.get(sessionId)??0;if(now-lastTrigger<SPIRAL_COOLDOWN_MS)return null;let windowCalls=(recentToolCallsBySession.get(sessionId)??[]).filter((c)=>now-c.timestamp<SPIRAL_WINDOW_MS);if(windowCalls.length<SPIRAL_THRESHOLD)return null;let lastN=windowCalls.slice(-SPIRAL_THRESHOLD),firstTool=lastN[0].tool,firstArgs=lastN[0].argsHash,allSameTool=lastN.every((c)=>c.tool===firstTool),allSimilarArgs=lastN.every((c)=>c.argsHash===firstArgs);if(allSameTool&&allSimilarArgs){if(lastSpiralTimestampBySession.set(sessionId,now),recentToolCallsBySession.delete(sessionId),lastSpiralTimestampBySession.size>MAX_TRACKED_SESSIONS3){for(let oldest of lastSpiralTimestampBySession.keys())if(oldest!==sessionId){lastSpiralTimestampBySession.delete(oldest),recentToolCallsBySession.delete(oldest);break}}return{pattern:"VELOCITY_RATIONALIZATION",severity:"HIGH",matchedText:`Tool '${firstTool}' called ${SPIRAL_THRESHOLD}+ times with identical args`,confidence:"HIGH"}}return null}function calculateAgeFactor(ageHours,config3){if(ageHours<=0)return 1;if(config3.mode==="exponential")return 2**(-ageHours/config3.half_life_hours);else{let linearFactor=1-ageHours/(config3.half_life_hours*2);return Math.max(0,linearFactor)}}function calculateBaseScore(candidate,weights,decayConfig){let{kind,metadata}=candidate,phase=kind==="phase"?1:0,currentTask=metadata.isCurrentTask?1:0,blockedTask=metadata.isBlockedTask?1:0,recentFailure=metadata.hasFailure?1:0,recentSuccess=metadata.hasSuccess?1:0,evidencePresence=metadata.hasEvidence?1:0,decisionRecency=0;if(kind==="decision"&&metadata.decisionAgeHours!==void 0)decisionRecency=calculateAgeFactor(metadata.decisionAgeHours,decayConfig);let dependencyProximity=1/(1+(metadata.dependencyDepth??0));return weights.phase*phase+weights.current_task*currentTask+weights.blocked_task*blockedTask+weights.recent_failure*recentFailure+weights.recent_success*recentSuccess+weights.evidence_presence*evidencePresence+weights.decision_recency*decisionRecency+weights.dependency_proximity*dependencyProximity}function rankCandidates(candidates,config3){if(!config3.enabled)return candidates.map((c)=>({...c,score:0}));if(candidates.length===0)return[];let scored=candidates.map((candidate)=>{let score=calculateBaseScore(candidate,config3.weights,config3.decision_decay);return{...candidate,score}});return scored.sort((a,b)=>{if(b.score!==a.score)return b.score-a.score;if(b.priority!==a.priority)return b.priority-a.priority;return a.id.localeCompare(b.id)}),scored.slice(0,config3.max_candidates)}init_extractors();init_knowledge_store();init_knowledge_validator();init_realtime_learning_nudge();import*as fs85 from"node:fs";var cache3=new Map;function getCachedGraph2(directory){let file3=getGraphPath(directory),stat13;try{stat13=fs85.statSync(file3)}catch{return cache3.delete(directory),null}let cached3=cache3.get(directory);if(cached3&&cached3.mtimeMs===stat13.mtimeMs&&cached3.size===stat13.size)return cached3.graph;let graph;try{graph=loadGraphSync(directory)}catch{return cache3.delete(directory),null}if(!graph)return cache3.delete(directory),null;return cache3.set(directory,{graph,mtimeMs:stat13.mtimeMs,size:stat13.size}),graph}function buildCoderLocalizationBlock(directory,targetFile){if(!targetFile)return null;let graph=getCachedGraph2(directory);if(!graph)return null;let normalized=targetFile.replace(/\\/g,"/").replace(/^\.\/+/,"");if(!getGraphNode(graph,normalized))return null;return["## REPO GRAPH — LOCALIZATION",getLocalizationContext(graph,normalized,{maxImporters:5,maxDeps:5,maxDepth:2}).summary,'_(Run `repo_map action="blast_radius"` for full transitive dependents.)_'].join(`
|
|
5568
5568
|
`)}function buildReviewerBlastRadiusBlock(directory,changedFiles){if(changedFiles.length===0)return null;let graph=getCachedGraph2(directory);if(!graph)return null;let normalized=changedFiles.map((f)=>f.replace(/\\/g,"/").replace(/^\.\/+/,"")).filter((f)=>getGraphNode(graph,f)!==void 0);if(normalized.length===0)return null;let blast=getBlastRadius(graph,normalized,3),directList=blast.directDependents.length===0?"(none)":blast.directDependents.slice(0,8).join(", ")+(blast.directDependents.length>8?`, +${blast.directDependents.length-8} more`:""),transitiveSummary=blast.transitiveDependents.length===0?"(none)":`${blast.transitiveDependents.length} files (depth ${blast.depthReached})`;return["## REPO GRAPH — BLAST RADIUS",` Changed: ${normalized.length<=3?normalized.join(", "):`${normalized.slice(0,3).join(", ")}, +${normalized.length-3} more`}`,` Direct dependents: ${directList}`,` Transitive dependents: ${transitiveSummary}`,` Risk: ${blast.riskLevel} (${blast.totalDependents} total)`,"_Verify these dependents still build/typecheck._"].join(`
|
|
5569
|
-
`)}import*as child_process11 from"node:child_process";import*as fs86 from"node:fs";import*as path155 from"node:path";import{extname as extname12}from"node:path";import{Query}from"web-tree-sitter";import{extname as extname11}from"node:path";var languageDefinitions=[{id:"javascript",extensions:[".js",".jsx",".mjs",".cjs"],commentNodes:["comment","line_comment","block_comment"]},{id:"typescript",extensions:[".ts"],commentNodes:["comment","line_comment","block_comment"]},{id:"python",extensions:[".py"],commentNodes:["comment"]},{id:"go",extensions:[".go"],commentNodes:["comment"]},{id:"rust",extensions:[".rs"],commentNodes:["line_comment","block_comment"]},{id:"php",extensions:[".php",".phtml"],commentNodes:["comment"]},{id:"java",extensions:[".java"],commentNodes:["line_comment","block_comment"]},{id:"c",extensions:[".c",".h"],commentNodes:["comment"]},{id:"cpp",extensions:[".cpp",".cxx",".cc",".hpp",".hxx",".hh"],commentNodes:["comment"]},{id:"csharp",extensions:[".cs"],commentNodes:["comment"]},{id:"ruby",extensions:[".rb"],commentNodes:["comment"]},{id:"swift",extensions:[".swift"],commentNodes:["comment","multiline_comment"]},{id:"kotlin",extensions:[".kt",".kts"],commentNodes:["line_comment","multiline_comment"]},{id:"dart",extensions:[".dart"],commentNodes:["comment","documentation_comment"]},{id:"css",extensions:[".css"],commentNodes:["comment"]},{id:"bash",extensions:[".sh",".bash"],commentNodes:["comment"]},{id:"powershell",extensions:[".ps1",".psm1"],commentNodes:["comment"]},{id:"ini",extensions:[".ini",".cfg",".conf"],commentNodes:["comment"]},{id:"regex",extensions:[".regex"],commentNodes:[]},{id:"tsx",extensions:[".tsx"],commentNodes:["comment"]}],extensionMap=new Map;for(let definition of languageDefinitions)for(let extension of definition.extensions)extensionMap.set(extension,definition);function getLanguageForExtension(extension){return extensionMap.get(extension.toLowerCase())}async function getParserForFile(filePath){let extension=extname11(filePath).toLowerCase(),language=getLanguageForExtension(extension);if(!language)return null;try{let{loadGrammar:loadGrammar2}=await Promise.resolve().then(() => (init_runtime(),exports_runtime));return await loadGrammar2(language.id)}catch{return null}}init_runtime();var QUERIES2={javascript:`
|
|
5569
|
+
`)}import*as child_process11 from"node:child_process";import*as fs86 from"node:fs";import*as path155 from"node:path";import{extname as extname12}from"node:path";import{Query}from"web-tree-sitter";import{extname as extname11}from"node:path";var languageDefinitions=[{id:"javascript",extensions:[".js",".jsx",".mjs",".cjs"],commentNodes:["comment","line_comment","block_comment"]},{id:"typescript",extensions:[".ts"],commentNodes:["comment","line_comment","block_comment"]},{id:"python",extensions:[".py"],commentNodes:["comment"]},{id:"go",extensions:[".go"],commentNodes:["comment"]},{id:"rust",extensions:[".rs"],commentNodes:["line_comment","block_comment"]},{id:"php",extensions:[".php",".phtml"],commentNodes:["comment"]},{id:"java",extensions:[".java"],commentNodes:["line_comment","block_comment"]},{id:"c",extensions:[".c",".h"],commentNodes:["comment"]},{id:"cpp",extensions:[".cpp",".cxx",".cc",".hpp",".hxx",".hh"],commentNodes:["comment"]},{id:"csharp",extensions:[".cs"],commentNodes:["comment"]},{id:"ruby",extensions:[".rb"],commentNodes:["comment"]},{id:"swift",extensions:[".swift"],commentNodes:["comment","multiline_comment"]},{id:"kotlin",extensions:[".kt",".kts"],commentNodes:["line_comment","multiline_comment"]},{id:"dart",extensions:[".dart"],commentNodes:["comment","documentation_comment"]},{id:"css",extensions:[".css"],commentNodes:["comment"]},{id:"bash",extensions:[".sh",".bash"],commentNodes:["comment"]},{id:"powershell",extensions:[".ps1",".psm1"],commentNodes:["comment"]},{id:"ini",extensions:[".ini",".cfg",".conf"],commentNodes:["comment"]},{id:"regex",extensions:[".regex"],commentNodes:[]},{id:"tsx",extensions:[".tsx"],commentNodes:["comment"]}],extensionMap=new Map;for(let definition of languageDefinitions)for(let extension of definition.extensions)extensionMap.set(extension,definition);function getLanguageForExtension(extension){return extensionMap.get(extension.toLowerCase())}async function getParserForFile(filePath){let extension=extname11(filePath).toLowerCase(),language=getLanguageForExtension(extension);if(!language)return null;try{let{loadGrammar:loadGrammar2}=await Promise.resolve().then(() => (init_runtime(),exports_runtime));return await loadGrammar2(language.id)}catch{return null}}init_runtime();init_logger();var QUERIES2={javascript:`
|
|
5570
5570
|
(function_declaration name: (identifier) @func.name) @func.def
|
|
5571
5571
|
(class_declaration name: (identifier) @class.name) @class.def
|
|
5572
5572
|
(export_statement) @export
|
|
@@ -5652,7 +5652,7 @@ The current fix strategy appears to be cycling without progress`;return{eventLog
|
|
|
5652
5652
|
(import_statement) @import
|
|
5653
5653
|
(type_alias_declaration name: (type_identifier) @type.name) @type.def
|
|
5654
5654
|
(interface_declaration name: (type_identifier) @interface.name) @interface.def
|
|
5655
|
-
`},AST_TIMEOUT_MS2=500;async function computeASTDiff(filePath,oldContent,newContent){let startTime=Date.now(),extension=extname12(filePath).toLowerCase(),language=getLanguageForExtension(extension);if(!language)return{filePath,language:null,changes:[],durationMs:Date.now()-startTime,usedAST:!1};try{let timeoutId,parser=await Promise.race([loadGrammar(language.id),new Promise((_,reject)=>{timeoutId=setTimeout(()=>reject(Error("AST_TIMEOUT")),AST_TIMEOUT_MS2)})]).finally(()=>{if(timeoutId)clearTimeout(timeoutId)}),oldTree=parser.parse(oldContent),newTree=parser.parse(newContent);if(!oldTree||!newTree)return{filePath,language:language.id,changes:[],durationMs:Date.now()-startTime,usedAST:!1,error:"Failed to parse file"};let oldSymbols=extractSymbols2(oldTree,language),newSymbols=extractSymbols2(newTree,language),changes=compareSymbols(oldSymbols,newSymbols);return oldTree.delete(),newTree.delete(),{filePath,language:language.id,changes,durationMs:Date.now()-startTime,usedAST:!0}}catch(error93){let errorMsg=error93 instanceof Error?error93.message:"Unknown error";if(errorMsg==="AST_TIMEOUT")console.warn(`[ast-diff] Timeout for ${filePath}, falling back to raw diff`);return{filePath,language:language.id,changes:[],durationMs:Date.now()-startTime,usedAST:!1,error:errorMsg}}}function extractSymbols2(tree,language){let symbols2=[],queryStr=QUERIES2[language.id];if(!queryStr)return symbols2;try{let lang=tree.language;if(!lang)return symbols2;let matches=new Query(lang,queryStr).matches(tree.rootNode);for(let match of matches){let symbol3=parseMatch(match,language.id);if(symbol3)symbols2.push(symbol3)}let defEntries=symbols2.filter((s)=>s.category!=="export"&&s.category!=="import");if(defEntries.length>0&&defEntries.length<symbols2.length){let filtered=symbols2.filter((symbol3)=>{if(symbol3.category!=="export"&&symbol3.category!=="import")return!0;return!defEntries.some((def)=>symbol3.lineStart===def.lineStart&&symbol3.lineEnd===def.lineEnd)});symbols2.length=0,symbols2.push(...filtered)}}catch{}return symbols2}function parseMatch(match,languageId){let captures=match.captures,defCapture=captures.find((c)=>c.name.endsWith(".def")),nameCapture=captures.find((c)=>c.name.endsWith(".name"));if(!defCapture){let exportCapture=captures.find((c)=>c.name==="export"),importCapture=captures.find((c)=>c.name==="import"),categoryCapture=exportCapture||importCapture;if(!categoryCapture)return null;let node2=categoryCapture.node,text=node2.text.trim(),name=extractStatementName(text,categoryCapture.name);return{category:categoryCapture.name==="export"?"export":"import",name,lineStart:node2.startPosition.row+1,lineEnd:node2.endPosition.row+1}}let node=defCapture.node,nameNode=nameCapture?.node;return{category:inferCategory(captures[0]?.name||"other"),name:nameNode?.text||"anonymous",lineStart:node.startPosition.row+1,lineEnd:node.endPosition.row+1,signature:extractSignature(node,languageId)}}function extractStatementName(text,captureType){if(captureType==="import"){let fromMatch=text.match(/from\s+['"]([^'"]+)['"]/);if(fromMatch)return fromMatch[1];let stringMatch=text.match(/['"]([^'"]+)['"]/);if(stringMatch)return stringMatch[1]}else{let namedExport=text.match(/export\s+(?:default\s+)?(?:function|class|const|let|var|type|interface)\s+(\w+)/);if(namedExport)return namedExport[1];if(text.match(/export\s+default\s+(?:function|class)\b/))return"default";let braceExport=text.match(/export\s+\{([^}]+)\}/);if(braceExport)return braceExport[1].trim()}let tokens=text.split(/\s+/);return tokens.length>1?tokens.slice(0,3).join(" "):text.slice(0,30)}function inferCategory(captureName){if(captureName.includes("func"))return"function";if(captureName.includes("class"))return"class";if(captureName.includes("type")||captureName.includes("interface")||captureName.includes("struct")||captureName.includes("protocol")||captureName.includes("mixin")||captureName.includes("object")||captureName.includes("module"))return"type";if(captureName.includes("export"))return"export";if(captureName.includes("import")||captureName.includes("use")||captureName.includes("using"))return"import";if(captureName.includes("var"))return"variable";if(captureName.includes("command"))return"function";if(captureName.includes("rule"))return"type";return"other"}var paramNodeTypes={javascript:["formal_parameters"],typescript:["formal_parameters"],tsx:["formal_parameters"],python:["parameters"],go:["parameter_list"],rust:["parameters","function_item"],java:["formal_parameters","method_declaration"],c:["parameter_list"],cpp:["parameter_list"],csharp:["formal_parameters"],ruby:["parameters"],php:["formal_parameters","parameter_list"],swift:["parameter_clause"],kotlin:["parameter_list"],dart:["parameter_list","function_signature"],css:[],bash:["command_position"],powershell:["parameter_list"]};function extractSignature(node,languageId){let nodeTypes=paramNodeTypes[languageId]||[];for(let child of node.children)if(child&&nodeTypes.includes(child.type))return child.text;if(languageId==="javascript"||languageId==="typescript"||languageId==="tsx"){let paramsNode=node.children.find((c)=>c!==null&&c.type==="formal_parameters");if(paramsNode)return paramsNode.text}if(node.type==="class_declaration"||node.type==="class_definition"||node.type==="class"){let classBodyNode=node.children.find((c)=>c!==null&&(c.type==="class_body"||c.type==="declaration_list"));if(classBodyNode)return classBodyNode.text}return}function compareSymbols(oldSymbols,newSymbols){let changes=[],oldMap=new Map(oldSymbols.map((s)=>[s.name,s])),newMap=new Map(newSymbols.map((s)=>[s.name,s])),matchedOldSymbols=new Set;for(let newSymbol of newSymbols)if(!oldMap.has(newSymbol.name)){let matchingOldSymbol=findRenamedSymbol(newSymbol,oldSymbols,matchedOldSymbols);if(matchingOldSymbol)changes.push({type:"renamed",category:newSymbol.category,name:newSymbol.name,lineStart:newSymbol.lineStart,lineEnd:newSymbol.lineEnd,signature:newSymbol.signature,renamedFrom:matchingOldSymbol.name}),matchedOldSymbols.add(matchingOldSymbol);else changes.push({type:"added",category:newSymbol.category,name:newSymbol.name,lineStart:newSymbol.lineStart,lineEnd:newSymbol.lineEnd,signature:newSymbol.signature})}else{let oldSymbol=oldMap.get(newSymbol.name);if(matchedOldSymbols.add(oldSymbol),oldSymbol.lineStart!==newSymbol.lineStart||oldSymbol.lineEnd!==newSymbol.lineEnd||oldSymbol.signature!==newSymbol.signature)changes.push({type:"modified",category:newSymbol.category,name:newSymbol.name,lineStart:newSymbol.lineStart,lineEnd:newSymbol.lineEnd,signature:newSymbol.signature})}for(let oldSymbol of oldSymbols)if(!newMap.has(oldSymbol.name)&&!matchedOldSymbols.has(oldSymbol))changes.push({type:"removed",category:oldSymbol.category,name:oldSymbol.name,lineStart:oldSymbol.lineStart,lineEnd:oldSymbol.lineEnd,signature:oldSymbol.signature});return changes}function findRenamedSymbol(newSymbol,oldSymbols,matchedOldSymbols){if(newSymbol.category!=="function"&&newSymbol.category!=="type"&&newSymbol.category!=="class")return null;if(!newSymbol.signature)return null;if(newSymbol.category==="function"&&newSymbol.signature.replace(/\s/g,"")==="()")return null;let lineCount=newSymbol.lineEnd-newSymbol.lineStart;for(let oldSymbol of oldSymbols){if(matchedOldSymbols.has(oldSymbol)||oldSymbol.category!==newSymbol.category)continue;if(oldSymbol.signature!==newSymbol.signature)continue;let oldLineCount=oldSymbol.lineEnd-oldSymbol.lineStart,maxAllowedLines=Math.ceil(lineCount*1.2);if(oldLineCount>maxAllowedLines)continue;return oldSymbol}return null}var GUARD_KEYWORDS=["guard","check","validate","verify","ensure","assert","require"];function isGuardKeyword(name){return GUARD_KEYWORDS.some((keyword)=>{let ciKeyword=keyword.split("").map((c)=>`[${c.toLowerCase()}${c.toUpperCase()}]`).join("");return new RegExp(`(?<![a-z])${ciKeyword}(?![a-z])`).test(name)})}function isExportedFunction(name,allChanges){return allChanges.some((c)=>c.name===name&&c.category==="export")}function classifyChange(change,filePath,allChanges){let base={filePath,symbolName:change.name,changeType:change.type,lineStart:change.lineStart,lineEnd:change.lineEnd,signature:change.signature};if(change.type==="removed"&&change.category==="function"){if(isGuardKeyword(change.name))return{...base,category:"GUARD_REMOVED",riskLevel:"Critical",description:`Guard function '${change.name}' was removed`};return{...base,category:"DELETED_FUNCTION",riskLevel:"High",description:`Deleted function '${change.name}'`}}if(change.type==="renamed"){if(change.category==="function"&&(isGuardKeyword(change.name)||isGuardKeyword(change.renamedFrom||"")))return{...base,category:"GUARD_REMOVED",riskLevel:"Critical",description:`Guard function renamed from '${change.renamedFrom||"unknown"}' to '${change.name}'`,renamedFrom:change.renamedFrom};return{...base,category:"REFACTOR",riskLevel:"Medium",description:`${change.category} renamed from '${change.renamedFrom||"unknown"}' to '${change.name}'`,renamedFrom:change.renamedFrom}}if(change.type==="added"&&change.category==="function")return{...base,category:"NEW_FUNCTION",riskLevel:"Medium",description:`New function '${change.name}' added`};if(change.type==="modified"&&change.category==="function"&&change.signature)return{...base,category:"SIGNATURE_CHANGE",riskLevel:"Critical",description:`Function signature changed for '${change.name}': ${change.signature}`};if(change.type==="modified"){if(change.category==="export"||change.category==="type")return{...base,category:"API_CHANGE",riskLevel:"Critical",description:`API surface changed for '${change.name}' (${change.category})`};if(change.category==="function"&&isExportedFunction(change.name,allChanges))return{...base,category:"API_CHANGE",riskLevel:"Critical",description:`Exported function '${change.name}' was modified`}}if(change.type==="modified"&&change.category==="function")return{...base,category:"LOGIC_CHANGE",riskLevel:"High",description:`Function body logic changed for '${change.name}'`};if(change.type==="modified"&&(change.category==="class"||change.category==="type"||change.category==="variable"))return{...base,category:"REFACTOR",riskLevel:"Medium",description:`${change.category} '${change.name}' was refactored`};if(change.category==="import")return{...base,category:"COSMETIC",riskLevel:"Low",description:`Import ${change.type} for '${change.name}'`};return{...base,category:"UNCLASSIFIED",riskLevel:"Medium",description:`Unclassified ${change.type} of ${change.category} '${change.name}'`}}function classifyChanges(astDiffs,fileConsumers){let result=[];for(let diff of astDiffs)for(let change of diff.changes){let classified=classifyChange(change,diff.filePath,diff.changes);if(fileConsumers&&diff.filePath in fileConsumers)classified.consumersCount=fileConsumers[diff.filePath];result.push(classified)}return result}var RISK_LEVELS=["Critical","High","Medium","Low"],CHANGE_CATEGORIES=["SIGNATURE_CHANGE","API_CHANGE","GUARD_REMOVED","LOGIC_CHANGE","DELETED_FUNCTION","NEW_FUNCTION","REFACTOR","COSMETIC","UNCLASSIFIED"];function generateSummary(changes){let byRisk=RISK_LEVELS.reduce((acc,level)=>{return acc[level]=[],acc},{}),byCategory=CHANGE_CATEGORIES.reduce((acc,cat)=>{return acc[cat]=[],acc},{});for(let change of changes)byRisk[change.riskLevel].push(change),byCategory[change.category].push(change);return{totalFiles:new Set(changes.map((c)=>c.filePath)).size,totalChanges:changes.length,byRisk,byCategory,criticalItems:byRisk.Critical}}function generateSummaryMarkdown(summary){let lines=[],totalFiles=summary.totalFiles,totalChanges=summary.totalChanges;lines.push(`## Change Summary (${totalFiles} files, ${totalChanges} changes)`);let riskLabels={Critical:"Critical (review first)",High:"High",Medium:"Medium",Low:"Low (skim)"};for(let riskLevel of RISK_LEVELS){let changes=summary.byRisk[riskLevel],header=riskLabels[riskLevel];if(lines.push(`### ${header}`),changes.length===0)lines.push("- (none)");else for(let change of changes){let consumers=change.consumersCount!=null?` (${change.consumersCount} consumer${change.consumersCount!==1?"s":""})`:"";lines.push(`- ${change.filePath}: ${change.category} — ${change.description}${consumers}`)}}return lines.join(`
|
|
5655
|
+
`},AST_TIMEOUT_MS2=500;async function computeASTDiff(filePath,oldContent,newContent){let startTime=Date.now(),extension=extname12(filePath).toLowerCase(),language=getLanguageForExtension(extension);if(!language)return{filePath,language:null,changes:[],durationMs:Date.now()-startTime,usedAST:!1};try{let timeoutId,parser=await Promise.race([loadGrammar(language.id),new Promise((_,reject)=>{timeoutId=setTimeout(()=>reject(Error("AST_TIMEOUT")),AST_TIMEOUT_MS2)})]).finally(()=>{if(timeoutId)clearTimeout(timeoutId)}),oldTree=parser.parse(oldContent),newTree=parser.parse(newContent);if(!oldTree||!newTree)return{filePath,language:language.id,changes:[],durationMs:Date.now()-startTime,usedAST:!1,error:"Failed to parse file"};let oldSymbols=extractSymbols2(oldTree,language),newSymbols=extractSymbols2(newTree,language),changes=compareSymbols(oldSymbols,newSymbols);return oldTree.delete(),newTree.delete(),{filePath,language:language.id,changes,durationMs:Date.now()-startTime,usedAST:!0}}catch(error93){let errorMsg=error93 instanceof Error?error93.message:"Unknown error";if(errorMsg==="AST_TIMEOUT")log(`[ast-diff] Timeout for ${filePath}, falling back to raw diff`);return{filePath,language:language.id,changes:[],durationMs:Date.now()-startTime,usedAST:!1,error:errorMsg}}}function extractSymbols2(tree,language){let symbols2=[],queryStr=QUERIES2[language.id];if(!queryStr)return symbols2;try{let lang=tree.language;if(!lang)return symbols2;let matches=new Query(lang,queryStr).matches(tree.rootNode);for(let match of matches){let symbol3=parseMatch(match,language.id);if(symbol3)symbols2.push(symbol3)}let defEntries=symbols2.filter((s)=>s.category!=="export"&&s.category!=="import");if(defEntries.length>0&&defEntries.length<symbols2.length){let filtered=symbols2.filter((symbol3)=>{if(symbol3.category!=="export"&&symbol3.category!=="import")return!0;return!defEntries.some((def)=>symbol3.lineStart===def.lineStart&&symbol3.lineEnd===def.lineEnd)});symbols2.length=0,symbols2.push(...filtered)}}catch{}return symbols2}function parseMatch(match,languageId){let captures=match.captures,defCapture=captures.find((c)=>c.name.endsWith(".def")),nameCapture=captures.find((c)=>c.name.endsWith(".name"));if(!defCapture){let exportCapture=captures.find((c)=>c.name==="export"),importCapture=captures.find((c)=>c.name==="import"),categoryCapture=exportCapture||importCapture;if(!categoryCapture)return null;let node2=categoryCapture.node,text=node2.text.trim(),name=extractStatementName(text,categoryCapture.name);return{category:categoryCapture.name==="export"?"export":"import",name,lineStart:node2.startPosition.row+1,lineEnd:node2.endPosition.row+1}}let node=defCapture.node,nameNode=nameCapture?.node;return{category:inferCategory(captures[0]?.name||"other"),name:nameNode?.text||"anonymous",lineStart:node.startPosition.row+1,lineEnd:node.endPosition.row+1,signature:extractSignature(node,languageId)}}function extractStatementName(text,captureType){if(captureType==="import"){let fromMatch=text.match(/from\s+['"]([^'"]+)['"]/);if(fromMatch)return fromMatch[1];let stringMatch=text.match(/['"]([^'"]+)['"]/);if(stringMatch)return stringMatch[1]}else{let namedExport=text.match(/export\s+(?:default\s+)?(?:function|class|const|let|var|type|interface)\s+(\w+)/);if(namedExport)return namedExport[1];if(text.match(/export\s+default\s+(?:function|class)\b/))return"default";let braceExport=text.match(/export\s+\{([^}]+)\}/);if(braceExport)return braceExport[1].trim()}let tokens=text.split(/\s+/);return tokens.length>1?tokens.slice(0,3).join(" "):text.slice(0,30)}function inferCategory(captureName){if(captureName.includes("func"))return"function";if(captureName.includes("class"))return"class";if(captureName.includes("type")||captureName.includes("interface")||captureName.includes("struct")||captureName.includes("protocol")||captureName.includes("mixin")||captureName.includes("object")||captureName.includes("module"))return"type";if(captureName.includes("export"))return"export";if(captureName.includes("import")||captureName.includes("use")||captureName.includes("using"))return"import";if(captureName.includes("var"))return"variable";if(captureName.includes("command"))return"function";if(captureName.includes("rule"))return"type";return"other"}var paramNodeTypes={javascript:["formal_parameters"],typescript:["formal_parameters"],tsx:["formal_parameters"],python:["parameters"],go:["parameter_list"],rust:["parameters","function_item"],java:["formal_parameters","method_declaration"],c:["parameter_list"],cpp:["parameter_list"],csharp:["formal_parameters"],ruby:["parameters"],php:["formal_parameters","parameter_list"],swift:["parameter_clause"],kotlin:["parameter_list"],dart:["parameter_list","function_signature"],css:[],bash:["command_position"],powershell:["parameter_list"]};function extractSignature(node,languageId){let nodeTypes=paramNodeTypes[languageId]||[];for(let child of node.children)if(child&&nodeTypes.includes(child.type))return child.text;if(languageId==="javascript"||languageId==="typescript"||languageId==="tsx"){let paramsNode=node.children.find((c)=>c!==null&&c.type==="formal_parameters");if(paramsNode)return paramsNode.text}if(node.type==="class_declaration"||node.type==="class_definition"||node.type==="class"){let classBodyNode=node.children.find((c)=>c!==null&&(c.type==="class_body"||c.type==="declaration_list"));if(classBodyNode)return classBodyNode.text}return}function compareSymbols(oldSymbols,newSymbols){let changes=[],oldMap=new Map(oldSymbols.map((s)=>[s.name,s])),newMap=new Map(newSymbols.map((s)=>[s.name,s])),matchedOldSymbols=new Set;for(let newSymbol of newSymbols)if(!oldMap.has(newSymbol.name)){let matchingOldSymbol=findRenamedSymbol(newSymbol,oldSymbols,matchedOldSymbols);if(matchingOldSymbol)changes.push({type:"renamed",category:newSymbol.category,name:newSymbol.name,lineStart:newSymbol.lineStart,lineEnd:newSymbol.lineEnd,signature:newSymbol.signature,renamedFrom:matchingOldSymbol.name}),matchedOldSymbols.add(matchingOldSymbol);else changes.push({type:"added",category:newSymbol.category,name:newSymbol.name,lineStart:newSymbol.lineStart,lineEnd:newSymbol.lineEnd,signature:newSymbol.signature})}else{let oldSymbol=oldMap.get(newSymbol.name);if(matchedOldSymbols.add(oldSymbol),oldSymbol.lineStart!==newSymbol.lineStart||oldSymbol.lineEnd!==newSymbol.lineEnd||oldSymbol.signature!==newSymbol.signature)changes.push({type:"modified",category:newSymbol.category,name:newSymbol.name,lineStart:newSymbol.lineStart,lineEnd:newSymbol.lineEnd,signature:newSymbol.signature})}for(let oldSymbol of oldSymbols)if(!newMap.has(oldSymbol.name)&&!matchedOldSymbols.has(oldSymbol))changes.push({type:"removed",category:oldSymbol.category,name:oldSymbol.name,lineStart:oldSymbol.lineStart,lineEnd:oldSymbol.lineEnd,signature:oldSymbol.signature});return changes}function findRenamedSymbol(newSymbol,oldSymbols,matchedOldSymbols){if(newSymbol.category!=="function"&&newSymbol.category!=="type"&&newSymbol.category!=="class")return null;if(!newSymbol.signature)return null;if(newSymbol.category==="function"&&newSymbol.signature.replace(/\s/g,"")==="()")return null;let lineCount=newSymbol.lineEnd-newSymbol.lineStart;for(let oldSymbol of oldSymbols){if(matchedOldSymbols.has(oldSymbol)||oldSymbol.category!==newSymbol.category)continue;if(oldSymbol.signature!==newSymbol.signature)continue;let oldLineCount=oldSymbol.lineEnd-oldSymbol.lineStart,maxAllowedLines=Math.ceil(lineCount*1.2);if(oldLineCount>maxAllowedLines)continue;return oldSymbol}return null}var GUARD_KEYWORDS=["guard","check","validate","verify","ensure","assert","require"];function isGuardKeyword(name){return GUARD_KEYWORDS.some((keyword)=>{let ciKeyword=keyword.split("").map((c)=>`[${c.toLowerCase()}${c.toUpperCase()}]`).join("");return new RegExp(`(?<![a-z])${ciKeyword}(?![a-z])`).test(name)})}function isExportedFunction(name,allChanges){return allChanges.some((c)=>c.name===name&&c.category==="export")}function classifyChange(change,filePath,allChanges){let base={filePath,symbolName:change.name,changeType:change.type,lineStart:change.lineStart,lineEnd:change.lineEnd,signature:change.signature};if(change.type==="removed"&&change.category==="function"){if(isGuardKeyword(change.name))return{...base,category:"GUARD_REMOVED",riskLevel:"Critical",description:`Guard function '${change.name}' was removed`};return{...base,category:"DELETED_FUNCTION",riskLevel:"High",description:`Deleted function '${change.name}'`}}if(change.type==="renamed"){if(change.category==="function"&&(isGuardKeyword(change.name)||isGuardKeyword(change.renamedFrom||"")))return{...base,category:"GUARD_REMOVED",riskLevel:"Critical",description:`Guard function renamed from '${change.renamedFrom||"unknown"}' to '${change.name}'`,renamedFrom:change.renamedFrom};return{...base,category:"REFACTOR",riskLevel:"Medium",description:`${change.category} renamed from '${change.renamedFrom||"unknown"}' to '${change.name}'`,renamedFrom:change.renamedFrom}}if(change.type==="added"&&change.category==="function")return{...base,category:"NEW_FUNCTION",riskLevel:"Medium",description:`New function '${change.name}' added`};if(change.type==="modified"&&change.category==="function"&&change.signature)return{...base,category:"SIGNATURE_CHANGE",riskLevel:"Critical",description:`Function signature changed for '${change.name}': ${change.signature}`};if(change.type==="modified"){if(change.category==="export"||change.category==="type")return{...base,category:"API_CHANGE",riskLevel:"Critical",description:`API surface changed for '${change.name}' (${change.category})`};if(change.category==="function"&&isExportedFunction(change.name,allChanges))return{...base,category:"API_CHANGE",riskLevel:"Critical",description:`Exported function '${change.name}' was modified`}}if(change.type==="modified"&&change.category==="function")return{...base,category:"LOGIC_CHANGE",riskLevel:"High",description:`Function body logic changed for '${change.name}'`};if(change.type==="modified"&&(change.category==="class"||change.category==="type"||change.category==="variable"))return{...base,category:"REFACTOR",riskLevel:"Medium",description:`${change.category} '${change.name}' was refactored`};if(change.category==="import")return{...base,category:"COSMETIC",riskLevel:"Low",description:`Import ${change.type} for '${change.name}'`};return{...base,category:"UNCLASSIFIED",riskLevel:"Medium",description:`Unclassified ${change.type} of ${change.category} '${change.name}'`}}function classifyChanges(astDiffs,fileConsumers){let result=[];for(let diff of astDiffs)for(let change of diff.changes){let classified=classifyChange(change,diff.filePath,diff.changes);if(fileConsumers&&diff.filePath in fileConsumers)classified.consumersCount=fileConsumers[diff.filePath];result.push(classified)}return result}var RISK_LEVELS=["Critical","High","Medium","Low"],CHANGE_CATEGORIES=["SIGNATURE_CHANGE","API_CHANGE","GUARD_REMOVED","LOGIC_CHANGE","DELETED_FUNCTION","NEW_FUNCTION","REFACTOR","COSMETIC","UNCLASSIFIED"];function generateSummary(changes){let byRisk=RISK_LEVELS.reduce((acc,level)=>{return acc[level]=[],acc},{}),byCategory=CHANGE_CATEGORIES.reduce((acc,cat)=>{return acc[cat]=[],acc},{});for(let change of changes)byRisk[change.riskLevel].push(change),byCategory[change.category].push(change);return{totalFiles:new Set(changes.map((c)=>c.filePath)).size,totalChanges:changes.length,byRisk,byCategory,criticalItems:byRisk.Critical}}function generateSummaryMarkdown(summary){let lines=[],totalFiles=summary.totalFiles,totalChanges=summary.totalChanges;lines.push(`## Change Summary (${totalFiles} files, ${totalChanges} changes)`);let riskLabels={Critical:"Critical (review first)",High:"High",Medium:"Medium",Low:"Low (skim)"};for(let riskLevel of RISK_LEVELS){let changes=summary.byRisk[riskLevel],header=riskLabels[riskLevel];if(lines.push(`### ${header}`),changes.length===0)lines.push("- (none)");else for(let change of changes){let consumers=change.consumersCount!=null?` (${change.consumersCount} consumer${change.consumersCount!==1?"s":""})`:"";lines.push(`- ${change.filePath}: ${change.category} — ${change.description}${consumers}`)}}return lines.join(`
|
|
5656
5656
|
`)}init_git_binary_missing_error();var _internals95={execFile:child_process11.execFile,realpathSync:fs86.realpathSync,readFile:fs86.promises.readFile,computeASTDiff,classifyChanges,generateSummary,generateSummaryMarkdown,getCachedGraph:getCachedGraph2,getImporters,normalizeGraphPath};async function execGit(directory,args2,options){try{return await new Promise((resolve56,reject)=>{let execOpts={encoding:"utf-8",cwd:directory,timeout:options?.timeout,maxBuffer:options?.maxBuffer,stdio:["ignore","pipe","pipe"]};_internals95.execFile("git",args2,execOpts,(error93,output,_stderr)=>{if(error93){reject(error93);return}resolve56(output??"")})})}catch(err){if(isGitBinaryMissing(err))throw new GitBinaryMissingError("git binary is not available",{cause:err});throw err}}async function buildSemanticDiffBlock(directory,changedFiles,maxFiles=10){if(changedFiles.length===0)return null;try{let realDirectory=_internals95.realpathSync(directory),filesToProcess=changedFiles.slice(0,maxFiles),astDiffs=[],graph=_internals95.getCachedGraph(directory),fileConsumers={};if(graph)for(let f of filesToProcess){let relativePath=path155.isAbsolute(f)?path155.relative(directory,f):f,normalized=_internals95.normalizeGraphPath(relativePath);fileConsumers[normalized]=_internals95.getImporters(graph,normalized).length,fileConsumers[f]=fileConsumers[normalized]}for(let filePath of filesToProcess){let normalizedPath=path155.normalize(filePath),resolvedPath=path155.resolve(directory,normalizedPath),relativeToDir=path155.relative(directory,resolvedPath);if(relativeToDir.startsWith("..")||path155.isAbsolute(relativeToDir))continue;let realResolvedPath;try{realResolvedPath=_internals95.realpathSync(resolvedPath)}catch{continue}let realRelativeToDir=path155.relative(realDirectory,realResolvedPath);if(realRelativeToDir.startsWith("..")||path155.isAbsolute(realRelativeToDir))continue;try{let fileExistsInHead=!1;try{await execGit(directory,["cat-file","-e",`HEAD:${filePath}`],{timeout:3000}),fileExistsInHead=!0}catch(err){if(err instanceof GitBinaryMissingError)throw err;fileExistsInHead=!1}let oldContent=fileExistsInHead?await execGit(directory,["show",`HEAD:${filePath}`],{timeout:5000,maxBuffer:5242880}):"",newContent=await _internals95.readFile(realResolvedPath,"utf-8"),astResult=await _internals95.computeASTDiff(filePath,oldContent,newContent);if(astResult&&(astResult.changes.length>0||astResult.error!==void 0))astDiffs.push(astResult)}catch(err){if(err instanceof GitBinaryMissingError)throw err}}if(astDiffs.length===0)return null;let classifiedChanges=_internals95.classifyChanges(astDiffs,fileConsumers);if(classifiedChanges.length===0)return null;let summary=_internals95.generateSummary(classifiedChanges);return`## SEMANTIC DIFF SUMMARY
|
|
5657
5657
|
${_internals95.generateSummaryMarkdown(summary)}`}catch{return null}}init_utils2();var SPEC_STALENESS_CACHE_NAMESPACE="spec-staleness-json:v1",HANDOFF_SOURCE_SESSION_PREFIX2="<!-- opencode-swarm-handoff-source-session:";function parseSessionScopedHandoff(content){let newlineIndex=content.indexOf(`
|
|
5658
5658
|
`),firstLine2=newlineIndex===-1?content:content.slice(0,newlineIndex);if(firstLine2.startsWith(HANDOFF_SOURCE_SESSION_PREFIX2)&&firstLine2.endsWith("-->")){let encodedSessionID=firstLine2.slice(HANDOFF_SOURCE_SESSION_PREFIX2.length,-3).trim();try{return{body:newlineIndex===-1?"":content.slice(newlineIndex+1),sourceSessionID:decodeURIComponent(encodedSessionID)}}catch{return{body:content}}}return{body:content}}function shouldConsumeHandoff(handoff,currentSessionID){return!(currentSessionID&&handoff.sourceSessionID&&handoff.sourceSessionID===currentSessionID)}function buildSpecDriftAdvisory(args2){let lines=["[spec-drift]",`Reason: ${args2.reason}`,`Stored spec hash: ${args2.storedHash}`,`Current spec hash: ${args2.currentHash??"(spec.md missing)"}`,"Action: surface this warning to the user at your next user-facing reply. Do NOT proceed with destructive plan operations (save_plan with removals, update_task_status, phase_complete, lean_turbo_run_phase, lean_turbo_acquire_locks) until the user runs /swarm clarify or /swarm acknowledge-spec-drift."];if(args2.midLoadRemovals)lines.push(`Auto-removed during recovery: ${args2.midLoadRemovals.count} task(s) (source: ${args2.midLoadRemovals.source}). See .swarm/plan-ledger.jsonl for IDs.`);if(args2.diff){if(lines.push(""),lines.push("--- spec diff (recorded vs current) ---"),args2.diff.changedSections.length>0)lines.push("Changed sections: "+args2.diff.changedSections.map((s)=>`## ${s}`).join(", "));lines.push("[Begin spec diff]",args2.diff.diff,"[End spec diff]")}else if(args2.diff===null)lines.push("(no recorded snapshot to diff against)");return lines.join(`
|
|
@@ -5846,15 +5846,15 @@ Review before proceeding.`;injectSystemMessage(input.sessionID,message)}}}init_b
|
|
|
5846
5846
|
`?resultContent.replace(/\n/g,`\r
|
|
5847
5847
|
`):resultContent;finalContent=ensureFinalNewline(withLineEnding,originalEndsWithNewline)}if(finalContent===content)return{file:targetPath,status:"no-changes",hunks:hunksTotal,hunksApplied:hunksTotal,hunksFailed:0};if(!dryRun)atomicWriteFileSync2(fullPath,finalContent);return{file:targetPath,status:"applied",hunks:hunksTotal,hunksApplied:hunksTotal,hunksFailed:0}}function buildErrorResult(message){return{success:!1,files:[{file:"",status:"error",hunks:0,hunksApplied:0,hunksFailed:0,errors:[{hunkIndex:0,type:"context-mismatch",message}]}],summary:{totalFiles:0,applied:0,failed:1,totalHunks:0}}}function isUnsupportedPatchFormat(patchText){let trimmed=patchText.trimStart();return trimmed.startsWith("*** Begin Patch")||trimmed.startsWith("*** Update File")||trimmed.startsWith("*** Add File")||trimmed.startsWith("*** Delete File")||trimmed.startsWith("*** End Patch")}var swarmApplyPatch=createSwarmTool({description:"Apply a unified diff patch to workspace files. Validates paths, matches context exactly, and writes atomically. Coder-scoped write tool. Use standard unified diff format (--- a/file / +++ b/file / @@ hunks). Does NOT support *** Begin Patch / *** Update File payloads — use the native apply_patch tool for those.",args:{patch:exports_external.string().min(1).describe("Unified diff text to parse and apply"),files:exports_external.array(exports_external.string()).min(1).describe("Array of target file paths the patch is expected to touch. Every parsed target must appear in this list."),dryRun:exports_external.boolean().optional().default(!1).describe("Validate without writing files (default: false)"),allowCreates:exports_external.boolean().optional().default(!1).describe("Allow creating new files from patches with --- /dev/null (default: false)"),allowDeletes:exports_external.boolean().optional().default(!1).describe("Allow deleting files from patches with +++ /dev/null (default: false)")},execute:async(args2,directory)=>{if(!args2||typeof args2!=="object")return JSON.stringify(buildErrorResult("Could not parse swarm_apply_patch arguments"),null,2);let obj=args2,patchText=obj.patch??"",files=obj.files??[],dryRun=obj.dryRun??!1,allowCreates=obj.allowCreates??!1,allowDeletes=obj.allowDeletes??!1;if(!existsSync95(directory))return JSON.stringify(buildErrorResult("Workspace directory does not exist"),null,2);if(files.length===0)return JSON.stringify(buildErrorResult("files array cannot be empty"),null,2);if(!patchText||patchText.trim()==="")return JSON.stringify(buildErrorResult("patch text cannot be empty"),null,2);if(isUnsupportedPatchFormat(patchText))return JSON.stringify(buildErrorResult("Unsupported patch format: *** Begin Patch / *** Update File style payloads are not supported by swarm_apply_patch. Use the native apply_patch tool for this format, or provide a standard unified diff (--- a/file / +++ b/file / @@ hunks)."),null,2);for(let filePath of files){let validationError=validatePatchTargetPath(filePath,directory);if(validationError)return JSON.stringify(buildErrorResult(validationError),null,2)}let{files:parsedFiles,error:parseError}=parseUnifiedDiff(patchText);if(parseError)return JSON.stringify(buildErrorResult(parseError),null,2);if(parsedFiles.length===0)return JSON.stringify({success:!0,dryRun,files:[],summary:{totalFiles:0,applied:0,failed:0,totalHunks:0}},null,2);let declaredFileSet=new Set(files),undeclaredTargets=[];for(let fileDiff of parsedFiles){let targetPath=fileDiff.isDelete?fileDiff.oldPath:fileDiff.newPath;if(targetPath&&targetPath!=="/dev/null"&&!declaredFileSet.has(targetPath))undeclaredTargets.push(targetPath)}if(undeclaredTargets.length>0)return JSON.stringify(buildErrorResult(`Patch targets files not in the declared files array: ${undeclaredTargets.join(", ")}`),null,2);let parsedTargetSet=new Set(parsedFiles.map((fd)=>fd.isDelete?fd.oldPath:fd.newPath).filter(Boolean)),extraFiles=files.filter((f)=>!parsedTargetSet.has(f)),fileResults=[],totalApplied=0,totalFailed=0,totalHunks=0;for(let fileDiff of parsedFiles){let targetPath=fileDiff.isDelete?fileDiff.oldPath:fileDiff.newPath,fullPath=path173.resolve(directory,targetPath);totalHunks+=fileDiff.hunks.length;let result=processFileDiff(fileDiff,targetPath,fullPath,directory,dryRun,allowCreates,allowDeletes);if(fileResults.push(result),result.status==="applied"||result.status==="created")totalApplied++;else if(result.status==="error")totalFailed++}let output={success:totalFailed===0,dryRun,files:fileResults,summary:{totalFiles:fileResults.length,applied:totalApplied,failed:totalFailed,totalHunks}};if(extraFiles.length>0)return JSON.stringify({...output,warnings:[`files[] contains entries not targeted by the patch: ${extraFiles.join(", ")}`]},null,2);return JSON.stringify(output,null,2)}});init_zod();init_external_tool_runner();init_path_security();init_create_tool();import*as fs102 from"node:fs";import*as path174 from"node:path";var AST_GREP_TIMEOUT_MS=1e4,AST_GREP_MAX_STDOUT_BYTES=8388608,AST_GREP_MAX_STDERR_BYTES=65536,DEFAULT_MAX_RESULTS2=100,HARD_CAP_RESULTS2=1e4,MAX_PATTERN_LENGTH=20000;function splitGlobPatterns(value){return value?value.split(",").map((p)=>p.trim()).filter(Boolean):[]}function resolveAstGrepBinary(){return _internals107.resolveExecutableFromPath(["ast-grep","sg"])}function toWorkspaceRelativePath(filePath,workspace){try{let resolved=path174.resolve(workspace,filePath),realWorkspace=fs102.realpathSync(workspace),realResolved=fs102.realpathSync(resolved),relative35=path174.relative(realWorkspace,realResolved);if(!relative35||relative35.startsWith("..")||path174.isAbsolute(relative35))return null;return relative35.split(path174.sep).join("/")}catch{return null}}function parseAstGrepStream(stdout,workspace,maxResults){let matches=[],total=0;for(let line of stdout.split(`
|
|
5848
5848
|
`)){if(!line.trim())continue;try{let entry=JSON.parse(line),relativePath=typeof entry.file==="string"?toWorkspaceRelativePath(entry.file,workspace):null;if(!relativePath)continue;if(total++,matches.length>=maxResults)continue;let start=entry.range?.start??{},end=entry.range?.end??{};matches.push({file:relativePath,lineNumber:typeof start.line==="number"?start.line+1:1,column:typeof start.column==="number"?start.column+1:1,endLineNumber:typeof end.line==="number"?end.line+1:1,endColumn:typeof end.column==="number"?end.column+1:1,text:typeof entry.text==="string"?entry.text:"",lines:typeof entry.lines==="string"?entry.lines.trimEnd():"",language:typeof entry.language==="string"?entry.language:void 0,metaVariables:entry.metaVariables&&typeof entry.metaVariables==="object"?entry.metaVariables:void 0})}catch{}}return{matches,total}}function validateGlobArg(kind,value){if(!value)return null;if(containsControlChars(value))return{error:!0,type:"path-escape",message:`${kind} pattern contains invalid control characters`};if(containsPathTraversal(value))return{error:!0,type:"path-escape",message:`${kind} pattern contains path traversal sequence`};return null}var ast_grep=createSwarmTool({description:"Read-only structural AST search using ast-grep. Searches code patterns with optional language and glob filters; does not rewrite files.",args:{pattern:exports_external.string().describe("ast-grep pattern to search for"),language:exports_external.string().optional().describe("Optional ast-grep language, e.g. ts, tsx, js, py, rust"),include:exports_external.string().optional().describe("Comma-separated include globs, passed to ast-grep --globs"),exclude:exports_external.string().optional().describe("Comma-separated exclude globs, passed to ast-grep as !glob"),max_results:exports_external.number().default(DEFAULT_MAX_RESULTS2).describe("Maximum number of matches to return")},execute:async(args2,directory)=>{let pattern,language,include,exclude,maxResults=DEFAULT_MAX_RESULTS2;try{let obj=args2;pattern=typeof obj.pattern==="string"?obj.pattern:"",language=typeof obj.language==="string"?obj.language:void 0,include=typeof obj.include==="string"?obj.include:void 0,exclude=typeof obj.exclude==="string"?obj.exclude:void 0;let rawMaxResults=typeof obj.max_results==="number"?obj.max_results:DEFAULT_MAX_RESULTS2,sanitizedMaxResults=Number.isFinite(rawMaxResults)?rawMaxResults:DEFAULT_MAX_RESULTS2;maxResults=Math.min(Math.max(0,sanitizedMaxResults),HARD_CAP_RESULTS2)}catch{return JSON.stringify({error:!0,type:"invalid-pattern",message:"Could not parse ast_grep arguments"},null,2)}if(!pattern||pattern.trim()==="")return JSON.stringify({error:!0,type:"invalid-pattern",message:"Pattern cannot be empty"},null,2);if(pattern.length>MAX_PATTERN_LENGTH||containsControlChars(pattern))return JSON.stringify({error:!0,type:"invalid-pattern",message:`Pattern is invalid or exceeds ${MAX_PATTERN_LENGTH} characters`},null,2);if(language&&!/^[A-Za-z0-9_-]+$/.test(language))return JSON.stringify({error:!0,type:"invalid-pattern",message:"Language must contain only letters, numbers, _ or -"},null,2);let includeError=validateGlobArg("Include",include);if(includeError)return JSON.stringify(includeError,null,2);let excludeError=validateGlobArg("Exclude",exclude);if(excludeError)return JSON.stringify(excludeError,null,2);if(!fs102.existsSync(directory))return JSON.stringify({error:!0,type:"unknown",message:"Workspace directory does not exist"},null,2);let executable=_internals107.resolveAstGrepBinary();if(!executable)return JSON.stringify({error:!0,type:"ast-grep-not-found",message:"ast-grep executable not found. Install ast-grep and ensure ast-grep or sg is on PATH."},null,2);let sgArgs=["run","--pattern",pattern,"--json=stream","--color","never"];if(language)sgArgs.push("--lang",language);for(let glob of splitGlobPatterns(include))sgArgs.push("--globs",glob);for(let glob of splitGlobPatterns(exclude))sgArgs.push("--globs",`!${glob}`);sgArgs.push(".");let run=await _internals107.runExternalTool({executable,args:sgArgs,cwd:directory,timeoutMs:AST_GREP_TIMEOUT_MS,maxStdoutBytes:AST_GREP_MAX_STDOUT_BYTES,maxStderrBytes:AST_GREP_MAX_STDERR_BYTES});if(run.status==="timeout")return JSON.stringify({error:!0,type:"timeout",message:`ast-grep timed out after ${AST_GREP_TIMEOUT_MS}ms`},null,2);if(run.status==="spawn-error")return JSON.stringify({error:!0,type:"unknown",message:run.message??"ast-grep failed to start"},null,2);if(run.exitCode!==0&&run.stderr)return JSON.stringify({error:!0,type:"invalid-pattern",message:run.stderr.split(`
|
|
5849
|
-
`)[0]},null,2);let{matches,total}=parseAstGrepStream(run.stdout,directory,maxResults);return JSON.stringify({matches,truncated:total>maxResults||run.stdoutTruncated||run.stderrTruncated,total,pattern,language,maxResults,outputTruncated:run.stdoutTruncated||run.stderrTruncated},null,2)}}),_internals107={resolveExecutableFromPath,resolveAstGrepBinary,runExternalTool,parseAstGrepStream};init_dist();init_create_tool();import*as fs103 from"node:fs";import*as path175 from"node:path";init_path_security();var WINDOWS_RESERVED_NAMES4=/^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;function containsWindowsAttacks3(str){if(/:[^\\/]/.test(str))return!0;let parts=str.split(/[/\\]/);for(let part of parts)if(WINDOWS_RESERVED_NAMES4.test(part))return!0;return!1}function isPathInWorkspace2(filePath,workspace){try{let resolvedPath=path175.resolve(workspace,filePath);if(!fs103.existsSync(resolvedPath))return!0;let realWorkspace=fs103.realpathSync(workspace),realResolvedPath=fs103.realpathSync(resolvedPath),relativePath=path175.relative(realWorkspace,realResolvedPath);if(relativePath.startsWith("..")||path175.isAbsolute(relativePath))return!1;return!0}catch{return!1}}function processFile(file3,cwd,exportedOnly){let ext=path175.extname(file3);if(containsControlChars(file3))return{file:file3,success:!1,error:"Path contains invalid control characters",errorType:"invalid-path"};if(containsPathTraversal(file3))return{file:file3,success:!1,error:"Path contains path traversal sequence",errorType:"path-traversal"};if(containsWindowsAttacks3(file3))return{file:file3,success:!1,error:"Path contains invalid Windows-specific sequence",errorType:"invalid-path"};if(!isPathInWorkspace2(file3,cwd))return{file:file3,success:!1,error:"Path is outside workspace",errorType:"path-outside-workspace"};let fullPath=path175.join(cwd,file3);if(!fs103.existsSync(fullPath))return{file:file3,success:!1,error:`File not found: ${file3}`,errorType:"file-not-found"};let syms;switch(ext){case".ts":case".tsx":case".js":case".jsx":case".mjs":case".cjs":syms=extractTSSymbols(file3,cwd);break;case".py":case".pyw":syms=extractPythonSymbols(file3,cwd);break;case".rs":syms=extractRustSymbols(file3,cwd);break;case".go":syms=extractGoSymbols(file3,cwd);break;default:return{file:file3,success:!1,error:`Unsupported file extension: ${ext}. Supported: .ts, .tsx, .js, .jsx, .mjs, .cjs, .py, .pyw, .rs, .go`,errorType:"unsupported-language"}}let isEmptyFile=!1;try{if(fs103.statSync(fullPath).size===0)isEmptyFile=!0}catch{}if(syms.length===0)try{if(fs103.readFileSync(fullPath,"utf-8").trim().length===0)isEmptyFile=!0}catch{}if(isEmptyFile)return{file:file3,success:!0,symbols:[],error:"empty-file",errorType:"empty-file"};if(exportedOnly)syms=syms.filter((s)=>s.exported);return{file:file3,success:!0,symbols:syms}}var batch_symbols=createSwarmTool({description:"Extract symbols from multiple files in a single batch call. Accepts an array of file paths and returns per-file symbol summaries. One bad file does not crash the batch. Use for surveying a module when you need symbol information from multiple files at once.",args:{files:tool.schema.array(tool.schema.string()).describe("Array of file paths to extract symbols from"),exported_only:tool.schema.boolean().default(!0).describe("If true, only return exported/public symbols. If false, include all top-level symbols.")},execute:async(args2,directory)=>{let files,exportedOnly=!0;try{let obj=args2;if(!Array.isArray(obj.files))return JSON.stringify({results:[],totalFiles:0,successCount:0,failureCount:0,error:"Invalid arguments: files must be an array"},null,2);files=obj.files.map((f)=>String(f)),exportedOnly=obj.exported_only!==!1}catch{return JSON.stringify({results:[],totalFiles:0,successCount:0,failureCount:0,error:"Invalid arguments: could not extract files array"},null,2)}let cwd=directory,results=[];for(let file3 of files){let result=processFile(file3,cwd,exportedOnly);results.push(result)}let successCount=results.filter((r)=>r.success).length,failureCount=results.filter((r)=>!r.success).length,batchResult={results,totalFiles:files.length,successCount,failureCount};return JSON.stringify(batchResult,null,2)}});init_zod();init_discovery();init_manager2();init_bun_compat();init_create_tool();var DEFAULT_TIMEOUT_MS2=300000,MAX_OUTPUT_BYTES5=10240,MAX_OUTPUT_LINES=100;function truncateOutput(output,maxLines=MAX_OUTPUT_LINES,maxBytes=MAX_OUTPUT_BYTES5){if(!output)return"";let truncated=output;if(truncated.length>maxBytes)truncated=truncated.slice(-maxBytes);let lines=truncated.split(`
|
|
5849
|
+
`)[0]},null,2);let{matches,total}=parseAstGrepStream(run.stdout,directory,maxResults);return JSON.stringify({matches,truncated:total>maxResults||run.stdoutTruncated||run.stderrTruncated,total,pattern,language,maxResults,outputTruncated:run.stdoutTruncated||run.stderrTruncated},null,2)}}),_internals107={resolveExecutableFromPath,resolveAstGrepBinary,runExternalTool,parseAstGrepStream};init_dist();init_create_tool();import*as fs103 from"node:fs";import*as path175 from"node:path";init_path_security();var WINDOWS_RESERVED_NAMES4=/^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;function containsWindowsAttacks3(str){if(/:[^\\/]/.test(str))return!0;let parts=str.split(/[/\\]/);for(let part of parts)if(WINDOWS_RESERVED_NAMES4.test(part))return!0;return!1}function isPathInWorkspace2(filePath,workspace){try{let resolvedPath=path175.resolve(workspace,filePath);if(!fs103.existsSync(resolvedPath))return!0;let realWorkspace=fs103.realpathSync(workspace),realResolvedPath=fs103.realpathSync(resolvedPath),relativePath=path175.relative(realWorkspace,realResolvedPath);if(relativePath.startsWith("..")||path175.isAbsolute(relativePath))return!1;return!0}catch{return!1}}function processFile(file3,cwd,exportedOnly){let ext=path175.extname(file3);if(containsControlChars(file3))return{file:file3,success:!1,error:"Path contains invalid control characters",errorType:"invalid-path"};if(containsPathTraversal(file3))return{file:file3,success:!1,error:"Path contains path traversal sequence",errorType:"path-traversal"};if(containsWindowsAttacks3(file3))return{file:file3,success:!1,error:"Path contains invalid Windows-specific sequence",errorType:"invalid-path"};if(!isPathInWorkspace2(file3,cwd))return{file:file3,success:!1,error:"Path is outside workspace",errorType:"path-outside-workspace"};let fullPath=path175.join(cwd,file3);if(!fs103.existsSync(fullPath))return{file:file3,success:!1,error:`File not found: ${file3}`,errorType:"file-not-found"};let syms;switch(ext){case".ts":case".tsx":case".js":case".jsx":case".mjs":case".cjs":syms=extractTSSymbols(file3,cwd);break;case".py":case".pyw":syms=extractPythonSymbols(file3,cwd);break;case".rs":syms=extractRustSymbols(file3,cwd);break;case".go":syms=extractGoSymbols(file3,cwd);break;default:return{file:file3,success:!1,error:`Unsupported file extension: ${ext}. Supported: .ts, .tsx, .js, .jsx, .mjs, .cjs, .py, .pyw, .rs, .go`,errorType:"unsupported-language"}}let isEmptyFile=!1;try{if(fs103.statSync(fullPath).size===0)isEmptyFile=!0}catch{}if(syms.length===0)try{if(fs103.readFileSync(fullPath,"utf-8").trim().length===0)isEmptyFile=!0}catch{}if(isEmptyFile)return{file:file3,success:!0,symbols:[],error:"empty-file",errorType:"empty-file"};if(exportedOnly)syms=syms.filter((s)=>s.exported);return{file:file3,success:!0,symbols:syms}}var batch_symbols=createSwarmTool({description:"Extract symbols from multiple files in a single batch call. Accepts an array of file paths and returns per-file symbol summaries. One bad file does not crash the batch. Use for surveying a module when you need symbol information from multiple files at once.",args:{files:tool.schema.array(tool.schema.string()).describe("Array of file paths to extract symbols from"),exported_only:tool.schema.boolean().default(!0).describe("If true, only return exported/public symbols. If false, include all top-level symbols.")},execute:async(args2,directory)=>{let files,exportedOnly=!0;try{let obj=args2;if(!Array.isArray(obj.files))return JSON.stringify({results:[],totalFiles:0,successCount:0,failureCount:0,error:"Invalid arguments: files must be an array"},null,2);files=obj.files.map((f)=>String(f)),exportedOnly=obj.exported_only!==!1}catch{return JSON.stringify({results:[],totalFiles:0,successCount:0,failureCount:0,error:"Invalid arguments: could not extract files array"},null,2)}let cwd=directory,results=[];for(let file3 of files){let result=processFile(file3,cwd,exportedOnly);results.push(result)}let successCount=results.filter((r)=>r.success).length,failureCount=results.filter((r)=>!r.success).length,batchResult={results,totalFiles:files.length,successCount,failureCount};return JSON.stringify(batchResult,null,2)}});init_zod();init_discovery();init_manager2();init_bun_compat();init_logger();init_create_tool();var DEFAULT_TIMEOUT_MS2=300000,MAX_OUTPUT_BYTES5=10240,MAX_OUTPUT_LINES=100;function truncateOutput(output,maxLines=MAX_OUTPUT_LINES,maxBytes=MAX_OUTPUT_BYTES5){if(!output)return"";let truncated=output;if(truncated.length>maxBytes)truncated=truncated.slice(-maxBytes);let lines=truncated.split(`
|
|
5850
5850
|
`);if(lines.length>maxLines)return lines.slice(-maxLines).join(`
|
|
5851
|
-
`);return truncated}function getCommandKind(command){let lower=command.toLowerCase();if(lower.includes("typecheck")||lower.includes("check")||lower.includes("analyze")||lower.includes("lint"))return"typecheck";if(lower.includes("test")||lower.includes("spec")||lower.includes("jest")||lower.includes("vitest")||lower.includes("mocha")||lower.includes("pytest"))return"test";return"build"}function filterByMode(commands,mode){if(mode==="both")return commands;return commands.filter((cmd)=>getCommandKind(cmd.command)===mode)}async function executeCommand(command){let startTime=Date.now(),kind=getCommandKind(command.command),isWindows=process.platform==="win32",cmd,args2;if(isWindows&&!command.command.includes(" "))cmd=[command.command],args2=[];else if(isWindows)cmd=["cmd","/c",command.command],args2=[];else cmd=["/bin/sh"],args2=["-c",command.command];let result=bunSpawn([...cmd,...args2],{cwd:command.cwd,stdout:"pipe",stderr:"pipe",timeout:DEFAULT_TIMEOUT_MS2}),[exitCode,stdout,stderr]=await Promise.all([result.exited,result.stdout.text(),result.stderr.text()]),duration_ms=Date.now()-startTime;return{kind,command:command.command,cwd:command.cwd,exit_code:exitCode??-1,duration_ms,stdout_tail:truncateOutput(stdout),stderr_tail:truncateOutput(stderr)}}async function runBuildCheck(workingDir,input){let scope=input.scope??"all",mode=input.mode??"both",changedFiles=input.changed_files??[],discoveryResult=await discoverBuildCommands(workingDir,{scope,changedFiles}),commands=filterByMode(discoveryResult.commands,mode),runs=[],failedCount=0;for(let cmd of commands)try{let run=await executeCommand(cmd);if(runs.push(run),run.exit_code!==0)failedCount++}catch(error93){runs.push({kind:getCommandKind(cmd.command),command:cmd.command,cwd:cmd.cwd,exit_code:-1,duration_ms:0,stdout_tail:"",stderr_tail:error93 instanceof Error?error93.message:"Unknown error"}),failedCount++}let verdict,skipped_reason;if(runs.length===0)if(verdict="info",discoveryResult.skipped.length>0)skipped_reason=discoveryResult.skipped.map((s)=>`${s.ecosystem}: ${s.reason}`).join("; ");else skipped_reason="No build commands discovered (no toolchains found)";else if(failedCount>0)verdict="fail";else verdict="pass";return{verdict,runs,summary:{files_scanned:changedFiles.length,runs_count:runs.length,failed_count:failedCount,skipped_reason}}}var build_check=createSwarmTool({description:"Discover and run build commands for various ecosystems in a project directory. Supports build, typecheck, and test commands.",args:{scope:exports_external.enum(["changed","all"]).describe('Scope of detection: "all" for all build files, "changed" for only changed files'),changed_files:exports_external.array(exports_external.string()).optional().describe('List of changed files when scope is "changed"'),mode:exports_external.enum(["build","typecheck","both"]).optional().describe('Mode: "build" for build commands, "typecheck" for type checking, "both" for all (default: both)')},async execute(args2,directory){let obj=args2,scope=obj.scope??"all",changedFiles=obj.changed_files??[],mode=obj.mode??"both",workingDir=directory,result=await runBuildCheck(workingDir,{scope,changed_files:changedFiles,mode}),evidence={task_id:"build",type:"build",timestamp:new Date().toISOString(),agent:"build_check",verdict:result.verdict,summary:`${result.runs.length} build command(s) executed, ${result.summary.failed_count} failed`,runs:result.runs,files_scanned:result.summary.files_scanned,runs_count:result.summary.runs_count,failed_count:result.summary.failed_count,skipped_reason:result.summary.skipped_reason};try{await saveEvidence(workingDir,"build",evidence)}catch(error93){console.error("Failed to save build evidence:",error93 instanceof Error?error93.message:String(error93))}return JSON.stringify(result,null,2)}});init_zod();init_manager2();init_task_id();init_create_tool();init_resolve_working_directory();import*as fs104 from"node:fs";import*as path176 from"node:path";var EVIDENCE_DIR=".swarm/evidence";function isValidTaskId4(taskId){return isStrictTaskId(taskId)}function isPathWithinSwarm(filePath,workspaceRoot){let normalizedWorkspace=path176.resolve(workspaceRoot),swarmPath=path176.join(normalizedWorkspace,".swarm","evidence");return path176.resolve(filePath).startsWith(swarmPath)}function readEvidenceFile(evidencePath){if(!fs104.existsSync(evidencePath))return null;let content;try{content=fs104.readFileSync(evidencePath,"utf-8")}catch{return null}let parsed;try{parsed=JSON.parse(content)}catch{return null}if(parsed&&typeof parsed==="object"&&Array.isArray(parsed.required_gates)&&typeof parsed.gates==="object"&&parsed.gates!==null)return parsed;return null}var check_gate_status=createSwarmTool({description:"Read-only tool to check the gate status of a specific task. Reads .swarm/evidence/{taskId}.json and returns structured JSON describing required, passed, and missing gates.",args:{task_id:exports_external.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/,'Task ID must be in N.M or N.M.P format (e.g., "1.1", "1.2.3", "1.2.3.4")').describe('The task ID to check gate status for (e.g., "1.1", "2.3.1")'),working_directory:exports_external.string().optional().describe("Explicit project root directory. When provided, .swarm/evidence/ is resolved 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 taskIdInput,workingDirInput;try{if(args2&&typeof args2==="object"){let obj=args2;taskIdInput=typeof obj.task_id==="string"?obj.task_id:void 0,workingDirInput=typeof obj.working_directory==="string"?obj.working_directory:void 0}}catch{}let dirResult=resolveWorkingDirectory(workingDirInput,directory);if(!dirResult.success){let errorResult={taskId:taskIdInput??"",status:"no_evidence",required_gates:[],passed_gates:[],missing_gates:[],gates:{},message:dirResult.message,todo_scan:null};return JSON.stringify(errorResult,null,2)}if(directory=dirResult.directory,!taskIdInput)return JSON.stringify({taskId:"",status:"no_evidence",required_gates:[],passed_gates:[],missing_gates:[],gates:{},message:"Invalid task_id: task_id is required",todo_scan:null},null,2);if(!isValidTaskId4(taskIdInput)){let errorResult={taskId:taskIdInput,status:"no_evidence",required_gates:[],passed_gates:[],missing_gates:[],gates:{},message:`Invalid task_id format: "${taskIdInput}". Must match N.M or N.M.P (e.g. "1.1", "1.2.3", "1.2.3.4")`,todo_scan:null};return JSON.stringify(errorResult,null,2)}let evidencePath=path176.join(directory,EVIDENCE_DIR,`${taskIdInput}.json`);if(!isPathWithinSwarm(evidencePath,directory))return JSON.stringify({taskId:taskIdInput,status:"no_evidence",required_gates:[],passed_gates:[],missing_gates:[],gates:{},message:"Invalid path: evidence path validation failed",todo_scan:null},null,2);let evidenceData=readEvidenceFile(evidencePath);if(!evidenceData){let errorResult={taskId:taskIdInput,status:"no_evidence",required_gates:[],passed_gates:[],missing_gates:[],gates:{},message:`No evidence file found for task "${taskIdInput}" at ${evidencePath}. Evidence file may be missing or invalid.`,todo_scan:null};return JSON.stringify(errorResult,null,2)}let requiredGates=evidenceData.required_gates||[],gatesMap=evidenceData.gates||{},passedGates=[],missingGates=[];for(let requiredGate of requiredGates)if(gatesMap[requiredGate])passedGates.push(requiredGate);else missingGates.push(requiredGate);let status=missingGates.length===0?"all_passed":"incomplete",message;if(status==="all_passed")message=`All required gates have passed for task "${taskIdInput}".`;else message=`Task "${taskIdInput}" is incomplete. Missing gates: ${missingGates.join(", ")}.`;let secretscanVerdict="not_run";try{let evidenceResult=await loadEvidence(directory,taskIdInput);if(evidenceResult.status==="found"){let secretscanEntries=evidenceResult.bundle.entries.filter((entry)=>entry.type==="secretscan");if(secretscanEntries.length>0){let lastSecretscan=secretscanEntries[secretscanEntries.length-1];if(isSecretscanEvidence(lastSecretscan)){if(lastSecretscan.verdict==="fail"||lastSecretscan.verdict==="rejected"){if(secretscanVerdict="fail",missingGates.push("secretscan (BLOCKED — secrets detected)"),status==="all_passed")status="incomplete";message=`BLOCKED: Secretscan found secrets in prior scan. ${message}`}else if(lastSecretscan.verdict==="pass"||lastSecretscan.verdict==="approved"||lastSecretscan.verdict==="info")secretscanVerdict="pass"}}else message+=" Advisory: No secretscan evidence found for this task. Consider running secretscan."}}catch{}let todoScan=evidenceData.todo_scan;return JSON.stringify({taskId:taskIdInput,status,required_gates:requiredGates,passed_gates:passedGates,missing_gates:missingGates,gates:gatesMap,message,todo_scan:todoScan??null,secretscan_verdict:secretscanVerdict},null,2)}});init_checkpoint();init_co_change_analyzer();init_zod();init_utils2();init_state2();init_create_tool();init_resolve_working_directory();import*as fs105 from"node:fs";import*as path177 from"node:path";function extractMatches(regex,text){return Array.from(text.matchAll(regex))}function parseIdentifiers(description){let identifiers=new Set,backtickRegex=/`([^`]+)`/g;for(let match of extractMatches(backtickRegex,description))identifiers.add(match[1]);let camelCaseRegex=/\b([a-z][a-zA-Z0-9]{2,})\b/g;for(let match of extractMatches(camelCaseRegex,description)){let word=match[1];if(word==="the"||word==="and"||word==="for"||word==="have"||word==="this"||word==="with"||word==="from"||word==="they"||word==="been"||word==="will"||word==="your"||word==="also")continue;identifiers.add(word)}let pascalCaseRegex=/\b([A-Z][a-zA-Z0-9]{2,})\b/g;for(let match of extractMatches(pascalCaseRegex,description))identifiers.add(match[1]);let configKeyRegex=/\b([a-z][a-zA-Z0-9]*(?:\.[a-z][a-zA-Z0-9]*)+)\b/g;for(let match of extractMatches(configKeyRegex,description))identifiers.add(match[1]);let quotedPathRegex=/['"](\.{0,3}(?:src|lib|test)[/\\][^'"]+)['"]/g;for(let match of extractMatches(quotedPathRegex,description))identifiers.add(match[1]);return Array.from(identifiers)}function parseFilePaths(description,filesTouched){if(filesTouched&&Array.isArray(filesTouched)&&filesTouched.length>0)return filesTouched;let filePaths=[],srcPathRegex=/\b(?:src|lib|test|app|packages?)[/\\][a-zA-Z0-9_./-]+\.(?:ts|tsx|js|jsx|mjs|cjs)\b/g;for(let match of extractMatches(srcPathRegex,description))filePaths.push(match[0]);let genericPathRegex=/\b[a-zA-Z0-9_./-]+[/\\][a-zA-Z0-9_./-]+\.[a-zA-Z0-9]+(?=\s|$|[.,;])/g;for(let match of extractMatches(genericPathRegex,description)){let pathStr=match[0];if(pathStr.includes("src/")||pathStr.includes("src\\")||pathStr.includes("lib/")||pathStr.includes("lib\\")||pathStr.includes("test/")||pathStr.includes("test\\"))filePaths.push(pathStr)}return filePaths}function buildVerifySummary(tasksChecked,tasksSkipped,tasksBlocked){if(tasksBlocked>0)return`Blocked: ${tasksBlocked} task(s) with missing identifiers`;let verified=tasksChecked-tasksSkipped;if(tasksSkipped===tasksChecked)return`All ${tasksChecked} completed task(s) skipped — research/inventory tasks`;if(tasksSkipped>0)return`${verified} task(s) verified, ${tasksSkipped} skipped (research tasks)`;return`All ${tasksChecked} completed tasks verified successfully`}async function executeCompletionVerify(args2,directory){let phase=Number(args2.phase);if(Number.isNaN(phase)||phase<1||!Number.isFinite(phase))return JSON.stringify({success:!1,phase,status:"blocked",reason:"Invalid phase number",tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]},null,2);if(hasActiveTurboMode(args2.sessionID))return JSON.stringify({success:!0,phase,status:"passed",reason:"Turbo Mode active — completion verification bypassed",tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]},null,2);let plan;try{let planPath=validateSwarmPath(directory,"plan.json"),planRaw=fs105.readFileSync(planPath,"utf-8");plan=JSON.parse(planRaw)}catch{return JSON.stringify({success:!0,phase,status:"passed",reason:"Cannot verify without plan.json",tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]},null,2)}let targetPhase=plan.phases.find((p)=>p.id===phase);if(!targetPhase){let result2={success:!1,phase,status:"blocked",reason:`Phase ${phase} not found in plan.json`,tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]};return JSON.stringify(result2,null,2)}let tasksChecked=0,tasksSkipped=0,tasksBlocked=0,blockedTasks=[];for(let task of targetPhase.tasks){if(task.status!=="completed")continue;tasksChecked++;let fileTargets=parseFilePaths(task.description,task.files_touched),identifiers=parseIdentifiers(task.description);if(fileTargets.length===0){tasksSkipped++;continue}if(identifiers.length===0){blockedTasks.push({task_id:task.id,identifier:"",file_path:"",reason:"No identifiers — cannot verify completion without identifiers"}),tasksBlocked++;continue}let foundIdentifiers=new Set,hasFileReadFailure=!1;for(let filePath of fileTargets){let normalizedPath=filePath.replace(/\\/g,"/"),resolvedPath=path177.resolve(directory,normalizedPath),projectRoot=path177.resolve(directory),relative37=path177.relative(projectRoot,resolvedPath);if(!(relative37===""||!relative37.startsWith("..")&&!path177.isAbsolute(relative37))){blockedTasks.push({task_id:task.id,identifier:"",file_path:filePath,reason:`File path '${filePath}' escapes the project directory — cannot verify completion`}),hasFileReadFailure=!0;continue}let fileContent;try{fileContent=fs105.readFileSync(resolvedPath,"utf-8")}catch{blockedTasks.push({task_id:task.id,identifier:"",file_path:filePath,reason:`File '${filePath}' not found — cannot verify completion`}),hasFileReadFailure=!0;continue}for(let identifier of identifiers)if(fileContent.includes(identifier))foundIdentifiers.add(identifier)}let foundCount=foundIdentifiers.size;if(hasFileReadFailure||foundCount===0){if(!hasFileReadFailure)blockedTasks.push({task_id:task.id,identifier:"",file_path:"",reason:"No identifiers found in target files"});tasksBlocked++}}let now=new Date().toISOString(),result={success:tasksBlocked===0,phase,status:tasksBlocked===0?"passed":"blocked",reason:tasksBlocked>0?`COMPLETION_INCOMPLETE: ${tasksBlocked} task(s) blocked — missing identifiers or target files`:void 0,tasksChecked,tasksSkipped,tasksBlocked,blockedTasks};try{let evidenceDir=path177.join(directory,".swarm","evidence",`${phase}`),evidencePath=path177.join(evidenceDir,"completion-verify.json");fs105.mkdirSync(evidenceDir,{recursive:!0});let evidenceBundle={schema_version:"1.0.0",task_id:"completion-verify",created_at:now,entries:[{task_id:"completion-verify",type:"completion_verify",timestamp:now,agent:"completion_verify",verdict:tasksBlocked===0?"pass":"fail",summary:buildVerifySummary(tasksChecked,tasksSkipped,tasksBlocked),phase,tasks_checked:tasksChecked,tasks_skipped:tasksSkipped,tasks_blocked:tasksBlocked,blocked_tasks:blockedTasks}]};fs105.writeFileSync(evidencePath,JSON.stringify(evidenceBundle,null,2),"utf-8")}catch{}return JSON.stringify(result,null,2)}var completion_verify=createSwarmTool({description:"Deterministic pre-check verifying that plan task identifiers exist in their target source files before phase completion. Blocks if obviously incomplete.",args:{phase:exports_external.number().describe("The phase number to check"),sessionID:exports_external.string().optional().describe("Session ID for tracking state (auto-provided by plugin context)"),working_directory:exports_external.string().optional().describe("Explicit project root directory. When provided, .swarm/ is resolved relative to this path instead of the plugin context directory. Use this when CWD differs from the actual project root.")},execute:async(args2,directory)=>{let parsedArgs;try{if(args2&&typeof args2==="object"){let obj=args2;parsedArgs={phase:typeof obj.phase==="number"?obj.phase:typeof obj.phase==="string"?Number(obj.phase):0,sessionID:typeof obj.sessionID==="string"?obj.sessionID:void 0,working_directory:typeof obj.working_directory==="string"?obj.working_directory:void 0}}else parsedArgs={phase:0}}catch{return JSON.stringify({success:!1,phase:0,status:"blocked",reason:"Invalid arguments",tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]},null,2)}let dirResult=resolveWorkingDirectory(parsedArgs.working_directory,directory);if(!dirResult.success)return JSON.stringify({success:!1,phase:parsedArgs.phase,status:"blocked",reason:dirResult.message,tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]},null,2);return executeCompletionVerify(parsedArgs,dirResult.directory)}});init_zod();import*as fs107 from"node:fs";import*as path179 from"node:path";import*as fs106 from"node:fs";import*as path178 from"node:path";var MAX_FILE_SIZE_BYTES3=262144,MIN_DUPLICATION_LINES=10;function estimateCyclomaticComplexity(content){let processed=content.replace(/\/\*[\s\S]*?\*\//g,"");processed=processed.replace(/\/\/.*/g,""),processed=processed.replace(/#.*/g,""),processed=processed.replace(/'[^']*'/g,""),processed=processed.replace(/"[^"]*"/g,""),processed=processed.replace(/`[^`]*`/g,"");let complexity=1,decisionPatterns=[/\bif\b/g,/\belse\s+if\b/g,/\bfor\b/g,/\bwhile\b/g,/\bswitch\b/g,/\bcase\b/g,/\bcatch\b/g,/\?\./g,/\?\?/g,/&&/g,/\|\|/g];for(let pattern of decisionPatterns){let matches=processed.match(pattern);if(matches)complexity+=matches.length}let ternaryMatches=processed.match(/\?[^:]/g);if(ternaryMatches)complexity+=ternaryMatches.length;return complexity}function getComplexityForFile(filePath){try{if(fs106.statSync(filePath).size>MAX_FILE_SIZE_BYTES3)return null;let content=fs106.readFileSync(filePath,"utf-8");return estimateCyclomaticComplexity(content)}catch{return null}}async function computeComplexityDelta(files,workingDir){let totalComplexity=0,analyzedFiles=[];for(let file3 of files){let fullPath=path178.isAbsolute(file3)?file3:path178.join(workingDir,file3);if(!fs106.existsSync(fullPath))continue;let complexity=getComplexityForFile(fullPath);if(complexity!==null)totalComplexity+=complexity,analyzedFiles.push(file3)}return{delta:totalComplexity,analyzedFiles}}function countExportsInFile(content){let count=0,exportFunctionMatches=content.match(/export\s+function\s+\w+/g);if(exportFunctionMatches)count+=exportFunctionMatches.length;let exportClassMatches=content.match(/export\s+class\s+\w+/g);if(exportClassMatches)count+=exportClassMatches.length;let exportConstMatches=content.match(/export\s+const\s+\w+/g);if(exportConstMatches)count+=exportConstMatches.length;let exportLetMatches=content.match(/export\s+let\s+\w+/g);if(exportLetMatches)count+=exportLetMatches.length;let exportVarMatches=content.match(/export\s+var\s+\w+/g);if(exportVarMatches)count+=exportVarMatches.length;let exportNamedMatches=content.match(/export\s*\{[^}]+\}/g);if(exportNamedMatches)for(let match of exportNamedMatches){let names=match.match(/\b[a-zA-Z_$][a-zA-Z0-9_$]*\b/g),filteredNames=names?names.filter((n)=>n!=="export"):[];count+=filteredNames.length}let exportDefaultMatches=content.match(/export\s+default/g);if(exportDefaultMatches)count+=exportDefaultMatches.length;let exportTypeMatches=content.match(/export\s+(type|interface)\s+\w+/g);if(exportTypeMatches)count+=exportTypeMatches.length;let exportEnumMatches=content.match(/export\s+enum\s+\w+/g);if(exportEnumMatches)count+=exportEnumMatches.length;let exportEqualsMatches=content.match(/export\s+=/g);if(exportEqualsMatches)count+=exportEqualsMatches.length;return count}function countPythonExports(content){let count=0,noStrings=content.replace(/#.*/g,"").replace(/"[^"]*"/g,"").replace(/'[^']*'/g,""),functionMatches=noStrings.match(/^\s*def\s+\w+/gm);if(functionMatches)count+=functionMatches.length;let classMatches=noStrings.match(/^\s*class\s+\w+/gm);if(classMatches)count+=classMatches.length;let allMatchOriginal=content.match(/__all__\s*=\s*\[([^\]]+)\]/);if(allMatchOriginal?.[1]){let names=allMatchOriginal[1].match(/['"]?(\w+)['"]?/g);if(names){let cleanNames=names.map((n)=>n.replace(/['"]/g,""));count+=cleanNames.length}}return count}function countRustExports(content){let count=0,processed=content.replace(/\/\/.*/g,"");processed=processed.replace(/\/\*[\s\S]*?\*\//g,"");let pubFnMatches=processed.match(/pub\s+fn\s+\w+/g);if(pubFnMatches)count+=pubFnMatches.length;let pubStructMatches=processed.match(/pub\s+struct\s+\w+/g);if(pubStructMatches)count+=pubStructMatches.length;let pubEnumMatches=processed.match(/pub\s+enum\s+\w+/g);if(pubEnumMatches)count+=pubEnumMatches.length;let pubUseMatches=processed.match(/pub\s+use\s+/g);if(pubUseMatches)count+=pubUseMatches.length;let pubConstMatches=processed.match(/pub\s+const\s+\w+/g);if(pubConstMatches)count+=pubConstMatches.length;let pubModMatches=processed.match(/pub\s+mod\s+\w+/g);if(pubModMatches)count+=pubModMatches.length;let pubTypeMatches=processed.match(/pub\s+type\s+\w+/g);if(pubTypeMatches)count+=pubTypeMatches.length;return count}function countGoExports(content){let count=0,processed=content.replace(/\/\/.*/gm,"");processed=processed.replace(/\/\*[\s\S]*?\*\//g,"");let exportedFuncMatches=processed.match(/^\s*func\s+[A-Z]\w*/gm);if(exportedFuncMatches)count+=exportedFuncMatches.length;let exportedVarMatches=processed.match(/^\s*var\s+[A-Z]\w*/gm);if(exportedVarMatches)count+=exportedVarMatches.length;let exportedTypeMatches=processed.match(/^\s*type\s+[A-Z]\w*/gm);if(exportedTypeMatches)count+=exportedTypeMatches.length;let exportedConstMatches=processed.match(/^\s*const\s+[A-Z]\w*/gm);if(exportedConstMatches)count+=exportedConstMatches.length;if(processed.match(/^\s*package\s+\w+/m))count+=1;return count}function getExportCountForFile(filePath){try{let content=fs106.readFileSync(filePath,"utf-8");switch(path178.extname(filePath).toLowerCase()){case".ts":case".tsx":case".js":case".jsx":case".mjs":case".cjs":return countExportsInFile(content);case".py":return countPythonExports(content);case".rs":return countRustExports(content);case".go":return countGoExports(content);default:return countExportsInFile(content)}}catch{return 0}}async function computePublicApiDelta(files,workingDir){let totalExports=0,analyzedFiles=[];for(let file3 of files){let fullPath=path178.isAbsolute(file3)?file3:path178.join(workingDir,file3);if(!fs106.existsSync(fullPath))continue;let exports=getExportCountForFile(fullPath);totalExports+=exports,analyzedFiles.push(file3)}return{delta:totalExports,analyzedFiles}}function findDuplicateLines(content,minLines){let lines=content.split(`
|
|
5851
|
+
`);return truncated}function getCommandKind(command){let lower=command.toLowerCase();if(lower.includes("typecheck")||lower.includes("check")||lower.includes("analyze")||lower.includes("lint"))return"typecheck";if(lower.includes("test")||lower.includes("spec")||lower.includes("jest")||lower.includes("vitest")||lower.includes("mocha")||lower.includes("pytest"))return"test";return"build"}function filterByMode(commands,mode){if(mode==="both")return commands;return commands.filter((cmd)=>getCommandKind(cmd.command)===mode)}async function executeCommand(command){let startTime=Date.now(),kind=getCommandKind(command.command),isWindows=process.platform==="win32",cmd,args2;if(isWindows&&!command.command.includes(" "))cmd=[command.command],args2=[];else if(isWindows)cmd=["cmd","/c",command.command],args2=[];else cmd=["/bin/sh"],args2=["-c",command.command];let result=bunSpawn([...cmd,...args2],{cwd:command.cwd,stdout:"pipe",stderr:"pipe",timeout:DEFAULT_TIMEOUT_MS2}),[exitCode,stdout,stderr]=await Promise.all([result.exited,result.stdout.text(),result.stderr.text()]),duration_ms=Date.now()-startTime;return{kind,command:command.command,cwd:command.cwd,exit_code:exitCode??-1,duration_ms,stdout_tail:truncateOutput(stdout),stderr_tail:truncateOutput(stderr)}}async function runBuildCheck(workingDir,input){let scope=input.scope??"all",mode=input.mode??"both",changedFiles=input.changed_files??[],discoveryResult=await discoverBuildCommands(workingDir,{scope,changedFiles}),commands=filterByMode(discoveryResult.commands,mode),runs=[],failedCount=0;for(let cmd of commands)try{let run=await executeCommand(cmd);if(runs.push(run),run.exit_code!==0)failedCount++}catch(error93){runs.push({kind:getCommandKind(cmd.command),command:cmd.command,cwd:cmd.cwd,exit_code:-1,duration_ms:0,stdout_tail:"",stderr_tail:error93 instanceof Error?error93.message:"Unknown error"}),failedCount++}let verdict,skipped_reason;if(runs.length===0)if(verdict="info",discoveryResult.skipped.length>0)skipped_reason=discoveryResult.skipped.map((s)=>`${s.ecosystem}: ${s.reason}`).join("; ");else skipped_reason="No build commands discovered (no toolchains found)";else if(failedCount>0)verdict="fail";else verdict="pass";return{verdict,runs,summary:{files_scanned:changedFiles.length,runs_count:runs.length,failed_count:failedCount,skipped_reason}}}var build_check=createSwarmTool({description:"Discover and run build commands for various ecosystems in a project directory. Supports build, typecheck, and test commands.",args:{scope:exports_external.enum(["changed","all"]).describe('Scope of detection: "all" for all build files, "changed" for only changed files'),changed_files:exports_external.array(exports_external.string()).optional().describe('List of changed files when scope is "changed"'),mode:exports_external.enum(["build","typecheck","both"]).optional().describe('Mode: "build" for build commands, "typecheck" for type checking, "both" for all (default: both)')},async execute(args2,directory){let obj=args2,scope=obj.scope??"all",changedFiles=obj.changed_files??[],mode=obj.mode??"both",workingDir=directory,result=await runBuildCheck(workingDir,{scope,changed_files:changedFiles,mode}),evidence={task_id:"build",type:"build",timestamp:new Date().toISOString(),agent:"build_check",verdict:result.verdict,summary:`${result.runs.length} build command(s) executed, ${result.summary.failed_count} failed`,runs:result.runs,files_scanned:result.summary.files_scanned,runs_count:result.summary.runs_count,failed_count:result.summary.failed_count,skipped_reason:result.summary.skipped_reason};try{await saveEvidence(workingDir,"build",evidence)}catch(error93){log("Failed to save build evidence:",error93 instanceof Error?error93.message:String(error93))}return JSON.stringify(result,null,2)}});init_zod();init_manager2();init_task_id();init_create_tool();init_resolve_working_directory();import*as fs104 from"node:fs";import*as path176 from"node:path";var EVIDENCE_DIR=".swarm/evidence";function isValidTaskId4(taskId){return isStrictTaskId(taskId)}function isPathWithinSwarm(filePath,workspaceRoot){let normalizedWorkspace=path176.resolve(workspaceRoot),swarmPath=path176.join(normalizedWorkspace,".swarm","evidence");return path176.resolve(filePath).startsWith(swarmPath)}function readEvidenceFile(evidencePath){if(!fs104.existsSync(evidencePath))return null;let content;try{content=fs104.readFileSync(evidencePath,"utf-8")}catch{return null}let parsed;try{parsed=JSON.parse(content)}catch{return null}if(parsed&&typeof parsed==="object"&&Array.isArray(parsed.required_gates)&&typeof parsed.gates==="object"&&parsed.gates!==null)return parsed;return null}var check_gate_status=createSwarmTool({description:"Read-only tool to check the gate status of a specific task. Reads .swarm/evidence/{taskId}.json and returns structured JSON describing required, passed, and missing gates.",args:{task_id:exports_external.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/,'Task ID must be in N.M or N.M.P format (e.g., "1.1", "1.2.3", "1.2.3.4")').describe('The task ID to check gate status for (e.g., "1.1", "2.3.1")'),working_directory:exports_external.string().optional().describe("Explicit project root directory. When provided, .swarm/evidence/ is resolved 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 taskIdInput,workingDirInput;try{if(args2&&typeof args2==="object"){let obj=args2;taskIdInput=typeof obj.task_id==="string"?obj.task_id:void 0,workingDirInput=typeof obj.working_directory==="string"?obj.working_directory:void 0}}catch{}let dirResult=resolveWorkingDirectory(workingDirInput,directory);if(!dirResult.success){let errorResult={taskId:taskIdInput??"",status:"no_evidence",required_gates:[],passed_gates:[],missing_gates:[],gates:{},message:dirResult.message,todo_scan:null};return JSON.stringify(errorResult,null,2)}if(directory=dirResult.directory,!taskIdInput)return JSON.stringify({taskId:"",status:"no_evidence",required_gates:[],passed_gates:[],missing_gates:[],gates:{},message:"Invalid task_id: task_id is required",todo_scan:null},null,2);if(!isValidTaskId4(taskIdInput)){let errorResult={taskId:taskIdInput,status:"no_evidence",required_gates:[],passed_gates:[],missing_gates:[],gates:{},message:`Invalid task_id format: "${taskIdInput}". Must match N.M or N.M.P (e.g. "1.1", "1.2.3", "1.2.3.4")`,todo_scan:null};return JSON.stringify(errorResult,null,2)}let evidencePath=path176.join(directory,EVIDENCE_DIR,`${taskIdInput}.json`);if(!isPathWithinSwarm(evidencePath,directory))return JSON.stringify({taskId:taskIdInput,status:"no_evidence",required_gates:[],passed_gates:[],missing_gates:[],gates:{},message:"Invalid path: evidence path validation failed",todo_scan:null},null,2);let evidenceData=readEvidenceFile(evidencePath);if(!evidenceData){let errorResult={taskId:taskIdInput,status:"no_evidence",required_gates:[],passed_gates:[],missing_gates:[],gates:{},message:`No evidence file found for task "${taskIdInput}" at ${evidencePath}. Evidence file may be missing or invalid.`,todo_scan:null};return JSON.stringify(errorResult,null,2)}let requiredGates=evidenceData.required_gates||[],gatesMap=evidenceData.gates||{},passedGates=[],missingGates=[];for(let requiredGate of requiredGates)if(gatesMap[requiredGate])passedGates.push(requiredGate);else missingGates.push(requiredGate);let status=missingGates.length===0?"all_passed":"incomplete",message;if(status==="all_passed")message=`All required gates have passed for task "${taskIdInput}".`;else message=`Task "${taskIdInput}" is incomplete. Missing gates: ${missingGates.join(", ")}.`;let secretscanVerdict="not_run";try{let evidenceResult=await loadEvidence(directory,taskIdInput);if(evidenceResult.status==="found"){let secretscanEntries=evidenceResult.bundle.entries.filter((entry)=>entry.type==="secretscan");if(secretscanEntries.length>0){let lastSecretscan=secretscanEntries[secretscanEntries.length-1];if(isSecretscanEvidence(lastSecretscan)){if(lastSecretscan.verdict==="fail"||lastSecretscan.verdict==="rejected"){if(secretscanVerdict="fail",missingGates.push("secretscan (BLOCKED — secrets detected)"),status==="all_passed")status="incomplete";message=`BLOCKED: Secretscan found secrets in prior scan. ${message}`}else if(lastSecretscan.verdict==="pass"||lastSecretscan.verdict==="approved"||lastSecretscan.verdict==="info")secretscanVerdict="pass"}}else message+=" Advisory: No secretscan evidence found for this task. Consider running secretscan."}}catch{}let todoScan=evidenceData.todo_scan;return JSON.stringify({taskId:taskIdInput,status,required_gates:requiredGates,passed_gates:passedGates,missing_gates:missingGates,gates:gatesMap,message,todo_scan:todoScan??null,secretscan_verdict:secretscanVerdict},null,2)}});init_checkpoint();init_co_change_analyzer();init_zod();init_utils2();init_state2();init_create_tool();init_resolve_working_directory();import*as fs105 from"node:fs";import*as path177 from"node:path";function extractMatches(regex,text){return Array.from(text.matchAll(regex))}function parseIdentifiers(description){let identifiers=new Set,backtickRegex=/`([^`]+)`/g;for(let match of extractMatches(backtickRegex,description))identifiers.add(match[1]);let camelCaseRegex=/\b([a-z][a-zA-Z0-9]{2,})\b/g;for(let match of extractMatches(camelCaseRegex,description)){let word=match[1];if(word==="the"||word==="and"||word==="for"||word==="have"||word==="this"||word==="with"||word==="from"||word==="they"||word==="been"||word==="will"||word==="your"||word==="also")continue;identifiers.add(word)}let pascalCaseRegex=/\b([A-Z][a-zA-Z0-9]{2,})\b/g;for(let match of extractMatches(pascalCaseRegex,description))identifiers.add(match[1]);let configKeyRegex=/\b([a-z][a-zA-Z0-9]*(?:\.[a-z][a-zA-Z0-9]*)+)\b/g;for(let match of extractMatches(configKeyRegex,description))identifiers.add(match[1]);let quotedPathRegex=/['"](\.{0,3}(?:src|lib|test)[/\\][^'"]+)['"]/g;for(let match of extractMatches(quotedPathRegex,description))identifiers.add(match[1]);return Array.from(identifiers)}function parseFilePaths(description,filesTouched){if(filesTouched&&Array.isArray(filesTouched)&&filesTouched.length>0)return filesTouched;let filePaths=[],srcPathRegex=/\b(?:src|lib|test|app|packages?)[/\\][a-zA-Z0-9_./-]+\.(?:ts|tsx|js|jsx|mjs|cjs)\b/g;for(let match of extractMatches(srcPathRegex,description))filePaths.push(match[0]);let genericPathRegex=/\b[a-zA-Z0-9_./-]+[/\\][a-zA-Z0-9_./-]+\.[a-zA-Z0-9]+(?=\s|$|[.,;])/g;for(let match of extractMatches(genericPathRegex,description)){let pathStr=match[0];if(pathStr.includes("src/")||pathStr.includes("src\\")||pathStr.includes("lib/")||pathStr.includes("lib\\")||pathStr.includes("test/")||pathStr.includes("test\\"))filePaths.push(pathStr)}return filePaths}function buildVerifySummary(tasksChecked,tasksSkipped,tasksBlocked){if(tasksBlocked>0)return`Blocked: ${tasksBlocked} task(s) with missing identifiers`;let verified=tasksChecked-tasksSkipped;if(tasksSkipped===tasksChecked)return`All ${tasksChecked} completed task(s) skipped — research/inventory tasks`;if(tasksSkipped>0)return`${verified} task(s) verified, ${tasksSkipped} skipped (research tasks)`;return`All ${tasksChecked} completed tasks verified successfully`}async function executeCompletionVerify(args2,directory){let phase=Number(args2.phase);if(Number.isNaN(phase)||phase<1||!Number.isFinite(phase))return JSON.stringify({success:!1,phase,status:"blocked",reason:"Invalid phase number",tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]},null,2);if(hasActiveTurboMode(args2.sessionID))return JSON.stringify({success:!0,phase,status:"passed",reason:"Turbo Mode active — completion verification bypassed",tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]},null,2);let plan;try{let planPath=validateSwarmPath(directory,"plan.json"),planRaw=fs105.readFileSync(planPath,"utf-8");plan=JSON.parse(planRaw)}catch{return JSON.stringify({success:!0,phase,status:"passed",reason:"Cannot verify without plan.json",tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]},null,2)}let targetPhase=plan.phases.find((p)=>p.id===phase);if(!targetPhase){let result2={success:!1,phase,status:"blocked",reason:`Phase ${phase} not found in plan.json`,tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]};return JSON.stringify(result2,null,2)}let tasksChecked=0,tasksSkipped=0,tasksBlocked=0,blockedTasks=[];for(let task of targetPhase.tasks){if(task.status!=="completed")continue;tasksChecked++;let fileTargets=parseFilePaths(task.description,task.files_touched),identifiers=parseIdentifiers(task.description);if(fileTargets.length===0){tasksSkipped++;continue}if(identifiers.length===0){blockedTasks.push({task_id:task.id,identifier:"",file_path:"",reason:"No identifiers — cannot verify completion without identifiers"}),tasksBlocked++;continue}let foundIdentifiers=new Set,hasFileReadFailure=!1;for(let filePath of fileTargets){let normalizedPath=filePath.replace(/\\/g,"/"),resolvedPath=path177.resolve(directory,normalizedPath),projectRoot=path177.resolve(directory),relative37=path177.relative(projectRoot,resolvedPath);if(!(relative37===""||!relative37.startsWith("..")&&!path177.isAbsolute(relative37))){blockedTasks.push({task_id:task.id,identifier:"",file_path:filePath,reason:`File path '${filePath}' escapes the project directory — cannot verify completion`}),hasFileReadFailure=!0;continue}let fileContent;try{fileContent=fs105.readFileSync(resolvedPath,"utf-8")}catch{blockedTasks.push({task_id:task.id,identifier:"",file_path:filePath,reason:`File '${filePath}' not found — cannot verify completion`}),hasFileReadFailure=!0;continue}for(let identifier of identifiers)if(fileContent.includes(identifier))foundIdentifiers.add(identifier)}let foundCount=foundIdentifiers.size;if(hasFileReadFailure||foundCount===0){if(!hasFileReadFailure)blockedTasks.push({task_id:task.id,identifier:"",file_path:"",reason:"No identifiers found in target files"});tasksBlocked++}}let now=new Date().toISOString(),result={success:tasksBlocked===0,phase,status:tasksBlocked===0?"passed":"blocked",reason:tasksBlocked>0?`COMPLETION_INCOMPLETE: ${tasksBlocked} task(s) blocked — missing identifiers or target files`:void 0,tasksChecked,tasksSkipped,tasksBlocked,blockedTasks};try{let evidenceDir=path177.join(directory,".swarm","evidence",`${phase}`),evidencePath=path177.join(evidenceDir,"completion-verify.json");fs105.mkdirSync(evidenceDir,{recursive:!0});let evidenceBundle={schema_version:"1.0.0",task_id:"completion-verify",created_at:now,entries:[{task_id:"completion-verify",type:"completion_verify",timestamp:now,agent:"completion_verify",verdict:tasksBlocked===0?"pass":"fail",summary:buildVerifySummary(tasksChecked,tasksSkipped,tasksBlocked),phase,tasks_checked:tasksChecked,tasks_skipped:tasksSkipped,tasks_blocked:tasksBlocked,blocked_tasks:blockedTasks}]};fs105.writeFileSync(evidencePath,JSON.stringify(evidenceBundle,null,2),"utf-8")}catch{}return JSON.stringify(result,null,2)}var completion_verify=createSwarmTool({description:"Deterministic pre-check verifying that plan task identifiers exist in their target source files before phase completion. Blocks if obviously incomplete.",args:{phase:exports_external.number().describe("The phase number to check"),sessionID:exports_external.string().optional().describe("Session ID for tracking state (auto-provided by plugin context)"),working_directory:exports_external.string().optional().describe("Explicit project root directory. When provided, .swarm/ is resolved relative to this path instead of the plugin context directory. Use this when CWD differs from the actual project root.")},execute:async(args2,directory)=>{let parsedArgs;try{if(args2&&typeof args2==="object"){let obj=args2;parsedArgs={phase:typeof obj.phase==="number"?obj.phase:typeof obj.phase==="string"?Number(obj.phase):0,sessionID:typeof obj.sessionID==="string"?obj.sessionID:void 0,working_directory:typeof obj.working_directory==="string"?obj.working_directory:void 0}}else parsedArgs={phase:0}}catch{return JSON.stringify({success:!1,phase:0,status:"blocked",reason:"Invalid arguments",tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]},null,2)}let dirResult=resolveWorkingDirectory(parsedArgs.working_directory,directory);if(!dirResult.success)return JSON.stringify({success:!1,phase:parsedArgs.phase,status:"blocked",reason:dirResult.message,tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]},null,2);return executeCompletionVerify(parsedArgs,dirResult.directory)}});init_zod();import*as fs107 from"node:fs";import*as path179 from"node:path";import*as fs106 from"node:fs";import*as path178 from"node:path";var MAX_FILE_SIZE_BYTES3=262144,MIN_DUPLICATION_LINES=10;function estimateCyclomaticComplexity(content){let processed=content.replace(/\/\*[\s\S]*?\*\//g,"");processed=processed.replace(/\/\/.*/g,""),processed=processed.replace(/#.*/g,""),processed=processed.replace(/'[^']*'/g,""),processed=processed.replace(/"[^"]*"/g,""),processed=processed.replace(/`[^`]*`/g,"");let complexity=1,decisionPatterns=[/\bif\b/g,/\belse\s+if\b/g,/\bfor\b/g,/\bwhile\b/g,/\bswitch\b/g,/\bcase\b/g,/\bcatch\b/g,/\?\./g,/\?\?/g,/&&/g,/\|\|/g];for(let pattern of decisionPatterns){let matches=processed.match(pattern);if(matches)complexity+=matches.length}let ternaryMatches=processed.match(/\?[^:]/g);if(ternaryMatches)complexity+=ternaryMatches.length;return complexity}function getComplexityForFile(filePath){try{if(fs106.statSync(filePath).size>MAX_FILE_SIZE_BYTES3)return null;let content=fs106.readFileSync(filePath,"utf-8");return estimateCyclomaticComplexity(content)}catch{return null}}async function computeComplexityDelta(files,workingDir){let totalComplexity=0,analyzedFiles=[];for(let file3 of files){let fullPath=path178.isAbsolute(file3)?file3:path178.join(workingDir,file3);if(!fs106.existsSync(fullPath))continue;let complexity=getComplexityForFile(fullPath);if(complexity!==null)totalComplexity+=complexity,analyzedFiles.push(file3)}return{delta:totalComplexity,analyzedFiles}}function countExportsInFile(content){let count=0,exportFunctionMatches=content.match(/export\s+function\s+\w+/g);if(exportFunctionMatches)count+=exportFunctionMatches.length;let exportClassMatches=content.match(/export\s+class\s+\w+/g);if(exportClassMatches)count+=exportClassMatches.length;let exportConstMatches=content.match(/export\s+const\s+\w+/g);if(exportConstMatches)count+=exportConstMatches.length;let exportLetMatches=content.match(/export\s+let\s+\w+/g);if(exportLetMatches)count+=exportLetMatches.length;let exportVarMatches=content.match(/export\s+var\s+\w+/g);if(exportVarMatches)count+=exportVarMatches.length;let exportNamedMatches=content.match(/export\s*\{[^}]+\}/g);if(exportNamedMatches)for(let match of exportNamedMatches){let names=match.match(/\b[a-zA-Z_$][a-zA-Z0-9_$]*\b/g),filteredNames=names?names.filter((n)=>n!=="export"):[];count+=filteredNames.length}let exportDefaultMatches=content.match(/export\s+default/g);if(exportDefaultMatches)count+=exportDefaultMatches.length;let exportTypeMatches=content.match(/export\s+(type|interface)\s+\w+/g);if(exportTypeMatches)count+=exportTypeMatches.length;let exportEnumMatches=content.match(/export\s+enum\s+\w+/g);if(exportEnumMatches)count+=exportEnumMatches.length;let exportEqualsMatches=content.match(/export\s+=/g);if(exportEqualsMatches)count+=exportEqualsMatches.length;return count}function countPythonExports(content){let count=0,noStrings=content.replace(/#.*/g,"").replace(/"[^"]*"/g,"").replace(/'[^']*'/g,""),functionMatches=noStrings.match(/^\s*def\s+\w+/gm);if(functionMatches)count+=functionMatches.length;let classMatches=noStrings.match(/^\s*class\s+\w+/gm);if(classMatches)count+=classMatches.length;let allMatchOriginal=content.match(/__all__\s*=\s*\[([^\]]+)\]/);if(allMatchOriginal?.[1]){let names=allMatchOriginal[1].match(/['"]?(\w+)['"]?/g);if(names){let cleanNames=names.map((n)=>n.replace(/['"]/g,""));count+=cleanNames.length}}return count}function countRustExports(content){let count=0,processed=content.replace(/\/\/.*/g,"");processed=processed.replace(/\/\*[\s\S]*?\*\//g,"");let pubFnMatches=processed.match(/pub\s+fn\s+\w+/g);if(pubFnMatches)count+=pubFnMatches.length;let pubStructMatches=processed.match(/pub\s+struct\s+\w+/g);if(pubStructMatches)count+=pubStructMatches.length;let pubEnumMatches=processed.match(/pub\s+enum\s+\w+/g);if(pubEnumMatches)count+=pubEnumMatches.length;let pubUseMatches=processed.match(/pub\s+use\s+/g);if(pubUseMatches)count+=pubUseMatches.length;let pubConstMatches=processed.match(/pub\s+const\s+\w+/g);if(pubConstMatches)count+=pubConstMatches.length;let pubModMatches=processed.match(/pub\s+mod\s+\w+/g);if(pubModMatches)count+=pubModMatches.length;let pubTypeMatches=processed.match(/pub\s+type\s+\w+/g);if(pubTypeMatches)count+=pubTypeMatches.length;return count}function countGoExports(content){let count=0,processed=content.replace(/\/\/.*/gm,"");processed=processed.replace(/\/\*[\s\S]*?\*\//g,"");let exportedFuncMatches=processed.match(/^\s*func\s+[A-Z]\w*/gm);if(exportedFuncMatches)count+=exportedFuncMatches.length;let exportedVarMatches=processed.match(/^\s*var\s+[A-Z]\w*/gm);if(exportedVarMatches)count+=exportedVarMatches.length;let exportedTypeMatches=processed.match(/^\s*type\s+[A-Z]\w*/gm);if(exportedTypeMatches)count+=exportedTypeMatches.length;let exportedConstMatches=processed.match(/^\s*const\s+[A-Z]\w*/gm);if(exportedConstMatches)count+=exportedConstMatches.length;if(processed.match(/^\s*package\s+\w+/m))count+=1;return count}function getExportCountForFile(filePath){try{let content=fs106.readFileSync(filePath,"utf-8");switch(path178.extname(filePath).toLowerCase()){case".ts":case".tsx":case".js":case".jsx":case".mjs":case".cjs":return countExportsInFile(content);case".py":return countPythonExports(content);case".rs":return countRustExports(content);case".go":return countGoExports(content);default:return countExportsInFile(content)}}catch{return 0}}async function computePublicApiDelta(files,workingDir){let totalExports=0,analyzedFiles=[];for(let file3 of files){let fullPath=path178.isAbsolute(file3)?file3:path178.join(workingDir,file3);if(!fs106.existsSync(fullPath))continue;let exports=getExportCountForFile(fullPath);totalExports+=exports,analyzedFiles.push(file3)}return{delta:totalExports,analyzedFiles}}function findDuplicateLines(content,minLines){let lines=content.split(`
|
|
5852
5852
|
`).filter((line)=>line.trim().length>0);if(lines.length<minLines)return 0;let normalizedLines=lines.map((line)=>line.trim()),windowCounts=new Map;for(let i=0;i<=normalizedLines.length-minLines;i++){let window2=normalizedLines.slice(i,i+minLines).join(`
|
|
5853
5853
|
`);windowCounts.set(window2,(windowCounts.get(window2)||0)+1)}let duplicateCount=0;for(let[_window,count]of windowCounts)if(count>1)duplicateCount+=(count-1)*minLines;return Math.min(duplicateCount,lines.length)}async function computeDuplicationRatio(files,workingDir){let totalLines=0,duplicateLines=0,analyzedFiles=[];for(let file3 of files){let fullPath=path178.isAbsolute(file3)?file3:path178.join(workingDir,file3);if(!fs106.existsSync(fullPath))continue;try{if(fs106.statSync(fullPath).size>MAX_FILE_SIZE_BYTES3)continue;let content=fs106.readFileSync(fullPath,"utf-8"),lines=content.split(`
|
|
5854
5854
|
`).filter((line)=>line.trim().length>0);if(lines.length<MIN_DUPLICATION_LINES){analyzedFiles.push(file3);continue}totalLines+=lines.length,duplicateLines+=findDuplicateLines(content,MIN_DUPLICATION_LINES),analyzedFiles.push(file3)}catch{}}return{ratio:totalLines>0?duplicateLines/totalLines:0,analyzedFiles}}function countCodeLines(content){let processed=content.replace(/\/\*[\s\S]*?\*\//g,"");return processed=processed.replace(/\/\/.*/g,""),processed=processed.replace(/#.*/g,""),processed.split(`
|
|
5855
5855
|
`).filter((line)=>line.trim().length>0).length}function isTestFile(filePath){let basename25=path178.basename(filePath),_ext=path178.extname(filePath).toLowerCase(),testPatterns=[".test.",".spec.",".tests.",".test.ts",".test.js",".spec.ts",".spec.js",".test.tsx",".test.jsx",".spec.tsx",".spec.jsx"];for(let pattern of testPatterns)if(basename25.includes(pattern))return!0;let normalizedPath=filePath.replace(/\\/g,"/");if(normalizedPath.includes("/tests/")||normalizedPath.includes("/test/"))return!0;if(normalizedPath.includes("/__tests__/"))return!0;return!1}function matchSegment(globSeg,pathSeg){if(globSeg==="**")return!1;if(globSeg===pathSeg)return!0;if(globSeg.includes("*")){let pattern=globSeg;return pattern=pattern.replace(/[[\](){}|+?^$.\\]/g,"\\$&"),pattern=pattern.replace(/\*/g,".*"),new RegExp(`^${pattern}$`).test(pathSeg)}return!1}function matchGlobSegment(globSegments,pathSegments){if(pathSegments.some((s)=>s===""))return!1;let gIndex=0,pIndex=0;while(gIndex<globSegments.length&&pIndex<pathSegments.length){let globSeg=globSegments[gIndex];if(globSeg==="**"){if(matchGlobSegment(globSegments.slice(gIndex+1),pathSegments.slice(pIndex)))return!0;for(let i=pIndex;i<pathSegments.length;i++)if(matchGlobSegment(globSegments.slice(gIndex+1),pathSegments.slice(i+1)))return!0;return!1}else if(globSeg==="*"){if(pathSegments[pIndex]==="")return!1;gIndex++,pIndex++}else{if(!matchSegment(globSeg,pathSegments[pIndex]))return!1;gIndex++,pIndex++}}while(gIndex<globSegments.length&&globSegments[gIndex]==="**")gIndex++;return gIndex===globSegments.length&&pIndex===pathSegments.length}function matchesGlobSegment(path179,glob){let normalizedPath=path179.replace(/\\/g,"/"),normalizedGlob=glob.replace(/\\/g,"/");if(normalizedPath.includes("//"))return!1;if(normalizedGlob.includes("//"))return!1;let pathSegments=normalizedPath.split("/").filter((s)=>s!==""),globSegments=normalizedGlob.split("/").filter((s)=>s!=="");if(globSegments.length===0)return!0;if(globSegments.length===1&&globSegments[0]==="**")return!0;return matchGlobSegment(globSegments,pathSegments)}function simpleGlobToRegex2(glob){if(!glob)return/.*/;let pattern=glob,regexMetacharacters=/[[\](){}|+?^$.\\]/g;return pattern=pattern.replace(regexMetacharacters,"\\$&"),pattern=pattern.replace(/\*/g,"[^/]+"),new RegExp(`^${pattern}$`)}function hasGlobstar(glob){return glob.includes("**")}function globMatches(path179,glob){let normalizedPath=path179.replace(/\\/g,"/");if(!glob||glob===""){if(normalizedPath.includes("//"))return!1;return!0}let normalizedGlob=glob.endsWith("\\")?glob.slice(0,-1):glob;if(normalizedPath.includes("//")||normalizedGlob.includes("//"))return!1;if(hasGlobstar(normalizedGlob))return matchesGlobSegment(normalizedPath,normalizedGlob);return simpleGlobToRegex2(normalizedGlob).test(normalizedPath)}function shouldExcludeFile(filePath,excludeGlobs){let normalizedPath=filePath.replace(/\\/g,"/");if(normalizedPath.includes("//"))return!1;for(let glob of excludeGlobs){if(glob.replace(/\\/g,"/").includes("//"))continue;if(globMatches(normalizedPath,glob))return!0}return!1}async function computeTestToCodeRatio(workingDir,enforceGlobs,excludeGlobs){let testLines=0,codeLines=0,srcDir=path178.join(workingDir,"src");if(fs106.existsSync(srcDir))await scanDirectoryForLines(srcDir,enforceGlobs,excludeGlobs,!1,(lines)=>{codeLines+=lines});let possibleSrcDirs=["lib","app","source","core"];for(let dir of possibleSrcDirs){let dirPath=path178.join(workingDir,dir);if(fs106.existsSync(dirPath))await scanDirectoryForLines(dirPath,enforceGlobs,excludeGlobs,!1,(lines)=>{codeLines+=lines})}let testsDir=path178.join(workingDir,"tests");if(fs106.existsSync(testsDir))await scanDirectoryForLines(testsDir,["**"],["node_modules","dist"],!0,(lines)=>{testLines+=lines});let possibleTestDirs=["test","__tests__","specs"];for(let dir of possibleTestDirs){let dirPath=path178.join(workingDir,dir);if(fs106.existsSync(dirPath)&&dirPath!==testsDir)await scanDirectoryForLines(dirPath,["**"],["node_modules","dist"],!0,(lines)=>{testLines+=lines})}let totalLines=testLines+codeLines;return{ratio:totalLines>0?testLines/totalLines:0,testLines,codeLines}}async function scanDirectoryForLines(dirPath,includeGlobs,excludeGlobs,isTestScan,callback){try{let entries=fs106.readdirSync(dirPath,{withFileTypes:!0});for(let entry of entries){let fullPath=path178.join(dirPath,entry.name);if(entry.isDirectory()){if(entry.name==="node_modules"||entry.name==="dist"||entry.name==="build"||entry.name===".git")continue;await scanDirectoryForLines(fullPath,includeGlobs,excludeGlobs,isTestScan,callback)}else if(entry.isFile()){let relativePath=fullPath.replace(`${dirPath}/`,""),ext=path178.extname(entry.name).toLowerCase();if(![".ts",".tsx",".js",".jsx",".py",".rs",".go",".java",".cs"].includes(ext))continue;if(isTestScan&&!isTestFile(fullPath))continue;if(!isTestScan&&isTestFile(fullPath))continue;if(shouldExcludeFile(relativePath,excludeGlobs))continue;if(!isTestScan&&includeGlobs.length>0&&!includeGlobs.includes("**")){let matches=!1;for(let glob of includeGlobs)if(globMatches(relativePath,glob)){matches=!0;break}if(!matches)continue}try{let content=fs106.readFileSync(fullPath,"utf-8"),lines=countCodeLines(content);callback(lines)}catch{}}}}catch{}}function detectViolations(metrics,thresholds){let violations=[];if(metrics.complexity_delta>thresholds.max_complexity_delta)violations.push({type:"complexity",message:`Complexity delta (${metrics.complexity_delta}) exceeds threshold (${thresholds.max_complexity_delta})`,severity:metrics.complexity_delta>thresholds.max_complexity_delta*1.5?"error":"warning",files:metrics.files_analyzed});if(metrics.public_api_delta>thresholds.max_public_api_delta)violations.push({type:"api",message:`Public API delta (${metrics.public_api_delta}) exceeds threshold (${thresholds.max_public_api_delta})`,severity:metrics.public_api_delta>thresholds.max_public_api_delta*1.5?"error":"warning",files:metrics.files_analyzed});if(metrics.duplication_ratio>thresholds.max_duplication_ratio)violations.push({type:"duplication",message:`Duplication ratio (${(metrics.duplication_ratio*100).toFixed(1)}%) exceeds threshold (${(thresholds.max_duplication_ratio*100).toFixed(1)}%)`,severity:metrics.duplication_ratio>thresholds.max_duplication_ratio*1.5?"error":"warning",files:metrics.files_analyzed});if(metrics.files_analyzed.length>0&&metrics.test_to_code_ratio<thresholds.min_test_to_code_ratio)violations.push({type:"test_ratio",message:`Test-to-code ratio (${(metrics.test_to_code_ratio*100).toFixed(1)}%) below threshold (${(thresholds.min_test_to_code_ratio*100).toFixed(1)}%)`,severity:metrics.test_to_code_ratio<thresholds.min_test_to_code_ratio*0.5?"error":"warning",files:metrics.files_analyzed});return violations}async function computeQualityMetrics(changedFiles,thresholds,workingDir){let config3={enabled:thresholds.enabled??!0,max_complexity_delta:thresholds.max_complexity_delta??5,max_public_api_delta:thresholds.max_public_api_delta??10,max_duplication_ratio:thresholds.max_duplication_ratio??0.05,min_test_to_code_ratio:thresholds.min_test_to_code_ratio??0.3,enforce_on_globs:thresholds.enforce_on_globs??["src/**"],exclude_globs:thresholds.exclude_globs??["docs/**","tests/**","**/*.test.*"]},filteredFiles=changedFiles.filter((file3)=>{let normalizedPath=file3.replace(/\\/g,"/");for(let glob of config3.enforce_on_globs)if(globMatches(normalizedPath,glob)){for(let exclude of config3.exclude_globs)if(globMatches(normalizedPath,exclude))return!1;return!0}return!1}),[complexityResult,apiResult,duplicationResult,testRatioResult]=await Promise.all([computeComplexityDelta(filteredFiles,workingDir),computePublicApiDelta(filteredFiles,workingDir),computeDuplicationRatio(filteredFiles,workingDir),computeTestToCodeRatio(workingDir,config3.enforce_on_globs,config3.exclude_globs)]),allAnalyzedFiles=[...new Set([...complexityResult.analyzedFiles,...apiResult.analyzedFiles,...duplicationResult.analyzedFiles])],violations=detectViolations({complexity_delta:complexityResult.delta,public_api_delta:apiResult.delta,duplication_ratio:duplicationResult.ratio,test_to_code_ratio:testRatioResult.ratio,files_analyzed:allAnalyzedFiles,thresholds:config3,violations:[]},config3);return{complexity_delta:complexityResult.delta,public_api_delta:apiResult.delta,duplication_ratio:duplicationResult.ratio,test_to_code_ratio:testRatioResult.ratio,files_analyzed:allAnalyzedFiles,thresholds:config3,violations}}init_bun_compat();init_create_tool();init_path_security();var MAX_FILE_SIZE_BYTES4=262144,DEFAULT_DAYS=90,DEFAULT_TOP_N=20,DEFAULT_EXTENSIONS="ts,tsx,js,jsx,py,rs,ps1",SHELL_METACHAR_REGEX=/[;&|%$`\\]/;function validateDays(days){if(typeof days>"u")return{valid:!0,value:DEFAULT_DAYS,error:null};if(typeof days!=="number"||!Number.isInteger(days))return{valid:!1,value:0,error:"days must be an integer"};if(days<1||days>365)return{valid:!1,value:0,error:"days must be between 1 and 365"};return{valid:!0,value:days,error:null}}function validateTopN(topN){if(typeof topN>"u")return{valid:!0,value:DEFAULT_TOP_N,error:null};if(typeof topN!=="number"||!Number.isInteger(topN))return{valid:!1,value:0,error:"top_n must be an integer"};if(topN<1||topN>100)return{valid:!1,value:0,error:"top_n must be between 1 and 100"};return{valid:!0,value:topN,error:null}}function validateExtensions(extensions){if(typeof extensions>"u")return{valid:!0,value:DEFAULT_EXTENSIONS,error:null};if(typeof extensions!=="string")return{valid:!1,value:"",error:"extensions must be a string"};if(containsControlChars(extensions))return{valid:!1,value:"",error:"extensions contains control characters"};if(SHELL_METACHAR_REGEX.test(extensions))return{valid:!1,value:"",error:"extensions contains shell metacharacters (;|&%$`\\)"};if(!/^[a-zA-Z0-9,.]+$/.test(extensions))return{valid:!1,value:"",error:"extensions contains invalid characters (only alphanumeric, commas, dots allowed)"};return{valid:!0,value:extensions,error:null}}async function getGitChurn(days,directory){let churnMap=new Map,proc=bunSpawn(["git","log",`--since=${days} days ago`,"--name-only","--pretty=format:"],{stdout:"pipe",stderr:"pipe",cwd:directory}),[stdout]=await Promise.all([proc.stdout.text(),proc.exited]),lines=stdout.split(/\r?\n/);for(let line of lines){let normalizedPath=line.replace(/\\/g,"/");if(!normalizedPath||normalizedPath.trim()==="")continue;if(normalizedPath.includes("node_modules")||normalizedPath.includes("/.git/")||normalizedPath.includes("/dist/")||normalizedPath.includes("/build/")||normalizedPath.includes("__tests__"))continue;if(normalizedPath.includes(".test.")||normalizedPath.includes(".spec."))continue;churnMap.set(normalizedPath,(churnMap.get(normalizedPath)||0)+1)}return churnMap}function getComplexityForFile2(filePath){try{if(fs107.statSync(filePath).size>MAX_FILE_SIZE_BYTES4)return null;let content=fs107.readFileSync(filePath,"utf-8");return estimateCyclomaticComplexity(content)}catch{return null}}async function analyzeHotspots(days,topN,extensions,directory){let churnMap=await getGitChurn(days,directory),extSet=new Set(extensions.map((e)=>e.startsWith(".")?e:`.${e}`)),filteredChurn=new Map;for(let[file3,count]of churnMap){let ext=path179.extname(file3).toLowerCase();if(extSet.has(ext))filteredChurn.set(file3,count)}let hotspots=[],cwd=directory,analyzedFiles=0;for(let[file3,churnCount]of filteredChurn){let fullPath=file3;if(!fs107.existsSync(fullPath))fullPath=path179.join(cwd,file3);let complexity=getComplexityForFile2(fullPath);if(complexity!==null){analyzedFiles++;let riskScore=Math.round(churnCount*Math.log2(Math.max(complexity,1))*10)/10,recommendation;if(riskScore>=50)recommendation="full_gates";else if(riskScore>=30)recommendation="security_review";else if(riskScore>=15)recommendation="enhanced_review";else recommendation="standard";hotspots.push({file:file3,churnCount,complexity,riskScore,recommendation})}}hotspots.sort((a,b)=>b.riskScore-a.riskScore);let topHotspots=hotspots.slice(0,topN),summary={fullGates:topHotspots.filter((h)=>h.recommendation==="full_gates").length,securityReview:topHotspots.filter((h)=>h.recommendation==="security_review").length,enhancedReview:topHotspots.filter((h)=>h.recommendation==="enhanced_review").length,standard:topHotspots.filter((h)=>h.recommendation==="standard").length};return{analyzedFiles,period:`${days} days`,hotspots:topHotspots,summary}}var complexity_hotspots=createSwarmTool({description:"Identify high-risk code hotspots by combining git churn frequency with cyclomatic complexity estimates. Returns files with their churn count, complexity score, risk score, and recommended review level.",args:{days:exports_external.number().optional().describe("Number of days of git history to analyze (default: 90, valid range: 1-365)"),top_n:exports_external.number().optional().describe("Number of top hotspots to return (default: 20, valid range: 1-100)"),extensions:exports_external.string().optional().describe('Comma-separated extensions to include (default: "ts,tsx,js,jsx,py,rs,ps1")')},async execute(args2,directory){if(!directory||typeof directory!=="string"||directory.trim()==="")return JSON.stringify({error:"project directory is required but was not provided",analyzedFiles:0,period:"0 days",hotspots:[],summary:{fullGates:0,securityReview:0,enhancedReview:0,standard:0}},null,2);let daysInput,topNInput,extensionsInput;try{if(args2&&typeof args2==="object"){let obj=args2;daysInput=typeof obj.days==="number"?obj.days:void 0,topNInput=typeof obj.top_n==="number"?obj.top_n:void 0,extensionsInput=typeof obj.extensions==="string"?obj.extensions:void 0}}catch{}let daysValidation=validateDays(daysInput);if(!daysValidation.valid){let errorResult={error:`invalid days: ${daysValidation.error}`,analyzedFiles:0,period:"0 days",hotspots:[],summary:{fullGates:0,securityReview:0,enhancedReview:0,standard:0}};return JSON.stringify(errorResult,null,2)}let topNValidation=validateTopN(topNInput);if(!topNValidation.valid){let errorResult={error:`invalid top_n: ${topNValidation.error}`,analyzedFiles:0,period:"0 days",hotspots:[],summary:{fullGates:0,securityReview:0,enhancedReview:0,standard:0}};return JSON.stringify(errorResult,null,2)}let extensionsValidation=validateExtensions(extensionsInput);if(!extensionsValidation.valid){let errorResult={error:`invalid extensions: ${extensionsValidation.error}`,analyzedFiles:0,period:"0 days",hotspots:[],summary:{fullGates:0,securityReview:0,enhancedReview:0,standard:0}};return JSON.stringify(errorResult,null,2)}let days=daysValidation.value,topN=topNValidation.value,extensions=extensionsValidation.value.split(",").map((e)=>e.trim());try{let result=await analyzeHotspots(days,topN,extensions,directory);return JSON.stringify(result,null,2)}catch(e){let errorResult={error:e instanceof Error?`analysis failed: ${e.message}`:"analysis failed: unknown error",analyzedFiles:0,period:`${days} days`,hotspots:[],summary:{fullGates:0,securityReview:0,enhancedReview:0,standard:0}};return JSON.stringify(errorResult,null,2)}}});init_config();init_model_limits();init_utils2();init_state2();init_create_tool();var _internals108={loadPluginConfig,fetchSessionMessages:async(sessionID,directory,limit=100)=>{if(!swarmState.opencodeClient?.session)return null;try{return(await swarmState.opencodeClient.session.messages({path:{id:sessionID},query:{directory,limit}})).data??null}catch{return null}}};function computeContextHeadroom(messages,warnThreshold=0.7,criticalThreshold=0.9,modelLimitsConfig={}){let{modelID,providerID}=extractModelInfo(messages),modelLimit=resolveModelLimit(modelID,providerID,modelLimitsConfig),totalTokens=0;for(let message of messages){if(!message?.parts)continue;for(let part of message.parts)if(part?.type==="text"&&part.text)totalTokens+=estimateTokens(part.text)}let usagePercent=totalTokens/modelLimit,thresholdCrossed="none";if(usagePercent>criticalThreshold)thresholdCrossed="critical";else if(usagePercent>warnThreshold)thresholdCrossed="warn";return{tokensUsed:totalTokens,modelLimit,usagePercent,thresholdCrossed,modelId:modelID??null,provider:providerID??null}}var context_status=createSwarmTool({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.",args:{},async execute(_args,directory,ctx){let config3=_internals108.loadPluginConfig(directory),warnThreshold=config3.context_budget?.warn_threshold??0.7,criticalThreshold=config3.context_budget?.critical_threshold??0.9,modelLimitsConfig=config3.context_budget?.model_limits??{},messages=[];if(ctx?.sessionID){let sessionMessages=await _internals108.fetchSessionMessages(ctx.sessionID,directory);if(sessionMessages)messages=sessionMessages}let headroom=computeContextHeadroom(messages,warnThreshold,criticalThreshold,modelLimitsConfig);return JSON.stringify(headroom,null,2)}});init_zod();init_loader();function pushCouncilAdvisory(session,synthesis){let dedupKey=`council:${synthesis.taskId}:${synthesis.roundNumber}`;if(synthesis.overallVerdict==="APPROVE"&&synthesis.advisoryFindings.length===0)return;if(session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.some((m)=>m.includes(dedupKey)))return;let blocking=synthesis.overallVerdict==="REJECT",header=`[${dedupKey}] (priority=HIGH, blocking=${blocking})`,body=synthesis.unifiedFeedbackMd;session.pendingAdvisoryMessages.push(`${header}
|
|
5856
|
-
${body}`)}init_zod();init_task_file();import{appendFileSync as appendFileSync18,existsSync as existsSync101,mkdirSync as mkdirSync44,readFileSync as readFileSync68}from"node:fs";import{join as join145}from"node:path";var EVIDENCE_DIR2=".swarm/evidence",VALID_TASK_ID=/^\d+\.\d+(\.\d+)*$/,COUNCIL_GATE_NAME="council",COUNCIL_AGENT_ID="architect",EvidenceFileSchema=exports_external.record(exports_external.string(),exports_external.unknown()),_internals109={withTaskEvidenceLock},FORBIDDEN_KEYS=new Set(["__proto__","constructor","prototype"]);function safeAssignOwnProps(target,source){for(let key of Object.keys(source)){if(FORBIDDEN_KEYS.has(key))continue;let value=source[key];if(value!==null&&typeof value==="object"&&!Array.isArray(value)){let nested=Object.create(null);safeAssignOwnProps(nested,value),target[key]=nested}else if(Array.isArray(value))target[key]=value.map((item)=>{if(item!==null&&typeof item==="object"&&!Array.isArray(item)){let nested=Object.create(null);return safeAssignOwnProps(nested,item),nested}return item});else target[key]=value}return target}async function writeCouncilEvidence(workingDir,synthesis){if(!VALID_TASK_ID.test(synthesis.taskId))throw Error(`writeCouncilEvidence: invalid taskId "${synthesis.taskId}" — must match N.M or N.M.P format`);let dir=join145(workingDir,EVIDENCE_DIR2);mkdirSync44(dir,{recursive:!0});let filePath=taskEvidencePath(workingDir,synthesis.taskId);await _internals109.withTaskEvidenceLock(workingDir,synthesis.taskId,COUNCIL_AGENT_ID,async()=>{let existingRoot=Object.create(null);if(existsSync101(filePath))try{let parsed=EvidenceFileSchema.parse(JSON.parse(readFileSync68(filePath,"utf-8")));safeAssignOwnProps(existingRoot,parsed)}catch{}let existingGatesRaw=existingRoot.gates,mergedGates=Object.create(null);if(existingGatesRaw&&typeof existingGatesRaw==="object"&&!Array.isArray(existingGatesRaw))safeAssignOwnProps(mergedGates,existingGatesRaw);mergedGates[COUNCIL_GATE_NAME]={sessionId:synthesis.swarmId,timestamp:synthesis.timestamp,agent:COUNCIL_AGENT_ID,verdict:synthesis.overallVerdict,vetoedBy:synthesis.vetoedBy,roundNumber:synthesis.roundNumber,allCriteriaMet:synthesis.allCriteriaMet,quorumSize:synthesis.quorumSize};let updated=Object.create(null);if(safeAssignOwnProps(updated,existingRoot),updated.gates=mergedGates,!updated.taskId)updated.taskId=synthesis.taskId;if(!Array.isArray(updated.required_gates))updated.required_gates=[];await atomicWriteFile(filePath,JSON.stringify(updated,null,2))});try{let councilDir=join145(workingDir,".swarm","council");mkdirSync44(councilDir,{recursive:!0});let auditLine=JSON.stringify({round:synthesis.roundNumber,verdict:synthesis.overallVerdict,timestamp:synthesis.timestamp,vetoedBy:synthesis.vetoedBy});appendFileSync18(join145(councilDir,`${synthesis.taskId}.rounds.jsonl`),`${auditLine}
|
|
5857
|
-
`)}catch(auditError){
|
|
5856
|
+
${body}`)}init_zod();init_task_file();init_logger();import{appendFileSync as appendFileSync18,existsSync as existsSync101,mkdirSync as mkdirSync44,readFileSync as readFileSync68}from"node:fs";import{join as join145}from"node:path";var EVIDENCE_DIR2=".swarm/evidence",VALID_TASK_ID=/^\d+\.\d+(\.\d+)*$/,COUNCIL_GATE_NAME="council",COUNCIL_AGENT_ID="architect",EvidenceFileSchema=exports_external.record(exports_external.string(),exports_external.unknown()),_internals109={withTaskEvidenceLock},FORBIDDEN_KEYS=new Set(["__proto__","constructor","prototype"]);function safeAssignOwnProps(target,source){for(let key of Object.keys(source)){if(FORBIDDEN_KEYS.has(key))continue;let value=source[key];if(value!==null&&typeof value==="object"&&!Array.isArray(value)){let nested=Object.create(null);safeAssignOwnProps(nested,value),target[key]=nested}else if(Array.isArray(value))target[key]=value.map((item)=>{if(item!==null&&typeof item==="object"&&!Array.isArray(item)){let nested=Object.create(null);return safeAssignOwnProps(nested,item),nested}return item});else target[key]=value}return target}async function writeCouncilEvidence(workingDir,synthesis){if(!VALID_TASK_ID.test(synthesis.taskId))throw Error(`writeCouncilEvidence: invalid taskId "${synthesis.taskId}" — must match N.M or N.M.P format`);let dir=join145(workingDir,EVIDENCE_DIR2);mkdirSync44(dir,{recursive:!0});let filePath=taskEvidencePath(workingDir,synthesis.taskId);await _internals109.withTaskEvidenceLock(workingDir,synthesis.taskId,COUNCIL_AGENT_ID,async()=>{let existingRoot=Object.create(null);if(existsSync101(filePath))try{let parsed=EvidenceFileSchema.parse(JSON.parse(readFileSync68(filePath,"utf-8")));safeAssignOwnProps(existingRoot,parsed)}catch{}let existingGatesRaw=existingRoot.gates,mergedGates=Object.create(null);if(existingGatesRaw&&typeof existingGatesRaw==="object"&&!Array.isArray(existingGatesRaw))safeAssignOwnProps(mergedGates,existingGatesRaw);mergedGates[COUNCIL_GATE_NAME]={sessionId:synthesis.swarmId,timestamp:synthesis.timestamp,agent:COUNCIL_AGENT_ID,verdict:synthesis.overallVerdict,vetoedBy:synthesis.vetoedBy,roundNumber:synthesis.roundNumber,allCriteriaMet:synthesis.allCriteriaMet,quorumSize:synthesis.quorumSize};let updated=Object.create(null);if(safeAssignOwnProps(updated,existingRoot),updated.gates=mergedGates,!updated.taskId)updated.taskId=synthesis.taskId;if(!Array.isArray(updated.required_gates))updated.required_gates=[];await atomicWriteFile(filePath,JSON.stringify(updated,null,2))});try{let councilDir=join145(workingDir,".swarm","council");mkdirSync44(councilDir,{recursive:!0});let auditLine=JSON.stringify({round:synthesis.roundNumber,verdict:synthesis.overallVerdict,timestamp:synthesis.timestamp,vetoedBy:synthesis.vetoedBy});appendFileSync18(join145(councilDir,`${synthesis.taskId}.rounds.jsonl`),`${auditLine}
|
|
5857
|
+
`)}catch(auditError){log(`writeCouncilEvidence: failed to append round-history audit log: ${auditError instanceof Error?auditError.message:String(auditError)}`)}}var COUNCIL_DEFAULTS={enabled:!1,maxRounds:3,parallelTimeoutMs:30000,vetoPriority:!0,requireAllMembers:!1,minimumMembers:3,phaseConcernsAllowComplete:!0};function synthesizeCouncilVerdicts(taskId,swarmId,verdicts,criteria,roundNumber,config3={}){let cfg={...COUNCIL_DEFAULTS,...config3},timestamp=new Date().toISOString(),quorumSize=new Set(verdicts.map((v)=>v.agent)).size,rejectingMembers=verdicts.filter((v)=>v.verdict==="REJECT").map((v)=>v.agent),overallVerdict;if(cfg.vetoPriority&&rejectingMembers.length>0)overallVerdict="REJECT";else if(verdicts.some((v)=>v.verdict==="CONCERNS")||!cfg.vetoPriority&&rejectingMembers.length>0)overallVerdict="CONCERNS";else overallVerdict="APPROVE";let unresolvedConflicts=detectConflicts2(verdicts),rejectingSet=new Set(rejectingMembers),vetoFindings=verdicts.filter((v)=>rejectingSet.has(v.agent)).flatMap((v)=>v.findings),requiredFixes=vetoFindings.filter((f)=>f.severity==="CRITICAL"||f.severity==="HIGH"||f.severity==="MEDIUM"),advisoryFindings=[...vetoFindings.filter((f)=>f.severity==="LOW"),...verdicts.filter((v)=>!rejectingSet.has(v.agent)).flatMap((v)=>v.findings)],blockingConcernsCount=promoteBlockingConcerns(verdicts,rejectingSet,requiredFixes,advisoryFindings),allAssessedIds=new Set(verdicts.flatMap((v)=>v.criteriaAssessed)),allUnmetIds=new Set(verdicts.flatMap((v)=>v.criteriaUnmet)),allCriteriaMet=[...new Set((criteria?.criteria??[]).filter((c)=>c.mandatory).map((c)=>c.id))].every((id)=>allAssessedIds.has(id)&&!allUnmetIds.has(id)),unifiedFeedbackMd=buildUnifiedFeedback(taskId,overallVerdict,rejectingMembers,requiredFixes,advisoryFindings,unresolvedConflicts,roundNumber,cfg.maxRounds,blockingConcernsCount);return{taskId,swarmId,timestamp,overallVerdict,vetoedBy:rejectingMembers.length>0?rejectingMembers:null,memberVerdicts:verdicts,unresolvedConflicts,requiredFixes,advisoryFindings,unifiedFeedbackMd,roundNumber,allCriteriaMet,quorumSize,blockingConcernsCount,...verdicts.length===0&&{emptyVerdictsWarning:!0}}}function promoteBlockingConcerns(verdicts,rejectingSet,requiredFixes,advisoryFindings){let blocking=verdicts.filter((v)=>v.verdict==="CONCERNS"&&!rejectingSet.has(v.agent)).flatMap((v)=>v.findings).filter((f)=>f.severity==="CRITICAL"||f.severity==="HIGH");if(blocking.length===0)return 0;requiredFixes.push(...blocking);let blockingSet=new Set(blocking);for(let i=advisoryFindings.length-1;i>=0;i--)if(blockingSet.has(advisoryFindings[i]))advisoryFindings.splice(i,1);return blocking.length}function detectConflicts2(verdicts){let conflicts=[],locationMap=new Map;for(let verdict of verdicts)for(let finding of verdict.findings){let key=finding.location.toLowerCase();if(!key)continue;let entries=locationMap.get(key);if(entries)entries.push({agent:verdict.agent,detail:finding.detail});else locationMap.set(key,[{agent:verdict.agent,detail:finding.detail}])}for(let[location,entries]of locationMap){if(entries.length<2)continue;let addDirectives=entries.filter((e)=>/\badd\b|\binclude\b|\binsert\b/i.test(e.detail)),removeDirectives=entries.filter((e)=>/\bremove\b|\bdelete\b|\beliminate\b/i.test(e.detail));if(addDirectives.length>0&&removeDirectives.length>0)conflicts.push(`Conflict at ${location}: ${addDirectives.map((e)=>`${e.agent} says "${e.detail}"`).join(", ")} vs ${removeDirectives.map((e)=>`${e.agent} says "${e.detail}"`).join(", ")}`)}return conflicts}function buildUnifiedFeedback(taskId,verdict,vetoedBy,requiredFixes,advisoryFindings,conflicts,roundNumber,maxRounds,blockingConcernsCount=0){let lines=[`## Work Complete Council — Round ${roundNumber}/${maxRounds}`,`**Task:** ${taskId} **Overall verdict:** ${verdict}`,""];if(vetoedBy.length>0)lines.push(`> ⛔ **BLOCKED** by: ${vetoedBy.join(", ")}`),lines.push("");if(blockingConcernsCount>0)lines.push(`> ⚠️ **BLOCKING CONCERNS**: ${blockingConcernsCount} HIGH/CRITICAL finding(s) from CONCERNS members require investigation and resolution before advancement.`),lines.push("");if(requiredFixes.length>0){lines.push("### Required Fixes (must resolve before re-submission)");for(let f of requiredFixes)lines.push(`- **[${f.severity}]** \`${f.location}\` — ${f.detail}`,` _Evidence:_ ${f.evidence}`);lines.push("")}if(conflicts.length>0){lines.push("### Conflicts to Resolve"),lines.push("_The following reviewers gave contradictory instructions. Architect must resolve before sending to coder._");for(let c of conflicts)lines.push(`- ${c}`);lines.push("")}if(advisoryFindings.length>0){lines.push("### Advisory Findings (non-blocking)");for(let f of advisoryFindings)lines.push(`- **[${f.severity}]** \`${f.location}\` — ${f.detail}`);lines.push("")}if(verdict==="APPROVE")lines.push("> ✅ **All council members approved.** Work may advance to `complete`.");else if(roundNumber>=maxRounds)lines.push(`> ⚠️ **Max rounds (${maxRounds}) reached.** Escalate to user — do not auto-advance.`);return lines.join(`
|
|
5858
5858
|
`)}function synthesizePhaseCouncilAdvisory(phaseNumber,phaseSummary,verdicts,roundNumber,config3={},_workingDir){let cfg={...COUNCIL_DEFAULTS,...config3},timestamp=new Date().toISOString(),scope="phase",quorumSize=new Set(verdicts.map((v)=>v.agent)).size,rejectingMembers=verdicts.filter((v)=>v.verdict==="REJECT").map((v)=>v.agent),overallVerdict;if(cfg.vetoPriority&&rejectingMembers.length>0)overallVerdict="REJECT";else if(verdicts.some((v)=>v.verdict==="CONCERNS")||!cfg.vetoPriority&&rejectingMembers.length>0)overallVerdict="CONCERNS";else overallVerdict="APPROVE";let unresolvedConflicts=detectConflicts2(verdicts),rejectingSet=new Set(rejectingMembers),vetoFindings=verdicts.filter((v)=>rejectingSet.has(v.agent)).flatMap((v)=>v.findings),requiredFixes=vetoFindings.filter((f)=>f.severity==="CRITICAL"||f.severity==="HIGH"||f.severity==="MEDIUM"),advisoryFindings=[...vetoFindings.filter((f)=>f.severity==="LOW"),...verdicts.filter((v)=>!rejectingSet.has(v.agent)).flatMap((v)=>v.findings)],blockingConcernsCount=promoteBlockingConcerns(verdicts,rejectingSet,requiredFixes,advisoryFindings),advisoryNotes=[];if(advisoryFindings.length>0)advisoryNotes.push(`Phase ${phaseNumber} council found ${advisoryFindings.length} advisory finding(s). Review before proceeding to next phase.`);if(verdicts.length<3)advisoryNotes.push(`Phase council quorum is ${verdicts.length} members — consider convening additional members for broader review coverage.`);let allCriteriaMet=new Set(verdicts.flatMap((v)=>v.criteriaUnmet)).size===0&&verdicts.length>0,unifiedFeedbackMd=buildPhaseCouncilFeedback(phaseNumber,phaseSummary,overallVerdict,rejectingMembers,requiredFixes,advisoryFindings,unresolvedConflicts,roundNumber,cfg.maxRounds,blockingConcernsCount),evidencePath=`.swarm/evidence/${phaseNumber}/phase-council.json`;return{phaseNumber,scope:"phase",timestamp,overallVerdict,vetoedBy:rejectingMembers.length>0?rejectingMembers:null,memberVerdicts:verdicts,unresolvedConflicts,requiredFixes,advisoryFindings,advisoryNotes,unifiedFeedbackMd,roundNumber,allCriteriaMet,quorumSize,blockingConcernsCount,evidencePath,phaseSummary}}function buildPhaseCouncilFeedback(phaseNumber,phaseSummary,verdict,vetoedBy,requiredFixes,advisoryFindings,conflicts,roundNumber,maxRounds,blockingConcernsCount=0){let lines=[`## Phase Council Review — Round ${roundNumber}/${maxRounds}`,`**Phase:** ${phaseNumber} **Overall verdict:** ${verdict}`,""];if(phaseSummary)lines.push(`**Phase Summary:** ${phaseSummary}`),lines.push("");if(vetoedBy.length>0)lines.push(`> ⛔ **BLOCKED** by: ${vetoedBy.join(", ")}`),lines.push("");if(blockingConcernsCount>0)lines.push(`> ⚠️ **BLOCKING CONCERNS**: ${blockingConcernsCount} HIGH/CRITICAL finding(s) from CONCERNS members require investigation and resolution before phase completion.`),lines.push("");if(requiredFixes.length>0){lines.push("### Required Fixes (must resolve before re-submission)");for(let f of requiredFixes)lines.push(`- **[${f.severity}]** \`${f.location}\` — ${f.detail}`,` _Evidence:_ ${f.evidence}`);lines.push("")}if(conflicts.length>0){lines.push("### Conflicts to Resolve"),lines.push("_The following reviewers gave contradictory instructions. Architect must resolve before sending to coder._");for(let c of conflicts)lines.push(`- ${c}`);lines.push("")}if(advisoryFindings.length>0){lines.push("### Advisory Findings (non-blocking)");for(let f of advisoryFindings)lines.push(`- **[${f.severity}]** \`${f.location}\` — ${f.detail}`);lines.push("")}if(verdict==="APPROVE")lines.push("> ✅ **Phase council approved.** Phase may proceed to completion.");else if(roundNumber>=maxRounds)lines.push(`> ⚠️ **Max rounds (${maxRounds}) reached.** Escalate to user — do not auto-advance.`);return lines.join(`
|
|
5859
5859
|
`)}function synthesizeFinalCouncilAdvisory(projectSummary,verdicts,roundNumber,config3={}){let cfg={...COUNCIL_DEFAULTS,...config3},timestamp=new Date().toISOString(),quorumSize=new Set(verdicts.map((v)=>v.agent)).size,rejectingMembers=verdicts.filter((v)=>v.verdict==="REJECT").map((v)=>v.agent),overallVerdict;if(cfg.vetoPriority&&rejectingMembers.length>0)overallVerdict="REJECT";else if(verdicts.some((v)=>v.verdict==="CONCERNS")||!cfg.vetoPriority&&rejectingMembers.length>0)overallVerdict="CONCERNS";else overallVerdict="APPROVE";let unresolvedConflicts=detectConflicts2(verdicts),rejectingSet=new Set(rejectingMembers),vetoFindings=verdicts.filter((v)=>rejectingSet.has(v.agent)).flatMap((v)=>v.findings),requiredFixes=vetoFindings.filter((f)=>f.severity==="CRITICAL"||f.severity==="HIGH"||f.severity==="MEDIUM"),advisoryFindings=[...vetoFindings.filter((f)=>f.severity==="LOW"),...verdicts.filter((v)=>!rejectingSet.has(v.agent)).flatMap((v)=>v.findings)],blockingConcernsCount=promoteBlockingConcerns(verdicts,rejectingSet,requiredFixes,advisoryFindings),advisoryNotes=[];if(advisoryFindings.length>0)advisoryNotes.push(`Final council found ${advisoryFindings.length} advisory finding(s). Review before project close.`);if(quorumSize<3)advisoryNotes.push(`Final council quorum is ${quorumSize} members - dispatch additional project-scoped council members before closing the project.`);let allCriteriaMet=new Set(verdicts.flatMap((v)=>v.criteriaUnmet)).size===0&&verdicts.length>0,unifiedFeedbackMd=buildFinalCouncilFeedback(projectSummary,overallVerdict,rejectingMembers,requiredFixes,advisoryFindings,unresolvedConflicts,roundNumber,cfg.maxRounds,blockingConcernsCount);return{scope:"project",timestamp,overallVerdict,vetoedBy:rejectingMembers.length>0?rejectingMembers:null,memberVerdicts:verdicts,unresolvedConflicts,requiredFixes,advisoryFindings,advisoryNotes,unifiedFeedbackMd,roundNumber,allCriteriaMet,quorumSize,evidencePath:".swarm/evidence/final-council.json",blockingConcernsCount,projectSummary}}function buildFinalCouncilFeedback(projectSummary,verdict,vetoedBy,requiredFixes,advisoryFindings,conflicts,roundNumber,maxRounds,blockingConcernsCount=0){let lines=[`## Final Council Review - Round ${roundNumber}/${maxRounds}`,`**Scope:** completed project **Overall verdict:** ${verdict}`,""];if(projectSummary)lines.push(`**Project Summary:** ${projectSummary}`),lines.push("");if(blockingConcernsCount>0)lines.push(`> ⚠️ **BLOCKING CONCERNS**: ${blockingConcernsCount} HIGH/CRITICAL finding(s) from CONCERNS members require investigation and resolution before project close.`),lines.push("");if(vetoedBy.length>0)lines.push(`> BLOCKED: project close is blocked by ${vetoedBy.join(", ")}`),lines.push("");if(requiredFixes.length>0){lines.push("### Required Fixes (must resolve before project close)");for(let f of requiredFixes)lines.push(`- **[${f.severity}]** \`${f.location}\` - ${f.detail}`,` _Evidence:_ ${f.evidence}`);lines.push("")}if(conflicts.length>0){lines.push("### Conflicts to Resolve"),lines.push("_The following council members gave contradictory project-close instructions. Architect must resolve before closing the project._");for(let c of conflicts)lines.push(`- ${c}`);lines.push("")}if(advisoryFindings.length>0){lines.push("### Advisory Findings (non-blocking)");for(let f of advisoryFindings)lines.push(`- **[${f.severity}]** \`${f.location}\` - ${f.detail}`);lines.push("")}if(verdict==="APPROVE")lines.push("> Final council approved. Project may proceed to close.");else if(roundNumber>=maxRounds)lines.push(`> Max rounds (${maxRounds}) reached. Escalate to user - do not close the project automatically.`);return lines.join(`
|
|
5860
5860
|
`)}init_zod();init_task_file();import{existsSync as existsSync102,mkdirSync as mkdirSync45,readFileSync as readFileSync69}from"node:fs";import{join as join146}from"node:path";var COUNCIL_DIR=".swarm/council",CouncilCriteriaSchema=exports_external.object({taskId:exports_external.string(),criteria:exports_external.array(exports_external.object({id:exports_external.string(),description:exports_external.string(),mandatory:exports_external.boolean()})),declaredAt:exports_external.string()});async function writeCriteria(workingDir,taskId,criteria){let dir=join146(workingDir,COUNCIL_DIR);mkdirSync45(dir,{recursive:!0});let payload={taskId,criteria,declaredAt:new Date().toISOString()};await atomicWriteFile(join146(dir,`${safeId(taskId)}.json`),JSON.stringify(payload,null,2))}function readCriteria(workingDir,taskId){let filePath=join146(workingDir,COUNCIL_DIR,`${safeId(taskId)}.json`);if(!existsSync102(filePath))return null;try{return CouncilCriteriaSchema.parse(JSON.parse(readFileSync69(filePath,"utf-8")))}catch{return null}}function safeId(id){return id.replace(/[^a-zA-Z0-9_-]/g,"_")}init_state2();init_create_tool();init_resolve_working_directory();var FindingSchema=exports_external.object({severity:exports_external.enum(["CRITICAL","HIGH","MEDIUM","LOW"]),category:exports_external.string().min(1),location:exports_external.string(),detail:exports_external.string(),evidence:exports_external.string()}),VerdictSchema=exports_external.object({agent:exports_external.enum(["critic","reviewer","sme","test_engineer","explorer"]),verdict:exports_external.enum(["APPROVE","CONCERNS","REJECT"]),verdictRound:exports_external.number().int().min(1).max(10).optional(),confidence:exports_external.number().min(0).max(1),findings:exports_external.array(FindingSchema),criteriaAssessed:exports_external.array(exports_external.string()),criteriaUnmet:exports_external.array(exports_external.string()),durationMs:exports_external.number().nonnegative()}),ArgsSchema=exports_external.object({taskId:exports_external.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/,'Task ID must be in N.M or N.M.P format (e.g. "1.1")'),swarmId:exports_external.string().min(1),roundNumber:exports_external.number().int().min(1).max(10).default(1),verdicts:exports_external.array(VerdictSchema).min(1).max(5),working_directory:exports_external.string().optional()}),submit_council_verdicts=createSwarmTool({description:"Submit pre-collected council member verdicts for synthesis. PREREQUISITE — "+"you MUST dispatch each council member (critic, reviewer, sme, test_engineer, explorer) as separate Agent tasks and collect their verdict responses BEFORE "+"calling this tool. This tool performs synthesis only — it does NOT dispatch, "+"invoke, or contact council members. Calling this tool without first collecting real verdicts from dispatched agents constitutes a council bypass. Returns the synthesized verdict, required fixes, and a quorum report showing which members voted and which were absent. Architect-only. Config-gated via council.enabled.",args:{taskId:exports_external.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/,"Task ID must be in N.M or N.M.P format").describe('Task ID being evaluated, e.g. "1.1", "1.2.3"'),swarmId:exports_external.string().min(1).describe('Swarm identifier, e.g. "mega"'),roundNumber:exports_external.number().int().min(1).max(10).optional().describe("1-indexed round number. Defaults to 1."),verdicts:exports_external.array(exports_external.object({agent:exports_external.enum(["critic","reviewer","sme","test_engineer","explorer"]),verdict:exports_external.enum(["APPROVE","CONCERNS","REJECT"]),verdictRound:exports_external.number().int().min(1).max(10).optional(),confidence:exports_external.number().min(0).max(1),findings:exports_external.array(exports_external.object({severity:exports_external.enum(["CRITICAL","HIGH","MEDIUM","LOW"]),category:exports_external.string().min(1),location:exports_external.string(),detail:exports_external.string(),evidence:exports_external.string()})),criteriaAssessed:exports_external.array(exports_external.string()),criteriaUnmet:exports_external.array(exports_external.string()),durationMs:exports_external.number()})).min(1).max(5).describe("Array of CouncilMemberVerdict objects. Must include between 1 and 5 entries, one per participating member (critic, reviewer, sme, test_engineer, explorer)."),working_directory:exports_external.string().optional().describe("Explicit project root directory. When provided, .swarm/council/ and .swarm/evidence/ are resolved relative to this path instead of the plugin context directory.")},async execute(args2,directory,ctx){let parsed=ArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,reason:"invalid arguments",errors:parsed.error.issues.map((i)=>({path:i.path.join("."),message:i.message}))},null,2);let input=parsed.data,dirResult=resolveWorkingDirectory(input.working_directory,directory);if(!dirResult.success)return JSON.stringify({success:!1,reason:dirResult.message},null,2);let workingDir=dirResult.directory,config3=loadPluginConfig(workingDir);if(!config3.council?.enabled)return JSON.stringify({success:!1,reason:"council feature is disabled — set council.enabled: true in .opencode/opencode-swarm.json to enable"},null,2);let effectiveMinimum=config3.council?.requireAllMembers?5:config3.council?.minimumMembers??3,ALL_MEMBERS=["critic","reviewer","sme","test_engineer","explorer"],distinctMembers=new Set(input.verdicts.map((v)=>v.agent)),membersVoted=[...distinctMembers],membersAbsent=ALL_MEMBERS.filter((m)=>!distinctMembers.has(m)),sessionID=ctx?.sessionID,session=sessionID?getAgentSession(sessionID):void 0,requirementKey=`${input.taskId}:${input.roundNumber}`;if(session&&!session.pendingCouncilRequirements)session.pendingCouncilRequirements=new Map;let pendingRequirements=session?.pendingCouncilRequirements?.get(requirementKey);if(pendingRequirements&&pendingRequirements.size>0){let stillMissingMembers=[...pendingRequirements].filter((member)=>!distinctMembers.has(member));if(stillMissingMembers.length>0)return JSON.stringify({success:!1,reason:"cherry_pick_detected",message:`Incomplete re-dispatch: ${stillMissingMembers.join(", ")} were required from the previous insufficient_quorum response but are still absent. Dispatch ALL absent members in one parallel batch.`,stillMissingMembers,membersProvided:membersVoted},null,2)}if(membersVoted.length<effectiveMinimum){if(session?.pendingCouncilRequirements)session.pendingCouncilRequirements.set(requirementKey,new Set(membersAbsent));return JSON.stringify({success:!1,reason:"insufficient_quorum",message:`Council quorum not met: ${membersVoted.length} of ${effectiveMinimum} required members provided verdicts. Members voted: [${membersVoted.join(", ")}]. Members absent: [${membersAbsent.join(", ")}]. Dispatch the absent council members as Agent tasks and collect their verdicts before calling submit_council_verdicts.`,membersVoted,membersAbsent,quorumRequired:effectiveMinimum},null,2)}let staleVerdicts=input.roundNumber>1?input.verdicts.filter((v)=>(v.verdictRound??1)<input.roundNumber):[];if(staleVerdicts.length>0)return JSON.stringify({success:!1,reason:"stale_verdict_detected",message:`Round ${input.roundNumber} requires fresh verdicts. One or more submitted verdicts are from an older round.`,staleVerdicts:staleVerdicts.map((v)=>({agent:v.agent,verdictRound:v.verdictRound}))},null,2);let criteria=readCriteria(workingDir,input.taskId),verdicts=input.verdicts,synthesis=synthesizeCouncilVerdicts(input.taskId,input.swarmId,verdicts,criteria,input.roundNumber,config3.council),dissenters=synthesis.memberVerdicts.filter((v)=>v.verdict==="CONCERNS"||v.verdict==="REJECT").map((v)=>v.agent);if(session?.pendingCouncilRequirements){if(session.pendingCouncilRequirements.delete(requirementKey),dissenters.length>0){let nextRoundKey=`${input.taskId}:${input.roundNumber+1}`;session.pendingCouncilRequirements.set(nextRoundKey,new Set(dissenters))}}if(synthesis.overallVerdict==="CONCERNS"&&synthesis.blockingConcernsCount>0)return JSON.stringify({success:!1,reason:"blocking_concerns_unresolved",overallVerdict:synthesis.overallVerdict,blockingConcernsCount:synthesis.blockingConcernsCount,requiredFixes:synthesis.requiredFixes,unifiedFeedbackMd:synthesis.unifiedFeedbackMd,message:`Council returned CONCERNS with ${synthesis.blockingConcernsCount} HIGH/CRITICAL finding(s) promoted to requiredFixes. These must be resolved before the task can advance. Do NOT write evidence or proceed — address every requiredFix and resubmit.`},null,2);await writeCouncilEvidence(workingDir,synthesis);try{if(sessionID){if(session)pushCouncilAdvisory(session,synthesis)}}catch{}return JSON.stringify({success:!0,overallVerdict:synthesis.overallVerdict,vetoedBy:synthesis.vetoedBy,roundNumber:synthesis.roundNumber,allCriteriaMet:synthesis.allCriteriaMet,requiredFixesCount:synthesis.requiredFixes.length,advisoryFindingsCount:synthesis.advisoryFindings.length,unresolvedConflictsCount:synthesis.unresolvedConflicts.length,membersVoted,membersAbsent,quorumSize:membersVoted.length,quorumMet:!0,unifiedFeedbackMd:synthesis.unifiedFeedbackMd},null,2)}});init_zod();init_loader();import*as fs108 from"node:fs";import*as path180 from"node:path";function pushGeneralCouncilAdvisory(session,result){if(!session)return;let body=renderAdvisoryBody(result);if(!body)return;session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(`[general_council] (advisory; not blocking)
|
|
@@ -5866,14 +5866,14 @@ ${body}`)}function renderAdvisoryBody(result){return result.synthesis.trim()}var
|
|
|
5866
5866
|
`):"_No persisting disagreements after deliberation._",sourcesBlock=allSources.length>0?allSources.map((s)=>`- [${s.title||s.url}](${s.url})`).join(`
|
|
5867
5867
|
`):"_No sources cited._";return["## General Council Synthesis","",`**Question:** ${question}`,`**Mode:** ${mode}`,`**Members:**
|
|
5868
5868
|
${memberLines}`,`**Rounds:** ${roundsCompleted}`,"","### Consensus",consensusBlock,"","### Persistent Disagreements",disagreementsBlock,"","### Sources",sourcesBlock].join(`
|
|
5869
|
-
`)}function synthesizeGeneralCouncil(question,mode,round1Responses,round2Responses){let safeRound1=Array.isArray(round1Responses)?round1Responses:[],safeRound2=Array.isArray(round2Responses)?round2Responses:[],disagreements=detectDisagreements(safeRound1),consensusPoints=buildConsensusClusters(safeRound1),persistingDisagreements=computePersistingDisagreements(disagreements,safeRound2),allSources=dedupeSources(safeRound1,safeRound2),roundsCompleted=safeRound2.length>0?2:1,synthesis=renderSynthesisMarkdown(question,mode,roundsCompleted,safeRound1,consensusPoints,persistingDisagreements,allSources);return{question,mode,round1Responses:safeRound1,disagreements,round2Responses:safeRound2,synthesis,consensusPoints,persistingDisagreements:persistingDisagreements.map((d)=>d.topic),allSources,timestamp:new Date().toISOString()}}init_state2();init_create_tool();init_resolve_working_directory();var WebSearchResultSchema=exports_external.object({title:exports_external.string(),url:exports_external.string(),snippet:exports_external.string(),query:exports_external.string()}),MemberRoleEnum=exports_external.enum(["generalist","skeptic","domain_expert","devil_advocate","synthesizer"]),Round1ResponseSchema=exports_external.object({memberId:exports_external.string().min(1),model:exports_external.string().min(1),role:MemberRoleEnum,response:exports_external.string(),sources:exports_external.array(WebSearchResultSchema).default([]),searchQueries:exports_external.array(exports_external.string()).default([]),confidence:exports_external.number().min(0).max(1),areasOfUncertainty:exports_external.array(exports_external.string()).default([]),durationMs:exports_external.number().nonnegative().default(0)}),Round2ResponseSchema=Round1ResponseSchema.extend({disagreementTopics:exports_external.array(exports_external.string()).default([])}),ArgsSchema2=exports_external.object({question:exports_external.string().min(1).max(8000),mode:exports_external.enum(["general","spec_review"]).default("general"),members:exports_external.array(exports_external.string()).default([]),round1Responses:exports_external.array(Round1ResponseSchema).min(1),round2Responses:exports_external.array(Round2ResponseSchema).optional(),working_directory:exports_external.string().optional()}),convene_general_council=createSwarmTool({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.",args:{question:exports_external.string().min(1).max(8000).describe("The question put to the council, or the spec text to review."),mode:exports_external.enum(["general","spec_review"]).optional().describe('"general" for /swarm council or pre-save PLAN advisory; "spec_review" for manual /swarm council --spec-review.'),members:exports_external.array(exports_external.string()).optional().describe("Optional list of member IDs convened (for evidence/audit)."),round1Responses:exports_external.array(exports_external.object({memberId:exports_external.string().min(1),model:exports_external.string().min(1),role:exports_external.enum(["generalist","skeptic","domain_expert","devil_advocate","synthesizer"]),response:exports_external.string(),sources:exports_external.array(exports_external.object({title:exports_external.string(),url:exports_external.string(),snippet:exports_external.string(),query:exports_external.string()})).optional(),searchQueries:exports_external.array(exports_external.string()).optional(),confidence:exports_external.number().min(0).max(1),areasOfUncertainty:exports_external.array(exports_external.string()).optional(),durationMs:exports_external.number().nonnegative().optional()})).describe("Round 1 member responses (one per council member)."),round2Responses:exports_external.array(exports_external.object({memberId:exports_external.string().min(1),model:exports_external.string().min(1),role:exports_external.enum(["generalist","skeptic","domain_expert","devil_advocate","synthesizer"]),response:exports_external.string(),sources:exports_external.array(exports_external.object({title:exports_external.string(),url:exports_external.string(),snippet:exports_external.string(),query:exports_external.string()})).optional(),searchQueries:exports_external.array(exports_external.string()).optional(),confidence:exports_external.number().min(0).max(1),areasOfUncertainty:exports_external.array(exports_external.string()).optional(),durationMs:exports_external.number().nonnegative().optional(),disagreementTopics:exports_external.array(exports_external.string()).optional()})).optional().describe("Round 2 deliberation responses (omit when no deliberation has occurred)."),working_directory:exports_external.string().optional().describe("Project root for config + evidence path resolution.")},execute:async(args2,directory,ctx)=>{let parsed=ArgsSchema2.safeParse(args2);if(!parsed.success){let fail={success:!1,reason:"invalid_args",message:parsed.error.issues.map((i)=>`${i.path.join(".")}: ${i.message}`).join("; ")};return JSON.stringify(fail,null,2)}let input=parsed.data,dirResult=resolveWorkingDirectory(input.working_directory,directory);if(!dirResult.success){let fail={success:!1,reason:"invalid_working_directory",message:dirResult.message};return JSON.stringify(fail,null,2)}let workingDir=dirResult.directory,generalConfig=loadPluginConfig(workingDir).council?.general;if(!generalConfig||generalConfig.enabled!==!0)return JSON.stringify({success:!1,reason:"council_general_disabled",message:"convene_general_council requires council.general.enabled: true in the resolved config: global ~/.config/opencode/opencode-swarm.json or project .opencode/opencode-swarm.json."},null,2);let round1=input.round1Responses,round2=input.round2Responses??[],result=synthesizeGeneralCouncil(input.question,input.mode,round1,round2),evidenceDir=path180.join(workingDir,".swarm","council","general"),evidenceFile=`${result.timestamp.replace(/[:.]/g,"-")}-${input.mode}.json`,evidencePath=path180.join(evidenceDir,evidenceFile);try{await fs108.promises.mkdir(evidenceDir,{recursive:!0}),await fs108.promises.writeFile(evidencePath,JSON.stringify(result,null,2))}catch(err){let message=err instanceof Error?err.message:String(err);console.warn(`[convene_general_council] Failed to write evidence to ${evidencePath}: ${message}`)}try{let sessionID=ctx?.sessionID;if(sessionID){let session=getAgentSession(sessionID);if(session)pushGeneralCouncilAdvisory(session,result)}}catch{}let ok={success:!0,question:input.question,mode:input.mode,roundsCompleted:round2.length>0?2:1,consensusPoints:result.consensusPoints,disagreementsCount:result.disagreements.length,persistingDisagreements:result.persistingDisagreements,allSourcesCount:result.allSources.length,synthesis:result.synthesis,evidencePath};return JSON.stringify(ok,null,2)}});init_zod();init_config();init_schema();init_curator();init_curator();init_curator_llm_factory();init_review_receipt();init_utils2();init_create_tool();var curator_analyze=createSwarmTool({description:"Run curator phase analysis and optionally apply knowledge recommendations. Call this after reviewing a phase to apply knowledge updates. If recommendations is provided, applies them via applyCuratorKnowledgeUpdates.",args:{phase:exports_external.number().int().min(1).describe("Phase number to analyze"),recommendations:exports_external.array(exports_external.object({action:exports_external.enum(["promote","archive","flag_contradiction","rewrite"]),entry_id:exports_external.string().optional(),lesson:exports_external.string(),reason:exports_external.string(),category:exports_external.enum(["process","architecture","tooling","security","testing","debugging","performance","integration","other"]).optional(),confidence:exports_external.number().min(0).max(1).optional()})).optional().describe("Knowledge recommendations to apply. If omitted, only collects digest data.")},execute:async(args2,directory,ctx)=>{let typedArgs=args2;try{if(!Number.isInteger(typedArgs.phase)||typedArgs.phase<1)return JSON.stringify({error:"phase must be a positive integer >= 1"},null,2);if(typedArgs.recommendations){let validActions=["promote","archive","flag_contradiction","rewrite"];for(let rec of typedArgs.recommendations)if(!validActions.includes(rec.action))return JSON.stringify({error:`Invalid recommendation action: ${rec.action}`},null,2)}if(typedArgs.recommendations){let UUID_V42=/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;for(let rec of typedArgs.recommendations)if(rec.entry_id!==void 0&&!UUID_V42.test(rec.entry_id))return JSON.stringify({error:`Invalid entry_id '${rec.entry_id}': must be a UUID v4 or omitted. Use undefined/omit entry_id to create a new entry.`},null,2)}let{config:config3}=loadPluginConfigWithMeta(directory),curatorConfig=CuratorConfigSchema.parse(config3.curator??{}),knowledgeConfig=KnowledgeConfigSchema.parse(config3.knowledge??{}),agentsDispatched=[];try{let eventsContent=await readSwarmFileAsync(directory,"events.jsonl");if(eventsContent){let phaseEvents=filterPhaseEvents(eventsContent,typedArgs.phase),agentSet=new Set;for(let evt of phaseEvents){let record3=evt;if(typeof record3.agent==="string"&&record3.agent.length>0)agentSet.add(record3.agent);if(Array.isArray(record3.agents_dispatched)){for(let a of record3.agents_dispatched)if(typeof a==="string")agentSet.add(a)}}agentsDispatched=Array.from(agentSet).sort()}}catch{}let llmDelegate=createCuratorLLMDelegate(directory,"phase",ctx?.sessionID),curatorResult=await runCuratorPhase(directory,typedArgs.phase,agentsDispatched,curatorConfig,{},llmDelegate);{let scopeContent=curatorResult.digest?.summary??`Phase ${typedArgs.phase} curator analysis`,complianceWarnings=curatorResult.compliance.filter((c)=>c.severity==="warning"),receipt=complianceWarnings.length>0?buildRejectedReceipt({agent:"curator",scopeContent,scopeDescription:"phase-digest",blockingFindings:complianceWarnings.map((c)=>({location:`phase-${c.phase}`,summary:c.description,severity:c.type==="missing_reviewer"?"high":"medium"})),evidenceReferences:[],passConditions:["resolve all compliance warnings before phase completion"]}):buildApprovedReceipt({agent:"curator",scopeContent,scopeDescription:"phase-digest",checkedAspects:["phase_compliance","knowledge_recommendations","phase_digest"],validatedClaims:[`phase: ${typedArgs.phase}`,`knowledge_recommendations: ${curatorResult.knowledge_recommendations.length}`]});persistReviewReceipt(directory,receipt).catch(()=>{})}let applied=0,skipped=0;if(typedArgs.recommendations&&typedArgs.recommendations.length>0){let result=await applyCuratorKnowledgeUpdates(directory,typedArgs.recommendations,knowledgeConfig);applied=result.applied,skipped=result.skipped}return JSON.stringify({phase_digest:curatorResult.digest,compliance_count:curatorResult.compliance.length,applied,skipped},null,2)}catch(error93){return JSON.stringify({error:error93 instanceof Error?error93.message:String(error93),phase:typedArgs.phase},null,2)}}});init_zod();init_loader();init_create_tool();init_resolve_working_directory();var CriteriaItemSchema=exports_external.object({id:exports_external.string().min(1).max(20).regex(/^C\d+$/,'Criterion id must match C\\d+ (e.g. "C1", "C12")'),description:exports_external.string().min(10).max(500),mandatory:exports_external.boolean()}),ArgsSchema3=exports_external.object({taskId:exports_external.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/,"Task ID must be in N.M or N.M.P format"),criteria:exports_external.array(CriteriaItemSchema).min(1).max(20),working_directory:exports_external.string().optional()}),declare_council_criteria=createSwarmTool({description:"Pre-declare acceptance criteria for a task before the coder starts work. Criteria are persisted under .swarm/council/ and read back during council evaluation so reviewers assess a stable, pre-committed contract. Architect-only. Config-gated via council.enabled.",args:{taskId:exports_external.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/,"Task ID must be in N.M or N.M.P format").describe('Task ID for which criteria are declared, e.g. "1.1", "1.2.3"'),criteria:exports_external.array(exports_external.object({id:exports_external.string().min(1).max(20).regex(/^C\d+$/,"Criterion id must match C\\d+").describe('Criterion identifier, e.g. "C1", "C12"'),description:exports_external.string().min(10).max(500).describe("Human-readable description of the criterion"),mandatory:exports_external.boolean().describe("Whether the criterion is mandatory. Mandatory criteria block APPROVE when unmet.")})).min(1).max(20).describe("Array of acceptance criteria items. Must contain between 1 and 20 entries with unique ids."),working_directory:exports_external.string().optional().describe("Explicit project root directory. When provided, .swarm/council/ is resolved relative to this path instead of the plugin context directory.")},async execute(args2,directory){let parsed=ArgsSchema3.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,reason:"invalid arguments",errors:parsed.error.issues.map((i)=>({path:i.path.join("."),message:i.message}))},null,2);let input=parsed.data,dirResult=resolveWorkingDirectory(input.working_directory,directory);if(!dirResult.success)return JSON.stringify({success:!1,reason:dirResult.message},null,2);let workingDir=dirResult.directory;if(!loadPluginConfig(workingDir).council?.enabled)return JSON.stringify({success:!1,reason:"council feature is disabled — set council.enabled: true in .opencode/opencode-swarm.json to enable"},null,2);let ids=input.criteria.map((c)=>c.id);if(new Set(ids).size<ids.length){let seen=new Set,duplicates=[];for(let id of ids){if(seen.has(id)&&!duplicates.includes(id))duplicates.push(id);seen.add(id)}return JSON.stringify({success:!1,reason:"duplicate criterion ids",errors:duplicates},null,2)}let replaced=readCriteria(workingDir,input.taskId)!==null;return await writeCriteria(workingDir,input.taskId,input.criteria),JSON.stringify({success:!0,taskId:input.taskId,criteriaCount:input.criteria.length,mandatoryCount:input.criteria.filter((c)=>c.mandatory).length,declaredAt:new Date().toISOString(),replaced},null,2)}});init_zod();init_guardrails2();init_scope_persistence();init_state2();init_task_id();init_create_tool();import*as fs109 from"node:fs";import*as path181 from"node:path";function validateTaskIdFormat2(taskId){return validateTaskIdFormat(taskId)}function validateFiles(files){let errors5=[];for(let file3 of files){if(file3.includes("\x00"))errors5.push(`Invalid file "${file3}": null bytes are not allowed`);if(file3.includes(".."))errors5.push(`Invalid file "${file3}": path traversal sequences (..) are not allowed`);if(file3.length>4096)errors5.push(`Invalid file "${file3}": path exceeds maximum length of 4096 characters`)}return errors5}async function executeDeclareScope(args2,fallbackDir){let taskIdError=validateTaskIdFormat2(args2.taskId);if(taskIdError)return{success:!1,message:"Validation failed",errors:[taskIdError]};if(!Array.isArray(args2.files)||args2.files.length===0)return{success:!1,message:"Validation failed",errors:["files must be a non-empty array"]};let fileErrors=validateFiles(args2.files);if(fileErrors.length>0)return{success:!1,message:"Validation failed",errors:fileErrors};if(args2.whitelist){let whitelistErrors=validateFiles(args2.whitelist);if(whitelistErrors.length>0)return{success:!1,message:"Validation failed",errors:whitelistErrors}}let normalizedDir;if(args2.working_directory!=null&&args2.working_directory.trim()!==""){if(args2.working_directory.includes("\x00"))return{success:!1,message:"Invalid working_directory: null bytes are not allowed",errors:["Invalid working_directory: null bytes are not allowed"]};if(/^\\\\|^(NUL|CON|AUX|COM[1-9]|LPT[1-9])(\..*)?$/i.test(args2.working_directory))return{success:!1,message:"Invalid working_directory: Windows device paths are not allowed",errors:["Invalid working_directory: Windows device paths are not allowed"]};if(normalizedDir=path181.normalize(args2.working_directory),normalizedDir.split(path181.sep).includes(".."))return{success:!1,message:"Invalid working_directory: path traversal sequences (..) are not allowed",errors:["Invalid working_directory: path traversal sequences (..) are not allowed"]};let resolvedDir=path181.resolve(normalizedDir);try{let realPath=fs109.realpathSync(resolvedDir),planPath2=path181.join(realPath,".swarm","plan.json");if(!fs109.existsSync(planPath2))return{success:!1,message:`Invalid working_directory: plan not found in "${realPath}"`,errors:[`Invalid working_directory: plan not found in "${realPath}"`]}}catch{return{success:!1,message:`Invalid working_directory: path "${resolvedDir}" does not exist or is inaccessible`,errors:[`Invalid working_directory: path "${resolvedDir}" does not exist or is inaccessible`]}}if(normalizedDir&&fallbackDir)try{let canonicalWorkingDir=fs109.realpathSync(path181.resolve(normalizedDir)),canonicalProjectRoot=fs109.realpathSync(path181.resolve(fallbackDir));if(canonicalWorkingDir.startsWith(canonicalProjectRoot+path181.sep))return{success:!1,message:`working_directory "${normalizedDir}" is a subdirectory of the project root. Use the project root "${fallbackDir}" instead.`,errors:[`Subdirectory working_directory not allowed — use project root "${fallbackDir}"`]}}catch{}}if(!normalizedDir&&!fallbackDir)return{success:!1,message:"Cannot resolve project directory",errors:["Provide working_directory or ensure the tool is invoked from a project root"]};let directory=normalizedDir||fallbackDir,planPath=path181.resolve(directory,".swarm","plan.json");if(!fs109.existsSync(planPath))return{success:!1,message:"No plan found",errors:["plan.json not found"]};let planContent;try{planContent=JSON.parse(fs109.readFileSync(planPath,"utf-8"))}catch{return{success:!1,message:"Failed to parse plan.json",errors:["plan.json is not valid JSON"]}}let allTasks=planContent.phases?.flatMap((p)=>p.tasks??[])??[];if(!allTasks.some((t)=>t.id===args2.taskId))return{success:!1,message:`Task ${args2.taskId} not found in plan`,errors:[`Task ${args2.taskId} does not exist in plan.json`]};let taskInPlan=allTasks.find((t)=>t.id===args2.taskId);if(taskInPlan&&taskInPlan.status==="completed")return{success:!1,message:`Task ${args2.taskId} is already completed`,errors:[`Cannot declare scope for completed task ${args2.taskId}`]};let rawMergedFiles=[...args2.files,...args2.whitelist??[]],warnings=[],normalizeErrors=[],dir=directory,mergedFiles=rawMergedFiles.map((file3)=>{if(path181.isAbsolute(file3)){let relativePath=path181.relative(dir,file3).replace(/\\/g,"/");if(relativePath.startsWith(".."))return normalizeErrors.push(`Path '${file3}' resolves outside the project directory`),file3;return warnings.push(`Absolute path normalized to relative: '${relativePath}' (was '${file3}')`),relativePath}return file3});if(normalizeErrors.length>0)return{success:!1,message:"Validation failed",errors:normalizeErrors};let lstatErrors=[];for(let file3 of mergedFiles){let block=checkWriteTargetForSymlink(file3,dir);if(block)lstatErrors.push(block)}if(lstatErrors.length>0)return{success:!1,message:"Scope contains symlink-backed paths",errors:lstatErrors};for(let[_sessionId,session]of swarmState.agentSessions)session.declaredCoderScope=mergedFiles,session.lastScopeViolation=null;return writeScopeToDisk(dir,args2.taskId,mergedFiles).catch(()=>{}),warnings.push("SCOPE ENFORCEMENT NOTE: Scope is enforced at the Edit/Write/Patch tool layer only. "+"Bash-based writes (sed -i, echo >, cat > <<HEREDOC, etc.) bypass this check — "+"see issue #520 for the syscall-layer follow-up."),{success:!0,message:"Scope declared successfully",taskId:args2.taskId,fileCount:mergedFiles.length,warnings}}var declare_scope=createSwarmTool({description:"Declare the file scope for the next coder delegation. Sets the list of files the coder is permitted to modify for a specific task. Must be called before delegating to coder to enable scope containment checking.",args:{taskId:exports_external.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/,"Task ID must be in N.M or N.M.P format").describe('Task ID for which scope is being declared, e.g. "1.1", "1.2.3"'),files:exports_external.array(exports_external.string().min(1).max(4096)).min(1).describe("Array of file paths the coder is permitted to modify"),whitelist:exports_external.array(exports_external.string().min(1).max(4096)).optional().describe("Additional file paths to whitelist (merged with files)"),working_directory:exports_external.string().optional().describe("Working directory where the plan is located")},execute:async(args2,_directory)=>{return JSON.stringify(await executeDeclareScope(args2,_directory),null,2)}});init_zod();import*as child_process14 from"node:child_process";import*as fs110 from"node:fs";import*as path182 from"node:path";init_create_tool();var MAX_DIFF_LINES=500,DIFF_TIMEOUT_MS=30000,MAX_BUFFER_BYTES=5242880,MAX_AST_FILES=50,CONTRACT_PATTERNS=[/^[+-]\s*export\s+(function|const|class|interface|type|enum|default)\b/,/^[+-]\s*(interface|type)\s+\w+/,/^[+-]\s*public\s+/,/^[+-]\s*(async\s+)?function\s+\w+\s*\(/],SAFE_REF_PATTERN=/^[a-zA-Z0-9._\-/~^@{}]+$/,MAX_REF_LENGTH=256,MAX_PATH_LENGTH=500,SHELL_METACHARACTERS2=/[;|&$`(){}<>!'"]/,CONTROL_CHAR_PATTERN2=/[\u0000-\u001F\u007F]/;function validateBase(base){if(base.length>MAX_REF_LENGTH)return`base ref exceeds maximum length of ${MAX_REF_LENGTH}`;if(!SAFE_REF_PATTERN.test(base))return"base contains invalid characters for git ref";return null}function validatePaths(paths){if(!paths)return null;for(let path183 of paths){if(!path183||path183.length===0)return"empty path not allowed";if(path183.length>MAX_PATH_LENGTH)return`path exceeds maximum length of ${MAX_PATH_LENGTH}`;if(SHELL_METACHARACTERS2.test(path183))return"path contains shell metacharacters";if(path183.startsWith("-"))return'path cannot start with "-" (option-like arguments not allowed)';if(CONTROL_CHAR_PATTERN2.test(path183))return"path contains control characters"}return null}var diff=createSwarmTool({description:"Analyze git diff for changed files, exports, interfaces, and function signatures. Returns structured output with contract change detection.",args:{base:exports_external.string().optional().describe('Base ref to diff against (default: HEAD). Use "staged" for staged changes, "unstaged" for working tree changes.'),paths:exports_external.array(exports_external.string()).optional().describe("Optional file paths to restrict diff scope."),summaryOnly:exports_external.boolean().optional().describe("When true, return only file list with additions/deletions counts and hasContractChanges. No hunk content or AST diff. Default false.")},async execute(args2,directory,_ctx){let typedArgs=args2,summaryOnly=typedArgs.summaryOnly===!0;try{let fileExistsInRef=function(refPath){try{return child_process14.execFileSync("git",["cat-file","-e",refPath],{encoding:"utf-8",timeout:3000,cwd:directory,stdio:["ignore","pipe","pipe"]}),!0}catch(e){if(e&&typeof e==="object"&&"code"in e){if(e.code==="ENOENT")throw e}return!1}},getContentFromRef=function(refPath){return child_process14.execFileSync("git",["show",refPath],{encoding:"utf-8",timeout:15000,cwd:directory,stdio:["ignore","pipe","pipe"]})};if(!directory||typeof directory!=="string"||directory.trim()==="")return JSON.stringify({error:"project directory is required but was not provided",files:[],contractChanges:[],hasContractChanges:!1},null,2);let base=typedArgs.base??"HEAD",baseValidationError=validateBase(base);if(baseValidationError){let errorResult={error:`invalid base: ${baseValidationError}`,files:[],contractChanges:[],hasContractChanges:!1};return JSON.stringify(errorResult,null,2)}let pathsValidationError=validatePaths(typedArgs.paths);if(pathsValidationError){let errorResult={error:`invalid paths: ${pathsValidationError}`,files:[],contractChanges:[],hasContractChanges:!1};return JSON.stringify(errorResult,null,2)}let gitArgs;if(base==="staged")gitArgs=["--no-pager","diff","--cached"];else if(base==="unstaged")gitArgs=["--no-pager","diff"];else gitArgs=["--no-pager","diff",base];let numstatArgs=[...gitArgs,"--numstat"],fullDiffArgs=[...gitArgs,"-U3"];if(typedArgs.paths?.length)numstatArgs.push("--",...typedArgs.paths),fullDiffArgs.push("--",...typedArgs.paths);let numstatOutput=child_process14.execFileSync("git",numstatArgs,{encoding:"utf-8",timeout:DIFF_TIMEOUT_MS,maxBuffer:MAX_BUFFER_BYTES,cwd:directory,stdio:["ignore","pipe","pipe"]}),files=[],numstatLines=numstatOutput.split(`
|
|
5869
|
+
`)}function synthesizeGeneralCouncil(question,mode,round1Responses,round2Responses){let safeRound1=Array.isArray(round1Responses)?round1Responses:[],safeRound2=Array.isArray(round2Responses)?round2Responses:[],disagreements=detectDisagreements(safeRound1),consensusPoints=buildConsensusClusters(safeRound1),persistingDisagreements=computePersistingDisagreements(disagreements,safeRound2),allSources=dedupeSources(safeRound1,safeRound2),roundsCompleted=safeRound2.length>0?2:1,synthesis=renderSynthesisMarkdown(question,mode,roundsCompleted,safeRound1,consensusPoints,persistingDisagreements,allSources);return{question,mode,round1Responses:safeRound1,disagreements,round2Responses:safeRound2,synthesis,consensusPoints,persistingDisagreements:persistingDisagreements.map((d)=>d.topic),allSources,timestamp:new Date().toISOString()}}init_state2();init_logger();init_create_tool();init_resolve_working_directory();var WebSearchResultSchema=exports_external.object({title:exports_external.string(),url:exports_external.string(),snippet:exports_external.string(),query:exports_external.string()}),MemberRoleEnum=exports_external.enum(["generalist","skeptic","domain_expert","devil_advocate","synthesizer"]),Round1ResponseSchema=exports_external.object({memberId:exports_external.string().min(1),model:exports_external.string().min(1),role:MemberRoleEnum,response:exports_external.string(),sources:exports_external.array(WebSearchResultSchema).default([]),searchQueries:exports_external.array(exports_external.string()).default([]),confidence:exports_external.number().min(0).max(1),areasOfUncertainty:exports_external.array(exports_external.string()).default([]),durationMs:exports_external.number().nonnegative().default(0)}),Round2ResponseSchema=Round1ResponseSchema.extend({disagreementTopics:exports_external.array(exports_external.string()).default([])}),ArgsSchema2=exports_external.object({question:exports_external.string().min(1).max(8000),mode:exports_external.enum(["general","spec_review"]).default("general"),members:exports_external.array(exports_external.string()).default([]),round1Responses:exports_external.array(Round1ResponseSchema).min(1),round2Responses:exports_external.array(Round2ResponseSchema).optional(),working_directory:exports_external.string().optional()}),convene_general_council=createSwarmTool({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.",args:{question:exports_external.string().min(1).max(8000).describe("The question put to the council, or the spec text to review."),mode:exports_external.enum(["general","spec_review"]).optional().describe('"general" for /swarm council or pre-save PLAN advisory; "spec_review" for manual /swarm council --spec-review.'),members:exports_external.array(exports_external.string()).optional().describe("Optional list of member IDs convened (for evidence/audit)."),round1Responses:exports_external.array(exports_external.object({memberId:exports_external.string().min(1),model:exports_external.string().min(1),role:exports_external.enum(["generalist","skeptic","domain_expert","devil_advocate","synthesizer"]),response:exports_external.string(),sources:exports_external.array(exports_external.object({title:exports_external.string(),url:exports_external.string(),snippet:exports_external.string(),query:exports_external.string()})).optional(),searchQueries:exports_external.array(exports_external.string()).optional(),confidence:exports_external.number().min(0).max(1),areasOfUncertainty:exports_external.array(exports_external.string()).optional(),durationMs:exports_external.number().nonnegative().optional()})).describe("Round 1 member responses (one per council member)."),round2Responses:exports_external.array(exports_external.object({memberId:exports_external.string().min(1),model:exports_external.string().min(1),role:exports_external.enum(["generalist","skeptic","domain_expert","devil_advocate","synthesizer"]),response:exports_external.string(),sources:exports_external.array(exports_external.object({title:exports_external.string(),url:exports_external.string(),snippet:exports_external.string(),query:exports_external.string()})).optional(),searchQueries:exports_external.array(exports_external.string()).optional(),confidence:exports_external.number().min(0).max(1),areasOfUncertainty:exports_external.array(exports_external.string()).optional(),durationMs:exports_external.number().nonnegative().optional(),disagreementTopics:exports_external.array(exports_external.string()).optional()})).optional().describe("Round 2 deliberation responses (omit when no deliberation has occurred)."),working_directory:exports_external.string().optional().describe("Project root for config + evidence path resolution.")},execute:async(args2,directory,ctx)=>{let parsed=ArgsSchema2.safeParse(args2);if(!parsed.success){let fail={success:!1,reason:"invalid_args",message:parsed.error.issues.map((i)=>`${i.path.join(".")}: ${i.message}`).join("; ")};return JSON.stringify(fail,null,2)}let input=parsed.data,dirResult=resolveWorkingDirectory(input.working_directory,directory);if(!dirResult.success){let fail={success:!1,reason:"invalid_working_directory",message:dirResult.message};return JSON.stringify(fail,null,2)}let workingDir=dirResult.directory,generalConfig=loadPluginConfig(workingDir).council?.general;if(!generalConfig||generalConfig.enabled!==!0)return JSON.stringify({success:!1,reason:"council_general_disabled",message:"convene_general_council requires council.general.enabled: true in the resolved config: global ~/.config/opencode/opencode-swarm.json or project .opencode/opencode-swarm.json."},null,2);let round1=input.round1Responses,round2=input.round2Responses??[],result=synthesizeGeneralCouncil(input.question,input.mode,round1,round2),evidenceDir=path180.join(workingDir,".swarm","council","general"),evidenceFile=`${result.timestamp.replace(/[:.]/g,"-")}-${input.mode}.json`,evidencePath=path180.join(evidenceDir,evidenceFile);try{await fs108.promises.mkdir(evidenceDir,{recursive:!0}),await fs108.promises.writeFile(evidencePath,JSON.stringify(result,null,2))}catch(err){let message=err instanceof Error?err.message:String(err);log(`[convene_general_council] Failed to write evidence to ${evidencePath}: ${message}`)}try{let sessionID=ctx?.sessionID;if(sessionID){let session=getAgentSession(sessionID);if(session)pushGeneralCouncilAdvisory(session,result)}}catch{}let ok={success:!0,question:input.question,mode:input.mode,roundsCompleted:round2.length>0?2:1,consensusPoints:result.consensusPoints,disagreementsCount:result.disagreements.length,persistingDisagreements:result.persistingDisagreements,allSourcesCount:result.allSources.length,synthesis:result.synthesis,evidencePath};return JSON.stringify(ok,null,2)}});init_zod();init_config();init_schema();init_curator();init_curator();init_curator_llm_factory();init_review_receipt();init_utils2();init_create_tool();var curator_analyze=createSwarmTool({description:"Run curator phase analysis and optionally apply knowledge recommendations. Call this after reviewing a phase to apply knowledge updates. If recommendations is provided, applies them via applyCuratorKnowledgeUpdates.",args:{phase:exports_external.number().int().min(1).describe("Phase number to analyze"),recommendations:exports_external.array(exports_external.object({action:exports_external.enum(["promote","archive","flag_contradiction","rewrite"]),entry_id:exports_external.string().optional(),lesson:exports_external.string(),reason:exports_external.string(),category:exports_external.enum(["process","architecture","tooling","security","testing","debugging","performance","integration","other"]).optional(),confidence:exports_external.number().min(0).max(1).optional()})).optional().describe("Knowledge recommendations to apply. If omitted, only collects digest data.")},execute:async(args2,directory,ctx)=>{let typedArgs=args2;try{if(!Number.isInteger(typedArgs.phase)||typedArgs.phase<1)return JSON.stringify({error:"phase must be a positive integer >= 1"},null,2);if(typedArgs.recommendations){let validActions=["promote","archive","flag_contradiction","rewrite"];for(let rec of typedArgs.recommendations)if(!validActions.includes(rec.action))return JSON.stringify({error:`Invalid recommendation action: ${rec.action}`},null,2)}if(typedArgs.recommendations){let UUID_V42=/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;for(let rec of typedArgs.recommendations)if(rec.entry_id!==void 0&&!UUID_V42.test(rec.entry_id))return JSON.stringify({error:`Invalid entry_id '${rec.entry_id}': must be a UUID v4 or omitted. Use undefined/omit entry_id to create a new entry.`},null,2)}let{config:config3}=loadPluginConfigWithMeta(directory),curatorConfig=CuratorConfigSchema.parse(config3.curator??{}),knowledgeConfig=KnowledgeConfigSchema.parse(config3.knowledge??{}),agentsDispatched=[];try{let eventsContent=await readSwarmFileAsync(directory,"events.jsonl");if(eventsContent){let phaseEvents=filterPhaseEvents(eventsContent,typedArgs.phase),agentSet=new Set;for(let evt of phaseEvents){let record3=evt;if(typeof record3.agent==="string"&&record3.agent.length>0)agentSet.add(record3.agent);if(Array.isArray(record3.agents_dispatched)){for(let a of record3.agents_dispatched)if(typeof a==="string")agentSet.add(a)}}agentsDispatched=Array.from(agentSet).sort()}}catch{}let llmDelegate=createCuratorLLMDelegate(directory,"phase",ctx?.sessionID),curatorResult=await runCuratorPhase(directory,typedArgs.phase,agentsDispatched,curatorConfig,{},llmDelegate);{let scopeContent=curatorResult.digest?.summary??`Phase ${typedArgs.phase} curator analysis`,complianceWarnings=curatorResult.compliance.filter((c)=>c.severity==="warning"),receipt=complianceWarnings.length>0?buildRejectedReceipt({agent:"curator",scopeContent,scopeDescription:"phase-digest",blockingFindings:complianceWarnings.map((c)=>({location:`phase-${c.phase}`,summary:c.description,severity:c.type==="missing_reviewer"?"high":"medium"})),evidenceReferences:[],passConditions:["resolve all compliance warnings before phase completion"]}):buildApprovedReceipt({agent:"curator",scopeContent,scopeDescription:"phase-digest",checkedAspects:["phase_compliance","knowledge_recommendations","phase_digest"],validatedClaims:[`phase: ${typedArgs.phase}`,`knowledge_recommendations: ${curatorResult.knowledge_recommendations.length}`]});persistReviewReceipt(directory,receipt).catch(()=>{})}let applied=0,skipped=0;if(typedArgs.recommendations&&typedArgs.recommendations.length>0){let result=await applyCuratorKnowledgeUpdates(directory,typedArgs.recommendations,knowledgeConfig);applied=result.applied,skipped=result.skipped}return JSON.stringify({phase_digest:curatorResult.digest,compliance_count:curatorResult.compliance.length,applied,skipped},null,2)}catch(error93){return JSON.stringify({error:error93 instanceof Error?error93.message:String(error93),phase:typedArgs.phase},null,2)}}});init_zod();init_loader();init_create_tool();init_resolve_working_directory();var CriteriaItemSchema=exports_external.object({id:exports_external.string().min(1).max(20).regex(/^C\d+$/,'Criterion id must match C\\d+ (e.g. "C1", "C12")'),description:exports_external.string().min(10).max(500),mandatory:exports_external.boolean()}),ArgsSchema3=exports_external.object({taskId:exports_external.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/,"Task ID must be in N.M or N.M.P format"),criteria:exports_external.array(CriteriaItemSchema).min(1).max(20),working_directory:exports_external.string().optional()}),declare_council_criteria=createSwarmTool({description:"Pre-declare acceptance criteria for a task before the coder starts work. Criteria are persisted under .swarm/council/ and read back during council evaluation so reviewers assess a stable, pre-committed contract. Architect-only. Config-gated via council.enabled.",args:{taskId:exports_external.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/,"Task ID must be in N.M or N.M.P format").describe('Task ID for which criteria are declared, e.g. "1.1", "1.2.3"'),criteria:exports_external.array(exports_external.object({id:exports_external.string().min(1).max(20).regex(/^C\d+$/,"Criterion id must match C\\d+").describe('Criterion identifier, e.g. "C1", "C12"'),description:exports_external.string().min(10).max(500).describe("Human-readable description of the criterion"),mandatory:exports_external.boolean().describe("Whether the criterion is mandatory. Mandatory criteria block APPROVE when unmet.")})).min(1).max(20).describe("Array of acceptance criteria items. Must contain between 1 and 20 entries with unique ids."),working_directory:exports_external.string().optional().describe("Explicit project root directory. When provided, .swarm/council/ is resolved relative to this path instead of the plugin context directory.")},async execute(args2,directory){let parsed=ArgsSchema3.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,reason:"invalid arguments",errors:parsed.error.issues.map((i)=>({path:i.path.join("."),message:i.message}))},null,2);let input=parsed.data,dirResult=resolveWorkingDirectory(input.working_directory,directory);if(!dirResult.success)return JSON.stringify({success:!1,reason:dirResult.message},null,2);let workingDir=dirResult.directory;if(!loadPluginConfig(workingDir).council?.enabled)return JSON.stringify({success:!1,reason:"council feature is disabled — set council.enabled: true in .opencode/opencode-swarm.json to enable"},null,2);let ids=input.criteria.map((c)=>c.id);if(new Set(ids).size<ids.length){let seen=new Set,duplicates=[];for(let id of ids){if(seen.has(id)&&!duplicates.includes(id))duplicates.push(id);seen.add(id)}return JSON.stringify({success:!1,reason:"duplicate criterion ids",errors:duplicates},null,2)}let replaced=readCriteria(workingDir,input.taskId)!==null;return await writeCriteria(workingDir,input.taskId,input.criteria),JSON.stringify({success:!0,taskId:input.taskId,criteriaCount:input.criteria.length,mandatoryCount:input.criteria.filter((c)=>c.mandatory).length,declaredAt:new Date().toISOString(),replaced},null,2)}});init_zod();init_guardrails2();init_scope_persistence();init_state2();init_task_id();init_create_tool();import*as fs109 from"node:fs";import*as path181 from"node:path";function validateTaskIdFormat2(taskId){return validateTaskIdFormat(taskId)}function validateFiles(files){let errors5=[];for(let file3 of files){if(file3.includes("\x00"))errors5.push(`Invalid file "${file3}": null bytes are not allowed`);if(file3.includes(".."))errors5.push(`Invalid file "${file3}": path traversal sequences (..) are not allowed`);if(file3.length>4096)errors5.push(`Invalid file "${file3}": path exceeds maximum length of 4096 characters`)}return errors5}async function executeDeclareScope(args2,fallbackDir){let taskIdError=validateTaskIdFormat2(args2.taskId);if(taskIdError)return{success:!1,message:"Validation failed",errors:[taskIdError]};if(!Array.isArray(args2.files)||args2.files.length===0)return{success:!1,message:"Validation failed",errors:["files must be a non-empty array"]};let fileErrors=validateFiles(args2.files);if(fileErrors.length>0)return{success:!1,message:"Validation failed",errors:fileErrors};if(args2.whitelist){let whitelistErrors=validateFiles(args2.whitelist);if(whitelistErrors.length>0)return{success:!1,message:"Validation failed",errors:whitelistErrors}}let normalizedDir;if(args2.working_directory!=null&&args2.working_directory.trim()!==""){if(args2.working_directory.includes("\x00"))return{success:!1,message:"Invalid working_directory: null bytes are not allowed",errors:["Invalid working_directory: null bytes are not allowed"]};if(/^\\\\|^(NUL|CON|AUX|COM[1-9]|LPT[1-9])(\..*)?$/i.test(args2.working_directory))return{success:!1,message:"Invalid working_directory: Windows device paths are not allowed",errors:["Invalid working_directory: Windows device paths are not allowed"]};if(normalizedDir=path181.normalize(args2.working_directory),normalizedDir.split(path181.sep).includes(".."))return{success:!1,message:"Invalid working_directory: path traversal sequences (..) are not allowed",errors:["Invalid working_directory: path traversal sequences (..) are not allowed"]};let resolvedDir=path181.resolve(normalizedDir);try{let realPath=fs109.realpathSync(resolvedDir),planPath2=path181.join(realPath,".swarm","plan.json");if(!fs109.existsSync(planPath2))return{success:!1,message:`Invalid working_directory: plan not found in "${realPath}"`,errors:[`Invalid working_directory: plan not found in "${realPath}"`]}}catch{return{success:!1,message:`Invalid working_directory: path "${resolvedDir}" does not exist or is inaccessible`,errors:[`Invalid working_directory: path "${resolvedDir}" does not exist or is inaccessible`]}}if(normalizedDir&&fallbackDir)try{let canonicalWorkingDir=fs109.realpathSync(path181.resolve(normalizedDir)),canonicalProjectRoot=fs109.realpathSync(path181.resolve(fallbackDir));if(canonicalWorkingDir.startsWith(canonicalProjectRoot+path181.sep))return{success:!1,message:`working_directory "${normalizedDir}" is a subdirectory of the project root. Use the project root "${fallbackDir}" instead.`,errors:[`Subdirectory working_directory not allowed — use project root "${fallbackDir}"`]}}catch{}}if(!normalizedDir&&!fallbackDir)return{success:!1,message:"Cannot resolve project directory",errors:["Provide working_directory or ensure the tool is invoked from a project root"]};let directory=normalizedDir||fallbackDir,planPath=path181.resolve(directory,".swarm","plan.json");if(!fs109.existsSync(planPath))return{success:!1,message:"No plan found",errors:["plan.json not found"]};let planContent;try{planContent=JSON.parse(fs109.readFileSync(planPath,"utf-8"))}catch{return{success:!1,message:"Failed to parse plan.json",errors:["plan.json is not valid JSON"]}}let allTasks=planContent.phases?.flatMap((p)=>p.tasks??[])??[];if(!allTasks.some((t)=>t.id===args2.taskId))return{success:!1,message:`Task ${args2.taskId} not found in plan`,errors:[`Task ${args2.taskId} does not exist in plan.json`]};let taskInPlan=allTasks.find((t)=>t.id===args2.taskId);if(taskInPlan&&taskInPlan.status==="completed")return{success:!1,message:`Task ${args2.taskId} is already completed`,errors:[`Cannot declare scope for completed task ${args2.taskId}`]};let rawMergedFiles=[...args2.files,...args2.whitelist??[]],warnings=[],normalizeErrors=[],dir=directory,mergedFiles=rawMergedFiles.map((file3)=>{if(path181.isAbsolute(file3)){let relativePath=path181.relative(dir,file3).replace(/\\/g,"/");if(relativePath.startsWith(".."))return normalizeErrors.push(`Path '${file3}' resolves outside the project directory`),file3;return warnings.push(`Absolute path normalized to relative: '${relativePath}' (was '${file3}')`),relativePath}return file3});if(normalizeErrors.length>0)return{success:!1,message:"Validation failed",errors:normalizeErrors};let lstatErrors=[];for(let file3 of mergedFiles){let block=checkWriteTargetForSymlink(file3,dir);if(block)lstatErrors.push(block)}if(lstatErrors.length>0)return{success:!1,message:"Scope contains symlink-backed paths",errors:lstatErrors};for(let[_sessionId,session]of swarmState.agentSessions)session.declaredCoderScope=mergedFiles,session.lastScopeViolation=null;return writeScopeToDisk(dir,args2.taskId,mergedFiles).catch(()=>{}),warnings.push("SCOPE ENFORCEMENT NOTE: Scope is enforced at the Edit/Write/Patch tool layer only. "+"Bash-based writes (sed -i, echo >, cat > <<HEREDOC, etc.) bypass this check — "+"see issue #520 for the syscall-layer follow-up."),{success:!0,message:"Scope declared successfully",taskId:args2.taskId,fileCount:mergedFiles.length,warnings}}var declare_scope=createSwarmTool({description:"Declare the file scope for the next coder delegation. Sets the list of files the coder is permitted to modify for a specific task. Must be called before delegating to coder to enable scope containment checking.",args:{taskId:exports_external.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/,"Task ID must be in N.M or N.M.P format").describe('Task ID for which scope is being declared, e.g. "1.1", "1.2.3"'),files:exports_external.array(exports_external.string().min(1).max(4096)).min(1).describe("Array of file paths the coder is permitted to modify"),whitelist:exports_external.array(exports_external.string().min(1).max(4096)).optional().describe("Additional file paths to whitelist (merged with files)"),working_directory:exports_external.string().optional().describe("Working directory where the plan is located")},execute:async(args2,_directory)=>{return JSON.stringify(await executeDeclareScope(args2,_directory),null,2)}});init_zod();import*as child_process14 from"node:child_process";import*as fs110 from"node:fs";import*as path182 from"node:path";init_create_tool();var MAX_DIFF_LINES=500,DIFF_TIMEOUT_MS=30000,MAX_BUFFER_BYTES=5242880,MAX_AST_FILES=50,CONTRACT_PATTERNS=[/^[+-]\s*export\s+(function|const|class|interface|type|enum|default)\b/,/^[+-]\s*(interface|type)\s+\w+/,/^[+-]\s*public\s+/,/^[+-]\s*(async\s+)?function\s+\w+\s*\(/],SAFE_REF_PATTERN=/^[a-zA-Z0-9._\-/~^@{}]+$/,MAX_REF_LENGTH=256,MAX_PATH_LENGTH=500,SHELL_METACHARACTERS2=/[;|&$`(){}<>!'"]/,CONTROL_CHAR_PATTERN2=/[\u0000-\u001F\u007F]/;function validateBase(base){if(base.length>MAX_REF_LENGTH)return`base ref exceeds maximum length of ${MAX_REF_LENGTH}`;if(!SAFE_REF_PATTERN.test(base))return"base contains invalid characters for git ref";return null}function validatePaths(paths){if(!paths)return null;for(let path183 of paths){if(!path183||path183.length===0)return"empty path not allowed";if(path183.length>MAX_PATH_LENGTH)return`path exceeds maximum length of ${MAX_PATH_LENGTH}`;if(SHELL_METACHARACTERS2.test(path183))return"path contains shell metacharacters";if(path183.startsWith("-"))return'path cannot start with "-" (option-like arguments not allowed)';if(CONTROL_CHAR_PATTERN2.test(path183))return"path contains control characters"}return null}var diff=createSwarmTool({description:"Analyze git diff for changed files, exports, interfaces, and function signatures. Returns structured output with contract change detection.",args:{base:exports_external.string().optional().describe('Base ref to diff against (default: HEAD). Use "staged" for staged changes, "unstaged" for working tree changes.'),paths:exports_external.array(exports_external.string()).optional().describe("Optional file paths to restrict diff scope."),summaryOnly:exports_external.boolean().optional().describe("When true, return only file list with additions/deletions counts and hasContractChanges. No hunk content or AST diff. Default false.")},async execute(args2,directory,_ctx){let typedArgs=args2,summaryOnly=typedArgs.summaryOnly===!0;try{let fileExistsInRef=function(refPath){try{return child_process14.execFileSync("git",["cat-file","-e",refPath],{encoding:"utf-8",timeout:3000,cwd:directory,stdio:["ignore","pipe","pipe"]}),!0}catch(e){if(e&&typeof e==="object"&&"code"in e){if(e.code==="ENOENT")throw e}return!1}},getContentFromRef=function(refPath){return child_process14.execFileSync("git",["show",refPath],{encoding:"utf-8",timeout:15000,cwd:directory,stdio:["ignore","pipe","pipe"]})};if(!directory||typeof directory!=="string"||directory.trim()==="")return JSON.stringify({error:"project directory is required but was not provided",files:[],contractChanges:[],hasContractChanges:!1},null,2);let base=typedArgs.base??"HEAD",baseValidationError=validateBase(base);if(baseValidationError){let errorResult={error:`invalid base: ${baseValidationError}`,files:[],contractChanges:[],hasContractChanges:!1};return JSON.stringify(errorResult,null,2)}let pathsValidationError=validatePaths(typedArgs.paths);if(pathsValidationError){let errorResult={error:`invalid paths: ${pathsValidationError}`,files:[],contractChanges:[],hasContractChanges:!1};return JSON.stringify(errorResult,null,2)}let gitArgs;if(base==="staged")gitArgs=["--no-pager","diff","--cached"];else if(base==="unstaged")gitArgs=["--no-pager","diff"];else gitArgs=["--no-pager","diff",base];let numstatArgs=[...gitArgs,"--numstat"],fullDiffArgs=[...gitArgs,"-U3"];if(typedArgs.paths?.length)numstatArgs.push("--",...typedArgs.paths),fullDiffArgs.push("--",...typedArgs.paths);let numstatOutput=child_process14.execFileSync("git",numstatArgs,{encoding:"utf-8",timeout:DIFF_TIMEOUT_MS,maxBuffer:MAX_BUFFER_BYTES,cwd:directory,stdio:["ignore","pipe","pipe"]}),files=[],numstatLines=numstatOutput.split(`
|
|
5870
5870
|
`);for(let line of numstatLines){if(!line.trim())continue;let parts=line.split("\t");if(parts.length>=3){let additions=parseInt(parts[0],10)||0,deletions=parseInt(parts[1],10)||0,path183=parts[2];files.push({path:path183,additions,deletions})}}if(summaryOnly){let hasContractChanges2=!1;try{let contractDiffArgs=[...gitArgs,"-U0"];if(typedArgs.paths?.length)contractDiffArgs.push("--",...typedArgs.paths);let contractDiffLines=child_process14.execFileSync("git",contractDiffArgs,{encoding:"utf-8",timeout:DIFF_TIMEOUT_MS,maxBuffer:MAX_BUFFER_BYTES,cwd:directory,stdio:["ignore","pipe","pipe"]}).split(`
|
|
5871
5871
|
`);for(let line of contractDiffLines){for(let pattern of CONTRACT_PATTERNS)if(pattern.test(line)){hasContractChanges2=!0;break}if(hasContractChanges2)break}}catch{hasContractChanges2=!0}let result2={files,contractChanges:[],hasContractChanges:hasContractChanges2,summary:`${files.length} files changed (summary only)`};return JSON.stringify(result2,null,2)}let fullDiffOutput=child_process14.execFileSync("git",fullDiffArgs,{encoding:"utf-8",timeout:DIFF_TIMEOUT_MS,maxBuffer:MAX_BUFFER_BYTES,cwd:directory,stdio:["ignore","pipe","pipe"]}),contractChanges=[],diffLines=fullDiffOutput.split(`
|
|
5872
5872
|
`),currentFile="";for(let line of diffLines){let gitLineMatch=line.match(/^diff --git.* b\/(.+)$/);if(gitLineMatch)currentFile=gitLineMatch[1];for(let pattern of CONTRACT_PATTERNS)if(pattern.test(line)){let trimmed=line.trim();if(currentFile)contractChanges.push(`[${currentFile}] ${trimmed}`);else contractChanges.push(trimmed);break}}let hasContractChanges=contractChanges.length>0,fileCount=files.length,astDiffs=[],filesForAST=files.slice(0,MAX_AST_FILES);for(let file3 of filesForAST)try{let oldContent,newContent;if(base==="staged"){let oldRef=`HEAD:${file3.path}`;oldContent=fileExistsInRef(oldRef)?getContentFromRef(oldRef):"",newContent=getContentFromRef(`:${file3.path}`)}else if(base==="unstaged"){let oldRef=`:${file3.path}`;oldContent=fileExistsInRef(oldRef)?getContentFromRef(oldRef):"",newContent=fs110.readFileSync(path182.join(directory,file3.path),"utf-8")}else{let oldRef=`${base}:${file3.path}`;oldContent=fileExistsInRef(oldRef)?getContentFromRef(oldRef):"",newContent=getContentFromRef(`HEAD:${file3.path}`)}let astResult=await computeASTDiff(file3.path,oldContent,newContent);if(astResult&&(astResult.changes.length>0||astResult.error))astDiffs.push(astResult)}catch(e){if(e&&typeof e==="object"&&"code"in e){if(e.code==="ENOENT")throw e}astDiffs.push({filePath:file3.path,language:null,changes:[{type:"modified",category:"other",name:"(parse failed)",lineStart:0,lineEnd:0}],durationMs:0,usedAST:!1,error:"AST parse unavailable — tree-sitter analysis failed for this file"})}let semanticSummary;if(astDiffs.length>0)try{let classifiedChanges=classifyChanges(astDiffs);semanticSummary=generateSummary(classifiedChanges)}catch{}let markdownSummary;if(semanticSummary)try{markdownSummary=generateSummaryMarkdown(semanticSummary)}catch{}let astSkippedCount=files.length>MAX_AST_FILES?files.length-MAX_AST_FILES:0,summary=diffLines.length>MAX_DIFF_LINES?`${fileCount} files changed. Contract changes: ${hasContractChanges?"YES":"NO"}. (truncated to ${MAX_DIFF_LINES} lines)`:`${fileCount} files changed. Contract changes: ${hasContractChanges?"YES":"NO"}`,result={files,contractChanges,hasContractChanges,summary,...astDiffs.length>0?{astDiffs}:{},...semanticSummary?{semanticSummary}:{},...markdownSummary?{markdownSummary}:{},...astSkippedCount>0?{astSkippedCount}:{}};return JSON.stringify(result,null,2)}catch(e){let errorResult={error:e instanceof Error?`git diff failed: ${e.message}`:"git diff failed: unknown error",files:[],contractChanges:[],hasContractChanges:!1};return JSON.stringify(errorResult,null,2)}}});init_zod();import*as child_process15 from"node:child_process";import*as fs111 from"node:fs";import*as path183 from"node:path";init_git_binary_missing_error();init_create_tool();init_resolve_working_directory();async function execGit3(workingDir,args2,options){try{return await new Promise((resolve70,reject)=>{let execOpts={encoding:"utf-8",cwd:workingDir,timeout:options?.timeout,maxBuffer:options?.maxBuffer,stdio:["ignore","pipe","pipe"]};child_process15.execFile("git",args2,execOpts,(error93,output,_stderr)=>{if(error93){reject(error93);return}resolve70(output??"")})})}catch(err){if(isGitBinaryMissing(err))throw new GitBinaryMissingError("git binary is not available",{cause:err});throw err}}var diff_summary=createSwarmTool({description:"Generate a filtered semantic diff summary from AST analysis. Returns SemanticDiffSummary with optional filtering by classification or riskLevel.",args:{files:exports_external.array(exports_external.string()).describe("Array of file paths to analyze"),classification:exports_external.string().optional().describe("Filter results to only this ChangeCategory"),riskLevel:exports_external.string().optional().describe("Filter results to only this RiskLevel")},async execute(args2,directory,_ctx){let typedArgs=args2;try{if(!typedArgs.files||!Array.isArray(typedArgs.files)||typedArgs.files.length===0)return JSON.stringify({error:"files must be a non-empty array of file paths",success:!1},null,2);let resolved=resolveWorkingDirectory(void 0,directory);if(!resolved.success)return JSON.stringify({success:!1,error:resolved.message},null,2);let workingDir=resolved.directory,astDiffs=[];for(let filePath of typedArgs.files){let astResult=null,fileExistsInHead=!1;try{await execGit3(workingDir,["cat-file","-e",`HEAD:${filePath}`],{timeout:3000}),fileExistsInHead=!0}catch(e){if(e instanceof GitBinaryMissingError)throw e}try{let oldContent,newContent=await fs111.promises.readFile(path183.join(workingDir,filePath),"utf-8");if(fileExistsInHead)oldContent=await execGit3(workingDir,["show",`HEAD:${filePath}`],{timeout:5000,maxBuffer:5242880});else oldContent="";astResult=await computeASTDiff(filePath,oldContent,newContent)}catch(e){if(e instanceof GitBinaryMissingError)throw e;astResult=null}if(astResult&&(astResult.changes.length>0||astResult.error!==void 0))astDiffs.push(astResult)}let filteredChanges=classifyChanges(astDiffs);if(typedArgs.classification)filteredChanges=filteredChanges.filter((change)=>change.category===typedArgs.classification);if(typedArgs.riskLevel)filteredChanges=filteredChanges.filter((change)=>change.riskLevel===typedArgs.riskLevel);let summary=generateSummary(filteredChanges);return JSON.stringify(summary,null,2)}catch(e){let errorResult={error:e instanceof Error?`diff_summary failed: ${e.message}`:"diff_summary failed: unknown error",success:!1};return JSON.stringify(errorResult,null,2)}}});import{createHash as createHash21}from"node:crypto";class Node{value;next;constructor(value){this.value=value}}class Queue{#head;#tail;#size;constructor(){this.clear()}enqueue(value){let node=new Node(value);if(this.#head)this.#tail.next=node,this.#tail=node;else this.#head=node,this.#tail=node;this.#size++}dequeue(){let current=this.#head;if(!current)return;if(this.#head=this.#head.next,this.#size--,!this.#head)this.#tail=void 0;return current.value}peek(){if(!this.#head)return;return this.#head.value}clear(){this.#head=void 0,this.#tail=void 0,this.#size=0}get size(){return this.#size}*[Symbol.iterator](){let current=this.#head;while(current)yield current.value,current=current.next}*drain(){while(this.#head)yield this.dequeue()}}function pLimit(concurrency){let rejectOnClear=!1;if(typeof concurrency==="object")({concurrency,rejectOnClear=!1}=concurrency);if(validateConcurrency(concurrency),typeof rejectOnClear!=="boolean")throw TypeError("Expected `rejectOnClear` to be a boolean");let queue=new Queue,activeCount=0,resumeNext=()=>{if(activeCount<concurrency&&queue.size>0)activeCount++,queue.dequeue().run()},next=()=>{activeCount--,resumeNext()},run=async(function_,resolve70,arguments_)=>{let result=(async()=>function_(...arguments_))();resolve70(result);try{await result}catch{}next()},enqueue=(function_,resolve70,reject,arguments_)=>{let queueItem={reject};if(new Promise((internalResolve)=>{queueItem.run=internalResolve,queue.enqueue(queueItem)}).then(run.bind(void 0,function_,resolve70,arguments_)),activeCount<concurrency)resumeNext()},generator=(function_,...arguments_)=>new Promise((resolve70,reject)=>{enqueue(function_,resolve70,reject,arguments_)});return Object.defineProperties(generator,{activeCount:{get:()=>activeCount},pendingCount:{get:()=>queue.size},clearQueue:{value(){if(!rejectOnClear){queue.clear();return}let abortError=AbortSignal.abort().reason;while(queue.size>0)queue.dequeue().reject(abortError)}},concurrency:{get:()=>concurrency,set(newConcurrency){validateConcurrency(newConcurrency),concurrency=newConcurrency,queueMicrotask(()=>{while(activeCount<concurrency&&queue.size>0)resumeNext()})}},map:{async value(iterable,function_){let promises12=Array.from(iterable,(value,index)=>this(function_,value,index));return Promise.all(promises12)}}}),generator}function validateConcurrency(concurrency){if(!((Number.isInteger(concurrency)||concurrency===Number.POSITIVE_INFINITY)&&concurrency>0))throw TypeError("Expected `concurrency` to be a number from 1 and up")}init_zod();init_zod();init_utils2();import{createHash as createHash20}from"node:crypto";import{existsSync as existsSync104,mkdirSync as mkdirSync46,readFileSync as readFileSync72,renameSync as renameSync30,unlinkSync as unlinkSync27,writeFileSync as writeFileSync28}from"node:fs";import*as path184 from"node:path";var LANE_OUTPUT_REF_PREFIX="L1",MAX_LANE_OUTPUT_STORED_BYTES=10485760,LANE_OUTPUT_SCHEMA_VERSION=1,REF_RE=/^L1:[a-f0-9]{64}:[a-f0-9]{64}:[a-f0-9]{64}$/,LaneOutputArtifactSchema=exports_external.object({schemaVersion:exports_external.literal(LANE_OUTPUT_SCHEMA_VERSION),ref:exports_external.string().regex(REF_RE),batchId:exports_external.string().min(1),laneId:exports_external.string().min(1),agent:exports_external.string().min(1),role:exports_external.string().min(1),sessionId:exports_external.string().min(1).optional(),parentSessionId:exports_external.string().min(1).optional(),mode:exports_external.string().min(1).optional(),source:exports_external.enum(["dispatch_lanes","collect_lane_results"]),text:exports_external.string(),chars:exports_external.number().int().nonnegative(),bytes:exports_external.number().int().nonnegative(),digest:exports_external.string().regex(/^[a-f0-9]{64}$/),messageCount:exports_external.number().int().nonnegative().optional(),transcriptIncomplete:exports_external.boolean().optional(),createdAt:exports_external.string(),updatedAt:exports_external.string()}).strict();function storeLaneOutput(directory,input,now=Date.now){let bytes=Buffer.byteLength(input.text,"utf-8"),digest3=digestText(input.text);if(bytes>MAX_LANE_OUTPUT_STORED_BYTES)return{digest:digest3,chars:input.text.length,bytes,degraded:!0,error:`lane output exceeds ${MAX_LANE_OUTPUT_STORED_BYTES} byte storage limit`};let batchDigest=digestText(input.batchId),laneDigest=digestText(input.laneId),ref=`${LANE_OUTPUT_REF_PREFIX}:${batchDigest}:${laneDigest}:${digest3}`,relPath=laneOutputRelativePath(ref),absPath=validateSwarmPath(directory,relPath),timestamp=new Date(now()).toISOString();try{if(existsSync104(absPath)){let existing=LaneOutputArtifactSchema.safeParse(JSON.parse(readFileSync72(absPath,"utf-8")));if(existing.success&&existing.data.digest===digest3)return{ref,digest:digest3,chars:existing.data.chars,bytes:existing.data.bytes,degraded:!1}}let artifact={schemaVersion:LANE_OUTPUT_SCHEMA_VERSION,ref,batchId:input.batchId,laneId:input.laneId,agent:input.agent,role:input.role,...input.sessionId?{sessionId:input.sessionId}:{},...input.parentSessionId?{parentSessionId:input.parentSessionId}:{},...input.mode?{mode:input.mode}:{},source:input.source,text:input.text,chars:input.text.length,bytes,digest:digest3,...input.messageCount!==void 0?{messageCount:input.messageCount}:{},...input.transcriptIncomplete!==void 0?{transcriptIncomplete:input.transcriptIncomplete}:{},createdAt:timestamp,updatedAt:timestamp};return writeAtomicJson(absPath,artifact),{ref,digest:digest3,chars:artifact.chars,bytes:artifact.bytes,degraded:!1}}catch(error93){return{digest:digest3,chars:input.text.length,bytes,degraded:!0,error:error93 instanceof Error?error93.message:"failed to store lane output artifact"}}}function readLaneOutput(directory,ref){if(!REF_RE.test(ref))return null;let absPath=validateSwarmPath(directory,laneOutputRelativePath(ref));if(!existsSync104(absPath))return null;let parsed;try{parsed=LaneOutputArtifactSchema.safeParse(JSON.parse(readFileSync72(absPath,"utf-8")))}catch{return null}if(!parsed.success||parsed.data.ref!==ref)return null;return{artifact:parsed.data}}function buildLaneOutputPreview(args2){let{text,ref,degraded,maxChars}=args2;if(!(text.length>maxChars)&&!degraded)return{output:text,output_chars:text.length,output_truncated:!1};let marker=buildPreviewMarker({omittedChars:Math.max(0,text.length-maxChars),ref,degraded:degraded===!0});if(text.length<=maxChars&°raded)return{output:`${text}${marker}`,output_chars:text.length,output_truncated:!1};let budget=Math.max(0,maxChars-marker.length),headChars=Math.ceil(budget/2),tailChars=Math.floor(budget/2),head2=text.slice(0,headChars),tail2=tailChars>0?text.slice(text.length-tailChars):"";return{output:`${head2}${marker}${tail2}`,output_chars:text.length,output_truncated:!0}}function paginateLaneOutput(text,offset,limit){let lines=text.length===0?[]:text.split(`
|
|
5873
5873
|
`),totalLines=lines.length,startLine=Math.max(0,offset);if(startLine>=totalLines)return{totalLines,startLine,endLine:totalLines,content:"",exhausted:!0};let endLine=Math.min(startLine+limit,totalLines);return{totalLines,startLine,endLine,content:lines.slice(startLine,endLine).join(`
|
|
5874
5874
|
`),exhausted:!1}}function buildPreviewMarker(args2){let retrieval=args2.ref?` retrieve_lane_output ref=${args2.ref} for full output.`:" no full output artifact is available; treat this lane as degraded.";return`
|
|
5875
5875
|
[... lane output preview omitted middle content.${args2.degraded?" Artifact storage degraded.":""}${retrieval} ...]
|
|
5876
|
-
`}function laneOutputRelativePath(ref){let[,batchDigest,laneDigest,outputDigest]=ref.split(":");return path184.join("lane-results",batchDigest,laneDigest,`${outputDigest}.json`)}var WINDOWS_RENAME_MAX_RETRIES3=3;function writeAtomicJson(absPath,value){mkdirSync46(path184.dirname(absPath),{recursive:!0});let tempFile=`${absPath}.tmp-${Date.now()}-${process.pid}`;try{writeFileSync28(tempFile,JSON.stringify(value,null,2),"utf-8");let lastRenameError;for(let attempt=0;attempt<WINDOWS_RENAME_MAX_RETRIES3;attempt++)try{renameSync30(tempFile,absPath),lastRenameError=void 0;break}catch(err){lastRenameError=err;let code=err.code;if(code!=="EEXIST"&&code!=="EBUSY"&&code!=="EPERM")break}if(lastRenameError)throw lastRenameError}finally{if(existsSync104(tempFile))try{unlinkSync27(tempFile)}catch{}}}function digestText(text){return createHash20("sha256").update(text).digest("hex")}init_pending_delegations();init_constants();init_schema();function createParallelDispatcher(config3){let limit=pLimit(config3.maxConcurrentTasks),activeSlots=new Map,slotCounter=0,shutdownCalled=!1;return{config:config3,dispatch(taskId){if(!config3.enabled)return{action:"reject",reason:"dispatcher_disabled"};if(shutdownCalled)return{action:"reject",reason:"dispatcher_shutdown"};if(activeSlots.size>=config3.maxConcurrentTasks)return{action:"defer",reason:"max_concurrent_tasks_reached"};let slotId=`slot-${++slotCounter}`,runId=`run-${taskId}-${slotId}`,slot={slotId,taskId,runId,startedAt:Date.now()};return activeSlots.set(slotId,slot),limit(async()=>{}),{action:"dispatch",reason:"slot_available",slot}},handles(){return[...activeSlots.values()].map((slot)=>({slotId:slot.slotId,taskId:slot.taskId,runId:slot.runId,cancel:()=>{activeSlots.delete(slot.slotId)}}))},releaseSlot(slotId){activeSlots.delete(slotId)},shutdown(){shutdownCalled=!0,activeSlots.clear(),limit.clearQueue()}}}init_state2();init_create_tool();var MAX_LANES=8,MAX_PROMPT_CHARS=80000,COMMON_PROMPT_SEPARATOR=`
|
|
5876
|
+
`}function laneOutputRelativePath(ref){let[,batchDigest,laneDigest,outputDigest]=ref.split(":");return path184.join("lane-results",batchDigest,laneDigest,`${outputDigest}.json`)}var WINDOWS_RENAME_MAX_RETRIES3=3;function writeAtomicJson(absPath,value){mkdirSync46(path184.dirname(absPath),{recursive:!0});let tempFile=`${absPath}.tmp-${Date.now()}-${process.pid}`;try{writeFileSync28(tempFile,JSON.stringify(value,null,2),"utf-8");let lastRenameError;for(let attempt=0;attempt<WINDOWS_RENAME_MAX_RETRIES3;attempt++)try{renameSync30(tempFile,absPath),lastRenameError=void 0;break}catch(err){lastRenameError=err;let code=err.code;if(code!=="EEXIST"&&code!=="EBUSY"&&code!=="EPERM")break}if(lastRenameError)throw lastRenameError}finally{if(existsSync104(tempFile))try{unlinkSync27(tempFile)}catch{}}}function digestText(text){return createHash20("sha256").update(text).digest("hex")}init_pending_delegations();init_constants();init_schema();function createParallelDispatcher(config3){let limit=pLimit(config3.maxConcurrentTasks),activeSlots=new Map,slotCounter=0,shutdownCalled=!1;return{config:config3,dispatch(taskId){if(!config3.enabled)return{action:"reject",reason:"dispatcher_disabled"};if(shutdownCalled)return{action:"reject",reason:"dispatcher_shutdown"};if(activeSlots.size>=config3.maxConcurrentTasks)return{action:"defer",reason:"max_concurrent_tasks_reached"};let slotId=`slot-${++slotCounter}`,runId=`run-${taskId}-${slotId}`,slot={slotId,taskId,runId,startedAt:Date.now()};return activeSlots.set(slotId,slot),limit(async()=>{}),{action:"dispatch",reason:"slot_available",slot}},handles(){return[...activeSlots.values()].map((slot)=>({slotId:slot.slotId,taskId:slot.taskId,runId:slot.runId,cancel:()=>{activeSlots.delete(slot.slotId)}}))},releaseSlot(slotId){activeSlots.delete(slotId)},shutdown(){shutdownCalled=!0,activeSlots.clear(),limit.clearQueue()}}}init_state2();init_logger();init_create_tool();var MAX_LANES=8,MAX_PROMPT_CHARS=80000,COMMON_PROMPT_SEPARATOR=`
|
|
5877
5877
|
|
|
5878
5878
|
`,DEFAULT_TIMEOUT_MS3=300000,DEFAULT_ASYNC_LAUNCH_TIMEOUT_MS=30000,MAX_TIMEOUT_MS2=1800000,MAX_LANE_OUTPUT_CHARS=20000,ASYNC_MESSAGE_FETCH_LIMIT=50,MAX_ERROR_CHARS=200,ERROR_TRUNCATION_SUFFIX="...",MAX_BATCH_ID_CHARS=120,DEFAULT_ASYNC_STALE_TIMEOUT_MS=1800000,DEFAULT_COLLECT_TIMEOUT_MS=DEFAULT_ASYNC_STALE_TIMEOUT_MS,MAX_COLLECT_TIMEOUT_MS=3600000,COLLECT_POLL_INTERVAL_MS=500,MAX_COLLECT_POLL_INTERVAL_MS=1e4,AGENT_NAME_SEPARATORS=["_","-"," "],EXPLORER_CANDIDATE_FORMAT_SUFFIX=`
|
|
5879
5879
|
|
|
@@ -5893,7 +5893,7 @@ micro-lane finds zero issues, emit its header followed by exactly:
|
|
|
5893
5893
|
Fill every CLEAN field; bare header-only micro output is UNATTESTED.
|
|
5894
5894
|
Do NOT use the default PROJECT/STRUCTURE output format for this dispatch.`,READ_ONLY_LANE_ROLES=new Set(["explorer","reviewer","critic","critic_oversight","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","critic_architecture_supervisor","sme","researcher","council_generalist","council_skeptic","council_domain_expert"]),READ_ONLY_TOOL_DENYLIST=[...new Set([...WRITE_TOOL_NAMES,"extract_code_blocks","multiedit","multi_edit","todo_write","save_plan","update_task_status","phase_complete","declare_scope","declare_council_criteria","submit_council_verdicts","submit_phase_council_verdicts","set_qa_gates","write_retro","write_drift_evidence","write_hallucination_evidence","write_mutation_evidence","knowledge_add","knowledge_remove","summarize_work","doc_scan"])],LaneSchema=exports_external.object({id:exports_external.string().min(1).max(80).regex(/^[A-Za-z0-9][A-Za-z0-9_.-]*$/).describe("Stable lane identifier, unique within this dispatch batch"),agent:exports_external.string().min(1).max(120).describe("Read-only swarm agent name, including any generated swarm prefix"),prompt:exports_external.string().min(1).max(MAX_PROMPT_CHARS).describe("Full lane prompt to send to the requested agent")}),DispatchLanesArgsSchema=exports_external.object({lanes:exports_external.array(LaneSchema).min(1).max(MAX_LANES).describe("Read-only lane specs to dispatch concurrently"),common_prompt:exports_external.string().min(1).regex(/\S/,"common_prompt must contain non-whitespace content").max(MAX_PROMPT_CHARS-COMMON_PROMPT_SEPARATOR.length-1).optional().describe("Optional shared context prepended to every lane prompt. Send large shared context (PR diff, obligation ledger, scope) ONCE here instead of inlining the same blob into each lane prompt; this keeps the tool-call payload small and avoids malformed/truncated tool-call JSON. Combined common_prompt + per-lane prompt must not exceed the per-lane character limit."),max_concurrent:exports_external.number().int().min(1).max(MAX_LANES).optional().describe("Maximum lanes in flight at once; defaults to lane count"),timeout_ms:exports_external.number().int().min(10).max(MAX_TIMEOUT_MS2).optional().describe("Per-lane timeout in milliseconds. For blocking dispatch this covers session create and prompt execution; for async dispatch this covers launch only, never lane runtime.")}),DispatchLanesAsyncArgsSchema=DispatchLanesArgsSchema.extend({launch_timeout_ms:exports_external.number().int().min(10).max(MAX_TIMEOUT_MS2).optional().describe("Async launch acceptance timeout in milliseconds. This only bounds session creation and promptAsync acceptance; it is never a lane runtime timeout. Deprecated alias: timeout_ms."),batch_id:exports_external.string().min(1).max(MAX_BATCH_ID_CHARS).regex(/^[A-Za-z0-9][A-Za-z0-9_.:-]*$/).optional().describe("Stable async batch id for later collection; generated when omitted"),mode:exports_external.string().min(1).max(80).optional().describe("Advisory workflow mode, such as deep-dive or swarm-pr-review"),pr_head_sha:exports_external.string().min(1).max(80).optional(),scope:exports_external.string().min(1).max(500).optional()}),CollectLaneResultsArgsSchema=exports_external.object({batch_id:exports_external.string().min(1).max(MAX_BATCH_ID_CHARS),wait:exports_external.boolean().optional().describe("Poll until all lanes settle or timeout"),timeout_ms:exports_external.number().int().min(0).max(MAX_COLLECT_TIMEOUT_MS).optional().describe("Total wait budget when wait=true"),include_pending:exports_external.boolean().optional().describe("Include pending/running lanes in lane_results. Defaults to true for non-blocking polls and false for wait=true joins."),cancel_pending:exports_external.boolean().optional().describe("Abort and mark pending/running lanes cancelled")}),_internals110={getSessionOps:()=>swarmState.opencodeClient?.session??null,getGeneratedAgentNames:()=>swarmState.generatedAgentNames,createParallelDispatcher,now:()=>Date.now(),sleep:sleep3};async function executeDispatchLanes(args2,directory,context={}){let parsed=DispatchLanesArgsSchema.safeParse(args2);if(!parsed.success)return failureResult({failure_class:"invalid_args",message:"Invalid dispatch_lanes arguments",errors:parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`)});let duplicateLaneIds=findDuplicateLaneIds(parsed.data.lanes);if(duplicateLaneIds.length>0)return failureResult({failure_class:"invalid_args",message:"Lane IDs must be unique within one dispatch_lanes batch",errors:duplicateLaneIds.map((id)=>`Duplicate lane id: ${id}`)});let session=_internals110.getSessionOps();if(!session)return failureResult({failure_class:"no_client",message:"OpenCode session client is not available"});let common=applyCommonPrompt(parsed.data.lanes,parsed.data.common_prompt);if(!common.ok)return failureResult({failure_class:"invalid_args",message:"Invalid dispatch_lanes arguments",errors:common.errors});let lanes=applyExplorerFormatSuffix(common.lanes),maxConcurrent=Math.min(parsed.data.max_concurrent??lanes.length,lanes.length,MAX_LANES),timeoutMs=parsed.data.timeout_ms??DEFAULT_TIMEOUT_MS3,dispatcher=_internals110.createParallelDispatcher({enabled:!0,maxConcurrentTasks:maxConcurrent,evidenceLockTimeoutMs:0}),limit=pLimit(maxConcurrent);try{let laneResults=await Promise.all(lanes.map((lane)=>limit(()=>runLane(session,dispatcher,lane,directory,timeoutMs,context))));return buildResult(laneResults,maxConcurrent,timeoutMs)}finally{dispatcher.shutdown()}}async function executeDispatchLanesAsync(args2,directory,context={}){let parsed=DispatchLanesAsyncArgsSchema.safeParse(args2);if(!parsed.success)return asyncFailureResult({failure_class:"invalid_args",message:"Invalid dispatch_lanes_async arguments",errors:parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`)});let duplicateLaneIds=findDuplicateLaneIds(parsed.data.lanes);if(duplicateLaneIds.length>0)return asyncFailureResult({failure_class:"invalid_args",message:"Lane IDs must be unique within one dispatch_lanes_async batch",errors:duplicateLaneIds.map((id)=>`Duplicate lane id: ${id}`)});let session=_internals110.getSessionOps();if(!session||typeof session.promptAsync!=="function")return asyncFailureResult({failure_class:"no_client",message:"OpenCode session promptAsync client is not available"});let common=applyCommonPrompt(parsed.data.lanes,parsed.data.common_prompt);if(!common.ok)return asyncFailureResult({failure_class:"invalid_args",message:"Invalid dispatch_lanes_async arguments",errors:common.errors});let lanes=applyExplorerFormatSuffix(common.lanes),batchId=parsed.data.batch_id??makeBatchId();if(findByBatchId(directory,batchId).length>0)return asyncFailureResult({failure_class:"invalid_args",message:`Async lane batch already exists: ${batchId}`,errors:[`batch_id must be unique: ${batchId}`]});let maxConcurrent=Math.min(parsed.data.max_concurrent??lanes.length,lanes.length,MAX_LANES),launchTimeoutMs=parsed.data.launch_timeout_ms??parsed.data.timeout_ms??DEFAULT_ASYNC_LAUNCH_TIMEOUT_MS,dispatcher=_internals110.createParallelDispatcher({enabled:!0,maxConcurrentTasks:maxConcurrent,evidenceLockTimeoutMs:0}),limit=pLimit(maxConcurrent);try{let laneResults=await Promise.all(lanes.map((lane)=>limit(()=>launchAsyncLane({session,dispatcher,lane,directory,timeoutMs:launchTimeoutMs,context,batchId,mode:parsed.data.mode,prHeadSha:parsed.data.pr_head_sha,scope:parsed.data.scope})))),failed=laneResults.filter((lane)=>lane.status==="failed"),rejected=laneResults.filter((lane)=>lane.status==="rejected"),pending=laneResults.filter((lane)=>lane.status==="pending");return{success:failed.length===0&&rejected.length===0,batch_id:batchId,dispatched:laneResults.length,pending:pending.length,failed:failed.length,rejected:rejected.length,max_concurrent:maxConcurrent,launch_timeout_ms:launchTimeoutMs,timeout_ms:launchTimeoutMs,lane_results:laneResults}}finally{dispatcher.shutdown()}}async function executeCollectLaneResults(args2,directory,context={}){let parsed=CollectLaneResultsArgsSchema.safeParse(args2);if(!parsed.success)return collectFailureResult({failure_class:"invalid_args",batch_id:"",message:"Invalid collect_lane_results arguments",errors:parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`)});let session=_internals110.getSessionOps();if(!session||typeof session.messages!=="function")return collectFailureResult({failure_class:"no_client",batch_id:parsed.data.batch_id,message:"OpenCode session messages client is not available"});let timeoutMs=parsed.data.timeout_ms??DEFAULT_COLLECT_TIMEOUT_MS,deadline=_internals110.now()+timeoutMs,batchFilter=context.sessionID!==void 0?{parentSessionId:context.sessionID}:void 0,records=findByBatchId(directory,parsed.data.batch_id,batchFilter);if(records.length===0)return collectFailureResult({failure_class:"not_found",batch_id:parsed.data.batch_id,message:`No async lane batch found for ${parsed.data.batch_id}`});let keepPolling=!0,pollIntervalMs=COLLECT_POLL_INTERVAL_MS;while(keepPolling){if(await collectOnce(session,directory,records,parsed.data.cancel_pending===!0),await sweepStaleAsyncLaneRecords(session,directory,records,DEFAULT_ASYNC_STALE_TIMEOUT_MS),records=findByBatchId(directory,parsed.data.batch_id,batchFilter),allSettled(records)||parsed.data.wait!==!0){keepPolling=!1;continue}if(_internals110.now()>=deadline){keepPolling=!1;continue}await _internals110.sleep(Math.min(pollIntervalMs,Math.max(0,deadline-_internals110.now()))),pollIntervalMs=nextCollectPollInterval(pollIntervalMs)}return buildCollectResult(parsed.data.batch_id,records,parsed.data.include_pending??parsed.data.wait!==!0)}async function launchAsyncLane(args2){let validation2=validateLaneAgent(args2.lane.agent,args2.context),role=validation2.role,startedAt=isoNow();if(!validation2.ok)return{id:args2.lane.id,agent:args2.lane.agent,role,status:"rejected",started_at:startedAt,completed_at:isoNow(),error:validation2.error};let decision=args2.dispatcher.dispatch(args2.lane.id);if(decision.action!=="dispatch")return{id:args2.lane.id,agent:args2.lane.agent,role,status:"failed",started_at:startedAt,completed_at:isoNow(),error:`dispatcher ${decision.action}: ${decision.reason}`};try{let createTimeoutMessage=`Lane "${args2.lane.id}" session.create timed out after ${args2.timeoutMs}ms`,createPromise=args2.session.create(buildLaneSessionCreateArgs(args2.directory,args2.lane,args2.context)),createTimedOut=!1;createPromise.then((createResult2)=>{if(createTimedOut&&createResult2.data?.id)scheduleSessionCleanup(args2.session,createResult2.data.id)}).catch(()=>{return});let createResult=await withTimeout2(createPromise,args2.timeoutMs,createTimeoutMessage).catch((error93)=>{if(formatError3(error93)===createTimeoutMessage)createTimedOut=!0;throw error93}),sessionId=createResult.data?.id;if(!sessionId)return failedLane(args2.lane,role,startedAt,`session.create failed: ${formatError3(createResult.error)}`,decision.slot.slotId,decision.slot.runId);if(!await recordPendingDelegation(args2.directory,{correlationId:sessionId,jobId:null,subagentSessionId:sessionId,parentSessionId:args2.context.sessionID??`dispatch_lanes_async:${args2.batchId}`,callID:args2.batchId,normalizedAgent:role,swarmPrefixedAgent:args2.lane.agent,planTaskId:null,evidenceTaskId:null,batchId:args2.batchId,laneId:args2.lane.id,mode:args2.mode??"advisory",promptHash:promptHash(args2.lane,args2.directory,args2.batchId),workspace:{directory:args2.directory,gitHead:null,dirtyHash:null,prHeadSha:args2.prHeadSha??null,scope:args2.scope??null},generation:1}))return cleanupAsyncLaunchSession(args2.session,sessionId),failedLane(args2.lane,role,startedAt,"Failed to record async lane in background delegation ledger",decision.slot.slotId,decision.slot.runId);return scheduleAsyncLanePrompt({session:args2.session,directory:args2.directory,sessionId,lane:args2.lane,timeoutMs:args2.timeoutMs}),{id:args2.lane.id,agent:args2.lane.agent,role,status:"pending",session_id:sessionId,slot_id:decision.slot.slotId,run_id:decision.slot.runId,started_at:startedAt,completed_at:isoNow()}}catch(error93){return failedLane(args2.lane,role,startedAt,formatError3(error93),decision.slot.slotId,decision.slot.runId)}finally{args2.dispatcher.releaseSlot(decision.slot.slotId)}}async function collectOnce(session,directory,records,cancelPending){for(let record3 of records){if(record3.status!=="pending"&&record3.status!=="running")continue;if(cancelPending){if(typeof session.abort==="function")await session.abort({path:{id:record3.subagentSessionId}}).catch(()=>{return});await appendDelegationTransition(directory,record3.correlationId,{status:"cancelled"});continue}if(!await isLaneReadyForCollection(session,directory,record3.subagentSessionId))continue;let messages;try{messages=await session.messages({path:{id:record3.subagentSessionId},query:{directory,limit:ASYNC_MESSAGE_FETCH_LIMIT}})}catch{continue}if(!messages.data)continue;let transcript=extractAssistantTranscript(messages.data);if(!transcript.text)continue;let output=prepareLaneOutput({directory,batchId:record3.batchId??record3.callID,laneId:record3.laneId??record3.correlationId,agent:record3.swarmPrefixedAgent,role:record3.normalizedAgent,sessionId:record3.subagentSessionId,parentSessionId:record3.parentSessionId,mode:record3.mode,source:"collect_lane_results",text:transcript.text,messageCount:transcript.messageCount,transcriptIncomplete:transcript.transcriptIncomplete});await appendDelegationTransition(directory,record3.correlationId,{status:"completed",result:{text:output.output,chars:output.output_chars,truncated:output.output_truncated,digest:output.output_digest,...output.output_ref?{outputRef:output.output_ref}:{},outputPreviewChars:output.output.length,...output.output_degraded!==void 0?{outputDegraded:output.output_degraded}:{},...output.output_artifact_error?{outputArtifactError:output.output_artifact_error}:{},...output.transcript_incomplete!==void 0?{transcriptIncomplete:output.transcript_incomplete}:{},messageCount:transcript.messageCount}})}}function scheduleAsyncLanePrompt(args2){queueMicrotask(()=>{startAsyncLanePrompt(args2).catch(async(error93)=>{let message=formatError3(error93);await appendAsyncLaneLaunchError(args2.directory,args2.session,args2.sessionId,message)})})}async function startAsyncLanePrompt(args2){let promptController=new AbortController,promptResult;try{promptResult=await withTimeout2(args2.session.promptAsync({path:{id:args2.sessionId},query:{directory:args2.directory},body:{agent:args2.lane.agent,tools:buildReadOnlyTools(),parts:[{type:"text",text:args2.lane.prompt}]},signal:promptController.signal}),args2.timeoutMs,`Lane "${args2.lane.id}" session.promptAsync launch timed out after ${args2.timeoutMs}ms`,promptController)}catch(error93){await appendAsyncLaneLaunchError(args2.directory,args2.session,args2.sessionId,formatError3(error93));return}if(promptResult.error){await appendAsyncLaneLaunchError(args2.directory,args2.session,args2.sessionId,`session.promptAsync launch failed: ${formatError3(promptResult.error)}`);return}await appendDelegationTransition(args2.directory,args2.sessionId,{status:"running"})}async function appendAsyncLaneLaunchError(directory,session,sessionId,message){await appendDelegationTransition(directory,sessionId,{status:"error",result:{error:message,chars:message.length,truncated:!1,digest:digestText2(message)}}),cleanupAsyncLaunchSession(session,sessionId)}async function isLaneReadyForCollection(session,directory,sessionId){if(typeof session.status!=="function")return!0;try{let status=await session.status({query:{directory}});if(status.error||!status.data)return!1;let current=status.data[sessionId];return current===void 0||current.type==="idle"}catch{return!1}}async function sweepStaleAsyncLaneRecords(session,directory,records,staleTimeoutMs){if(staleTimeoutMs<=0)return;let now=_internals110.now();for(let record3 of records){if(record3.status!=="pending"&&record3.status!=="running"&&record3.status!=="ingestion_error")continue;if(now-record3.updatedAt<=staleTimeoutMs)continue;if(!await isLaneReadyForCollection(session,directory,record3.subagentSessionId))continue;await appendDelegationTransition(directory,record3.correlationId,{status:"stale"})}}function extractAssistantTranscript(messages){let assistantTexts=[];for(let message of messages){if(message.info?.role!=="assistant")continue;let text=extractText3(message.parts);if(text.trim().length>0)assistantTexts.push(text)}return{text:assistantTexts.join(`
|
|
5895
5895
|
|
|
5896
|
-
`),messageCount:assistantTexts.length,transcriptIncomplete:messages.length>=ASYNC_MESSAGE_FETCH_LIMIT}}function nextCollectPollInterval(currentMs){if(currentMs<=0)return COLLECT_POLL_INTERVAL_MS;return Math.min(currentMs*2,MAX_COLLECT_POLL_INTERVAL_MS)}async function runLane(session,dispatcher,lane,directory,timeoutMs,context){let validation2=validateLaneAgent(lane.agent,context),role=validation2.role,startedAt=isoNow();if(!validation2.ok)return{id:lane.id,agent:lane.agent,role,status:"rejected",started_at:startedAt,completed_at:isoNow(),error:validation2.error};let decision=dispatcher.dispatch(lane.id);if(decision.action!=="dispatch")return{id:lane.id,agent:lane.agent,role,status:"failed",started_at:startedAt,completed_at:isoNow(),error:`dispatcher ${decision.action}: ${decision.reason}`};let promptController=new AbortController,sessionId;try{let createTimeoutMessage=`Lane "${lane.id}" session.create timed out after ${timeoutMs}ms`,createPromise=session.create(buildLaneSessionCreateArgs(directory,lane,context)),createTimedOut=!1;createPromise.then((createResult2)=>{if(createTimedOut&&createResult2.data?.id)scheduleSessionCleanup(session,createResult2.data.id)}).catch(()=>{return});let createResult=await withTimeout2(createPromise,timeoutMs,createTimeoutMessage).catch((error93)=>{if(formatError3(error93)===createTimeoutMessage)createTimedOut=!0;throw error93});if(!createResult.data?.id)return failedLane(lane,role,startedAt,`session.create failed: ${formatError3(createResult.error)}`,decision.slot.slotId,decision.slot.runId);sessionId=createResult.data.id;let promptResult=await withTimeout2(session.prompt({path:{id:sessionId},body:{agent:lane.agent,tools:buildReadOnlyTools(),parts:[{type:"text",text:lane.prompt}]},signal:promptController.signal}),timeoutMs,`Lane "${lane.id}" session.prompt timed out after ${timeoutMs}ms`,promptController);if(!promptResult.data)return failedLane(lane,role,startedAt,`session.prompt failed: ${formatError3(promptResult.error)}`,decision.slot.slotId,decision.slot.runId,sessionId);let laneOutput=prepareLaneOutput({directory,batchId:`blocking:${sessionId}`,laneId:lane.id,agent:lane.agent,role,sessionId,parentSessionId:context.sessionID,source:"dispatch_lanes",text:extractText3(promptResult.data.parts)});return{id:lane.id,agent:lane.agent,role,status:"completed",session_id:sessionId,slot_id:decision.slot.slotId,run_id:decision.slot.runId,started_at:startedAt,completed_at:isoNow(),...laneOutput}}catch(error93){return failedLane(lane,role,startedAt,formatError3(error93),decision.slot.slotId,decision.slot.runId,sessionId)}finally{if(dispatcher.releaseSlot(decision.slot.slotId),promptController.abort(),sessionId)scheduleSessionCleanup(session,sessionId)}}function buildResult(laneResults,maxConcurrent,timeoutMs){let completed=laneResults.filter((lane)=>lane.status==="completed"),failed=laneResults.filter((lane)=>lane.status==="failed"),rejected=laneResults.filter((lane)=>lane.status==="rejected");return{success:failed.length===0&&rejected.length===0,dispatched:laneResults.length,completed:completed.length,failed:failed.length,rejected:rejected.length,max_concurrent:maxConcurrent,timeout_ms:timeoutMs,lane_results:laneResults}}function buildCollectResult(batchId,records,includePending){let laneResults=records.filter((record3)=>includePending||record3.status!=="pending"&&record3.status!=="running").map(recordToLaneResult),completed=records.filter((record3)=>record3.status==="completed"),failed=records.filter((record3)=>record3.status==="error"||record3.status==="ingestion_error"),cancelled=records.filter((record3)=>record3.status==="cancelled"),stale=records.filter((record3)=>record3.status==="stale"),pending=records.filter((record3)=>record3.status==="pending"||record3.status==="running"),consumed=records.filter((record3)=>record3.status==="consumed");return{success:pending.length===0&&failed.length===0&&cancelled.length===0&&stale.length===0,batch_id:batchId,total:records.length,completed:completed.length,failed:failed.length,cancelled:cancelled.length,stale:stale.length,pending:pending.length,consumed:consumed.length,all_settled:pending.length===0,lane_results:laneResults}}function recordToLaneResult(record3){let status=record3.status==="error"?"failed":record3.status==="ingestion_error"?"failed":record3.status==="running"?"pending":record3.status;return{id:record3.laneId??record3.correlationId,agent:record3.swarmPrefixedAgent,role:record3.normalizedAgent,status,session_id:record3.subagentSessionId,started_at:new Date(record3.createdAt).toISOString(),completed_at:new Date(record3.completedAt??record3.updatedAt).toISOString(),...record3.result?.text!==void 0?{output:record3.result.text,output_chars:record3.result.chars,output_truncated:record3.result.truncated,output_digest:record3.result.digest,...record3.result.outputRef?{output_ref:record3.result.outputRef}:{},...record3.result.outputPreviewChars!==void 0?{output_preview_chars:record3.result.outputPreviewChars}:{},...record3.result.outputDegraded!==void 0?{output_degraded:record3.result.outputDegraded}:{},...record3.result.outputArtifactError?{output_artifact_error:record3.result.outputArtifactError}:{},...record3.result.transcriptIncomplete!==void 0?{transcript_incomplete:record3.result.transcriptIncomplete}:{},...record3.result.messageCount!==void 0?{message_count:record3.result.messageCount}:{}}:{},...record3.result?.error!==void 0?{error:record3.result.error}:{}}}function allSettled(records){return records.every((record3)=>record3.status!=="pending"&&record3.status!=="running")}function failedLane(lane,role,startedAt,error93,slotId,runId,sessionId){return{id:lane.id,agent:lane.agent,role,status:"failed",session_id:sessionId,slot_id:slotId,run_id:runId,started_at:startedAt,completed_at:isoNow(),error:error93}}function validateLaneAgent(agent,context){let generatedAgentNames=_internals110.getGeneratedAgentNames(),role=resolveGeneratedAgentRole(agent,generatedAgentNames);if(!isKnownCanonicalRole(role))return{ok:!1,role,error:`Agent "${agent}" is not registered as a generated swarm agent or canonical role`};if(!READ_ONLY_LANE_ROLES.has(role))return{ok:!1,role,error:`Agent role "${role}" is not allowed for read-only lane dispatch`};let callerPrefix=context.callerAgent?getGeneratedAgentPrefix(context.callerAgent,generatedAgentNames):null;if(callerPrefix){if(getGeneratedAgentPrefix(agent,generatedAgentNames)!==callerPrefix)return{ok:!1,role,error:`Agent "${agent}" does not match caller swarm prefix "${callerPrefix}"`}}return{ok:!0,role}}function getGeneratedAgentPrefix(agent,generatedAgentNames){let role=resolveGeneratedAgentRole(agent,generatedAgentNames);if(!isKnownCanonicalRole(role))return null;let normalized=agent.toLowerCase();if(normalized===role)return null;for(let separator of AGENT_NAME_SEPARATORS){let suffix=`${separator}${role}`;if(normalized.endsWith(suffix))return normalized.slice(0,-suffix.length)}return null}function buildReadOnlyTools(){let tools={};for(let toolName of READ_ONLY_TOOL_DENYLIST)tools[toolName]=!1;return tools.write=!1,tools.edit=!1,tools.patch=!1,tools}function prepareLaneOutput(args2){let stored=storeLaneOutput(args2.directory,{batchId:args2.batchId,laneId:args2.laneId,agent:args2.agent,role:args2.role,sessionId:args2.sessionId,parentSessionId:args2.parentSessionId,mode:args2.mode,source:args2.source,text:args2.text,messageCount:args2.messageCount,transcriptIncomplete:args2.transcriptIncomplete}),preview=buildLaneOutputPreview({text:args2.text,ref:stored.ref,degraded:stored.degraded,maxChars:MAX_LANE_OUTPUT_CHARS});return{...preview,output_ref:stored.ref,output_digest:stored.digest,output_preview_chars:preview.output.length,...stored.degraded?{output_degraded:!0}:{},...stored.error?{output_artifact_error:stored.error}:{},...args2.transcriptIncomplete!==void 0?{transcript_incomplete:args2.transcriptIncomplete}:{},...args2.messageCount!==void 0?{message_count:args2.messageCount}:{}}}function failureResult(args2){return{success:!1,failure_class:args2.failure_class,message:args2.message,dispatched:0,completed:0,failed:0,rejected:0,max_concurrent:0,timeout_ms:0,lane_results:[],errors:args2.errors}}function asyncFailureResult(args2){return{success:!1,failure_class:args2.failure_class,message:args2.message,batch_id:null,dispatched:0,pending:0,failed:0,rejected:0,max_concurrent:0,launch_timeout_ms:0,timeout_ms:0,lane_results:[],errors:args2.errors}}function collectFailureResult(args2){return{success:!1,failure_class:args2.failure_class,message:args2.message,batch_id:args2.batch_id,total:0,completed:0,failed:0,cancelled:0,stale:0,pending:0,consumed:0,all_settled:!1,lane_results:[],errors:args2.errors}}function applyCommonPrompt(lanes,commonPrompt){if(!commonPrompt)return{ok:!0,lanes:[...lanes]};let errors5=[],merged=lanes.map((lane)=>{let prompt=`${commonPrompt}${COMMON_PROMPT_SEPARATOR}${lane.prompt}`;if(prompt.length>MAX_PROMPT_CHARS)errors5.push(`Lane "${lane.id}" combined common_prompt + prompt is ${prompt.length} chars (common_prompt ${commonPrompt.length} + separator ${COMMON_PROMPT_SEPARATOR.length} + lane prompt ${lane.prompt.length}; max ${MAX_PROMPT_CHARS})`);return{...lane,prompt}});if(errors5.length>0)return{ok:!1,errors:errors5};return{ok:!0,lanes:merged}}function applyExplorerFormatSuffix(lanes){let generatedAgentNames=_internals110.getGeneratedAgentNames();return lanes.map((lane)=>{if(resolveGeneratedAgentRole(lane.agent,generatedAgentNames)!=="explorer")return lane;if(lane.prompt.includes("[CANDIDATE]"))return lane;let prompt=`${lane.prompt}${EXPLORER_CANDIDATE_FORMAT_SUFFIX}`;if(prompt.length>MAX_PROMPT_CHARS)return console.warn(`[dispatch-lanes] applyExplorerFormatSuffix: lane "${lane.id}" prompt too long (${lane.prompt.length} chars + suffix = ${prompt.length}, max ${MAX_PROMPT_CHARS}); `+"format enforcement skipped — explorer may not emit [CANDIDATE] rows"),lane;return{...lane,prompt}})}function findDuplicateLaneIds(lanes){let seen=new Set,duplicates=new Set;for(let lane of lanes){if(seen.has(lane.id))duplicates.add(lane.id);seen.add(lane.id)}return[...duplicates]}function scheduleSessionCleanup(session,sessionId){session.delete({path:{id:sessionId}}).catch(()=>{return})}function cleanupAsyncLaunchSession(session,sessionId){if(typeof session.abort==="function")session.abort({path:{id:sessionId}}).catch(()=>{return});scheduleSessionCleanup(session,sessionId)}async function withTimeout2(promise3,timeoutMs,message,controller){let timeout;try{return await Promise.race([promise3,new Promise((_,reject)=>{timeout=setTimeout(()=>{controller?.abort(),reject(Error(message))},timeoutMs)})])}finally{if(timeout)clearTimeout(timeout)}}function extractText3(parts){if(!Array.isArray(parts))return"";return parts.filter((part)=>part.type==="text").map((part)=>part.text??"").join(`
|
|
5896
|
+
`),messageCount:assistantTexts.length,transcriptIncomplete:messages.length>=ASYNC_MESSAGE_FETCH_LIMIT}}function nextCollectPollInterval(currentMs){if(currentMs<=0)return COLLECT_POLL_INTERVAL_MS;return Math.min(currentMs*2,MAX_COLLECT_POLL_INTERVAL_MS)}async function runLane(session,dispatcher,lane,directory,timeoutMs,context){let validation2=validateLaneAgent(lane.agent,context),role=validation2.role,startedAt=isoNow();if(!validation2.ok)return{id:lane.id,agent:lane.agent,role,status:"rejected",started_at:startedAt,completed_at:isoNow(),error:validation2.error};let decision=dispatcher.dispatch(lane.id);if(decision.action!=="dispatch")return{id:lane.id,agent:lane.agent,role,status:"failed",started_at:startedAt,completed_at:isoNow(),error:`dispatcher ${decision.action}: ${decision.reason}`};let promptController=new AbortController,sessionId;try{let createTimeoutMessage=`Lane "${lane.id}" session.create timed out after ${timeoutMs}ms`,createPromise=session.create(buildLaneSessionCreateArgs(directory,lane,context)),createTimedOut=!1;createPromise.then((createResult2)=>{if(createTimedOut&&createResult2.data?.id)scheduleSessionCleanup(session,createResult2.data.id)}).catch(()=>{return});let createResult=await withTimeout2(createPromise,timeoutMs,createTimeoutMessage).catch((error93)=>{if(formatError3(error93)===createTimeoutMessage)createTimedOut=!0;throw error93});if(!createResult.data?.id)return failedLane(lane,role,startedAt,`session.create failed: ${formatError3(createResult.error)}`,decision.slot.slotId,decision.slot.runId);sessionId=createResult.data.id;let promptResult=await withTimeout2(session.prompt({path:{id:sessionId},body:{agent:lane.agent,tools:buildReadOnlyTools(),parts:[{type:"text",text:lane.prompt}]},signal:promptController.signal}),timeoutMs,`Lane "${lane.id}" session.prompt timed out after ${timeoutMs}ms`,promptController);if(!promptResult.data)return failedLane(lane,role,startedAt,`session.prompt failed: ${formatError3(promptResult.error)}`,decision.slot.slotId,decision.slot.runId,sessionId);let laneOutput=prepareLaneOutput({directory,batchId:`blocking:${sessionId}`,laneId:lane.id,agent:lane.agent,role,sessionId,parentSessionId:context.sessionID,source:"dispatch_lanes",text:extractText3(promptResult.data.parts)});return{id:lane.id,agent:lane.agent,role,status:"completed",session_id:sessionId,slot_id:decision.slot.slotId,run_id:decision.slot.runId,started_at:startedAt,completed_at:isoNow(),...laneOutput}}catch(error93){return failedLane(lane,role,startedAt,formatError3(error93),decision.slot.slotId,decision.slot.runId,sessionId)}finally{if(dispatcher.releaseSlot(decision.slot.slotId),promptController.abort(),sessionId)scheduleSessionCleanup(session,sessionId)}}function buildResult(laneResults,maxConcurrent,timeoutMs){let completed=laneResults.filter((lane)=>lane.status==="completed"),failed=laneResults.filter((lane)=>lane.status==="failed"),rejected=laneResults.filter((lane)=>lane.status==="rejected");return{success:failed.length===0&&rejected.length===0,dispatched:laneResults.length,completed:completed.length,failed:failed.length,rejected:rejected.length,max_concurrent:maxConcurrent,timeout_ms:timeoutMs,lane_results:laneResults}}function buildCollectResult(batchId,records,includePending){let laneResults=records.filter((record3)=>includePending||record3.status!=="pending"&&record3.status!=="running").map(recordToLaneResult),completed=records.filter((record3)=>record3.status==="completed"),failed=records.filter((record3)=>record3.status==="error"||record3.status==="ingestion_error"),cancelled=records.filter((record3)=>record3.status==="cancelled"),stale=records.filter((record3)=>record3.status==="stale"),pending=records.filter((record3)=>record3.status==="pending"||record3.status==="running"),consumed=records.filter((record3)=>record3.status==="consumed");return{success:pending.length===0&&failed.length===0&&cancelled.length===0&&stale.length===0,batch_id:batchId,total:records.length,completed:completed.length,failed:failed.length,cancelled:cancelled.length,stale:stale.length,pending:pending.length,consumed:consumed.length,all_settled:pending.length===0,lane_results:laneResults}}function recordToLaneResult(record3){let status=record3.status==="error"?"failed":record3.status==="ingestion_error"?"failed":record3.status==="running"?"pending":record3.status;return{id:record3.laneId??record3.correlationId,agent:record3.swarmPrefixedAgent,role:record3.normalizedAgent,status,session_id:record3.subagentSessionId,started_at:new Date(record3.createdAt).toISOString(),completed_at:new Date(record3.completedAt??record3.updatedAt).toISOString(),...record3.result?.text!==void 0?{output:record3.result.text,output_chars:record3.result.chars,output_truncated:record3.result.truncated,output_digest:record3.result.digest,...record3.result.outputRef?{output_ref:record3.result.outputRef}:{},...record3.result.outputPreviewChars!==void 0?{output_preview_chars:record3.result.outputPreviewChars}:{},...record3.result.outputDegraded!==void 0?{output_degraded:record3.result.outputDegraded}:{},...record3.result.outputArtifactError?{output_artifact_error:record3.result.outputArtifactError}:{},...record3.result.transcriptIncomplete!==void 0?{transcript_incomplete:record3.result.transcriptIncomplete}:{},...record3.result.messageCount!==void 0?{message_count:record3.result.messageCount}:{}}:{},...record3.result?.error!==void 0?{error:record3.result.error}:{}}}function allSettled(records){return records.every((record3)=>record3.status!=="pending"&&record3.status!=="running")}function failedLane(lane,role,startedAt,error93,slotId,runId,sessionId){return{id:lane.id,agent:lane.agent,role,status:"failed",session_id:sessionId,slot_id:slotId,run_id:runId,started_at:startedAt,completed_at:isoNow(),error:error93}}function validateLaneAgent(agent,context){let generatedAgentNames=_internals110.getGeneratedAgentNames(),role=resolveGeneratedAgentRole(agent,generatedAgentNames);if(!isKnownCanonicalRole(role))return{ok:!1,role,error:`Agent "${agent}" is not registered as a generated swarm agent or canonical role`};if(!READ_ONLY_LANE_ROLES.has(role))return{ok:!1,role,error:`Agent role "${role}" is not allowed for read-only lane dispatch`};let callerPrefix=context.callerAgent?getGeneratedAgentPrefix(context.callerAgent,generatedAgentNames):null;if(callerPrefix){if(getGeneratedAgentPrefix(agent,generatedAgentNames)!==callerPrefix)return{ok:!1,role,error:`Agent "${agent}" does not match caller swarm prefix "${callerPrefix}"`}}return{ok:!0,role}}function getGeneratedAgentPrefix(agent,generatedAgentNames){let role=resolveGeneratedAgentRole(agent,generatedAgentNames);if(!isKnownCanonicalRole(role))return null;let normalized=agent.toLowerCase();if(normalized===role)return null;for(let separator of AGENT_NAME_SEPARATORS){let suffix=`${separator}${role}`;if(normalized.endsWith(suffix))return normalized.slice(0,-suffix.length)}return null}function buildReadOnlyTools(){let tools={};for(let toolName of READ_ONLY_TOOL_DENYLIST)tools[toolName]=!1;return tools.write=!1,tools.edit=!1,tools.patch=!1,tools}function prepareLaneOutput(args2){let stored=storeLaneOutput(args2.directory,{batchId:args2.batchId,laneId:args2.laneId,agent:args2.agent,role:args2.role,sessionId:args2.sessionId,parentSessionId:args2.parentSessionId,mode:args2.mode,source:args2.source,text:args2.text,messageCount:args2.messageCount,transcriptIncomplete:args2.transcriptIncomplete}),preview=buildLaneOutputPreview({text:args2.text,ref:stored.ref,degraded:stored.degraded,maxChars:MAX_LANE_OUTPUT_CHARS});return{...preview,output_ref:stored.ref,output_digest:stored.digest,output_preview_chars:preview.output.length,...stored.degraded?{output_degraded:!0}:{},...stored.error?{output_artifact_error:stored.error}:{},...args2.transcriptIncomplete!==void 0?{transcript_incomplete:args2.transcriptIncomplete}:{},...args2.messageCount!==void 0?{message_count:args2.messageCount}:{}}}function failureResult(args2){return{success:!1,failure_class:args2.failure_class,message:args2.message,dispatched:0,completed:0,failed:0,rejected:0,max_concurrent:0,timeout_ms:0,lane_results:[],errors:args2.errors}}function asyncFailureResult(args2){return{success:!1,failure_class:args2.failure_class,message:args2.message,batch_id:null,dispatched:0,pending:0,failed:0,rejected:0,max_concurrent:0,launch_timeout_ms:0,timeout_ms:0,lane_results:[],errors:args2.errors}}function collectFailureResult(args2){return{success:!1,failure_class:args2.failure_class,message:args2.message,batch_id:args2.batch_id,total:0,completed:0,failed:0,cancelled:0,stale:0,pending:0,consumed:0,all_settled:!1,lane_results:[],errors:args2.errors}}function applyCommonPrompt(lanes,commonPrompt){if(!commonPrompt)return{ok:!0,lanes:[...lanes]};let errors5=[],merged=lanes.map((lane)=>{let prompt=`${commonPrompt}${COMMON_PROMPT_SEPARATOR}${lane.prompt}`;if(prompt.length>MAX_PROMPT_CHARS)errors5.push(`Lane "${lane.id}" combined common_prompt + prompt is ${prompt.length} chars (common_prompt ${commonPrompt.length} + separator ${COMMON_PROMPT_SEPARATOR.length} + lane prompt ${lane.prompt.length}; max ${MAX_PROMPT_CHARS})`);return{...lane,prompt}});if(errors5.length>0)return{ok:!1,errors:errors5};return{ok:!0,lanes:merged}}function applyExplorerFormatSuffix(lanes){let generatedAgentNames=_internals110.getGeneratedAgentNames();return lanes.map((lane)=>{if(resolveGeneratedAgentRole(lane.agent,generatedAgentNames)!=="explorer")return lane;if(lane.prompt.includes("[CANDIDATE]"))return lane;let prompt=`${lane.prompt}${EXPLORER_CANDIDATE_FORMAT_SUFFIX}`;if(prompt.length>MAX_PROMPT_CHARS)return log(`[dispatch-lanes] applyExplorerFormatSuffix: lane "${lane.id}" prompt too long (${lane.prompt.length} chars + suffix = ${prompt.length}, max ${MAX_PROMPT_CHARS}); `+"format enforcement skipped — explorer may not emit [CANDIDATE] rows"),lane;return{...lane,prompt}})}function findDuplicateLaneIds(lanes){let seen=new Set,duplicates=new Set;for(let lane of lanes){if(seen.has(lane.id))duplicates.add(lane.id);seen.add(lane.id)}return[...duplicates]}function scheduleSessionCleanup(session,sessionId){session.delete({path:{id:sessionId}}).catch(()=>{return})}function cleanupAsyncLaunchSession(session,sessionId){if(typeof session.abort==="function")session.abort({path:{id:sessionId}}).catch(()=>{return});scheduleSessionCleanup(session,sessionId)}async function withTimeout2(promise3,timeoutMs,message,controller){let timeout;try{return await Promise.race([promise3,new Promise((_,reject)=>{timeout=setTimeout(()=>{controller?.abort(),reject(Error(message))},timeoutMs)})])}finally{if(timeout)clearTimeout(timeout)}}function extractText3(parts){if(!Array.isArray(parts))return"";return parts.filter((part)=>part.type==="text").map((part)=>part.text??"").join(`
|
|
5897
5897
|
`)}function formatError3(error93){if(error93 instanceof Error)return error93.message;let text=typeof error93==="string"?error93:String(error93);return boundErrorString(text)}function boundErrorString(text){if(text.length<=MAX_ERROR_CHARS)return text;return`${text.slice(0,MAX_ERROR_CHARS)}${ERROR_TRUNCATION_SUFFIX}`}function isoNow(){return new Date(_internals110.now()).toISOString()}function buildLaneSessionCreateArgs(directory,lane,context){let parentID=context.sessionID?.trim(),escapedAgent=lane.agent.replace(/\(/g,"(").replace(/\)/g,")");return{body:{...parentID?{parentID}:{},title:`${lane.id} (${escapedAgent})`},query:{directory}}}function makeBatchId(){return`lanes-${_internals110.now().toString(36)}`}function promptHash(lane,directory,batchId){return digestText2(JSON.stringify({batchId,laneId:lane.id,agent:lane.agent,directory,prompt:lane.prompt.replace(/\r\n/g,`
|
|
5898
5898
|
`)}))}function digestText2(text){return createHash21("sha256").update(text).digest("hex")}function sleep3(ms){if(ms<=0)return Promise.resolve();return new Promise((resolve70)=>{setTimeout(resolve70,ms)})}var dispatch_lanes=createSwarmTool({description:"Dispatch multiple read-only exploration/review lanes concurrently and BLOCK until every lane finishes, returning a structured join result. This blocks the caller until completion; for non-blocking dispatch that lets you keep working while lanes run, prefer dispatch_lanes_async + collect_lane_results and use this blocking variant only when promptAsync is unavailable. Keep each lane prompt compact: send large shared context once via common_prompt (or have lanes read it from a file by absolute path) instead of inlining it into every lane prompt.",args:{lanes:DispatchLanesArgsSchema.shape.lanes,common_prompt:DispatchLanesArgsSchema.shape.common_prompt,max_concurrent:DispatchLanesArgsSchema.shape.max_concurrent,timeout_ms:DispatchLanesArgsSchema.shape.timeout_ms},execute:async(args2,directory,ctx)=>{let result=await executeDispatchLanes(args2,directory,{callerAgent:getContextAgent(ctx),sessionID:getContextSessionID(ctx)});return JSON.stringify(result,null,2)}}),dispatch_lanes_async=createSwarmTool({description:"Launch multiple read-only advisory lanes with OpenCode promptAsync and return IMMEDIATELY with a batch id and lane session handles (non-blocking). launch_timeout_ms only bounds session creation and promptAsync acceptance; it is NOT a lane runtime timeout. After launching, keep working on non-dependent investigation while lanes run — poll incrementally with collect_lane_results (wait omitted or false) to process settled lanes as they complete, or use wait: true only at workflow boundaries where all results are needed. Keep each lane prompt compact: send large shared context once via common_prompt (or have lanes read it from a file by absolute path) instead of inlining it into every lane prompt, which can produce oversized or malformed tool-call JSON.",args:{lanes:DispatchLanesAsyncArgsSchema.shape.lanes,common_prompt:DispatchLanesAsyncArgsSchema.shape.common_prompt,max_concurrent:DispatchLanesAsyncArgsSchema.shape.max_concurrent,launch_timeout_ms:DispatchLanesAsyncArgsSchema.shape.launch_timeout_ms,timeout_ms:DispatchLanesAsyncArgsSchema.shape.timeout_ms,batch_id:DispatchLanesAsyncArgsSchema.shape.batch_id,mode:DispatchLanesAsyncArgsSchema.shape.mode,pr_head_sha:DispatchLanesAsyncArgsSchema.shape.pr_head_sha,scope:DispatchLanesAsyncArgsSchema.shape.scope},execute:async(args2,directory,ctx)=>{let result=await executeDispatchLanesAsync(args2,directory,{callerAgent:getContextAgent(ctx),sessionID:getContextSessionID(ctx)});return JSON.stringify(result,null,2)}}),collect_lane_results=createSwarmTool({description:"Collect or poll results for a dispatch_lanes_async batch. Supports two modes: (1) non-blocking poll (wait omitted or false) — performs one collection pass and returns current lane status, including pending lane identities by default, and any settled results so you can process completed lanes while continuing independent work; (2) blocking join (wait: true) — polls until all lanes settle or the collection wait budget expires. Busy/retry lanes do not become stale solely because they run for a long time. Does not advance workflow gates.",args:{batch_id:CollectLaneResultsArgsSchema.shape.batch_id,wait:CollectLaneResultsArgsSchema.shape.wait,timeout_ms:CollectLaneResultsArgsSchema.shape.timeout_ms,include_pending:CollectLaneResultsArgsSchema.shape.include_pending,cancel_pending:CollectLaneResultsArgsSchema.shape.cancel_pending},execute:async(args2,directory,ctx)=>{let result=await executeCollectLaneResults(args2,directory,{sessionID:getContextSessionID(ctx)});return JSON.stringify(result,null,2)}});function getContextAgent(ctx){if(!ctx||typeof ctx!=="object")return;let value=ctx.agent;return typeof value==="string"?value:void 0}function getContextSessionID(ctx){if(!ctx||typeof ctx!=="object")return;let value=ctx.sessionID;return typeof value==="string"?value:void 0}init_doc_scan();init_zod();init_create_tool();var DOMAIN_PATTERNS={windows:[/\bwindows\b/i,/\bwin32\b/i,/\bregistry\b/i,/\bregedit\b/i,/\bwmi\b/i,/\bcim\b/i,/\bservice\b/i,/\bevent\s*log\b/i,/\bscheduled\s*task\b/i,/\bgpo\b/i,/\bgroup\s*policy\b/i,/\bmsi\b/i,/\binstaller\b/i,/\bwinrm\b/i],powershell:[/\bpowershell\b/i,/\bpwsh\b/i,/\bps1\b/i,/\bcmdlet\b/i,/\bget-\w+/i,/\bset-\w+/i,/\bnew-\w+/i,/\bremove-\w+/i,/\binvoke-\w+/i,/\bpester\b/i],python:[/\bpython\b/i,/\bpip\b/i,/\bpypi\b/i,/\bdjango\b/i,/\bflask\b/i,/\bpandas\b/i,/\bnumpy\b/i,/\bpytest\b/i,/\bvenv\b/i,/\bconda\b/i],oracle:[/\boracle\b/i,/\bsqlplus\b/i,/\bplsql\b/i,/\btnsnames\b/i,/\bpdb\b/i,/\bcdb\b/i,/\btablespace\b/i,/\brman\b/i,/\bdataguard\b/i,/\basm\b/i,/\brac\b/i,/\bora-\d+/i],network:[/\bnetwork\b/i,/\bfirewall\b/i,/\bdns\b/i,/\bdhcp\b/i,/\btcp\b/i,/\budp\b/i,/\bip\s*address\b/i,/\bsubnet\b/i,/\bvlan\b/i,/\brouting\b/i,/\bswitch\b/i,/\bload\s*balanc/i,/\bproxy\b/i,/\bssl\b/i,/\btls\b/i,/\bcertificate\b/i],security:[/\bstig\b/i,/\bdisa\b/i,/\bcve\b/i,/\bvulnerabil/i,/\bharden\b/i,/\baudit\b/i,/\bcompliance\b/i,/\bscap\b/i,/\bfips\b/i,/\bcac\b/i,/\bpki\b/i,/\bencrypt/i],linux:[/\blinux\b/i,/\bubuntu\b/i,/\brhel\b/i,/\bcentos\b/i,/\bbash\b/i,/\bsystemd\b/i,/\bsystemctl\b/i,/\byum\b/i,/\bapt\b/i,/\bcron\b/i,/\bchmod\b/i,/\bchown\b/i],vmware:[/\bvmware\b/i,/\bvsphere\b/i,/\besxi\b/i,/\bvcenter\b/i,/\bvsan\b/i,/\bnsx\b/i,/\bvmotion\b/i,/\bdatastore\b/i,/\bpowercli\b/i,/\bova\b/i,/\bovf\b/i],azure:[/\bazure\b/i,/\baz\s+\w+/i,/\bentra\b/i,/\baad\b/i,/\bazure\s*ad\b/i,/\barm\s*template\b/i,/\bbicep\b/i,/\bazure\s*devops\b/i,/\bblob\b/i,/\bkeyvault\b/i],active_directory:[/\bactive\s*directory\b/i,/\bad\s+\w+/i,/\bldap\b/i,/\bdomain\s*controller\b/i,/\bgpupdate\b/i,/\bdsquery\b/i,/\bdsmod\b/i,/\baduc\b/i,/\bkerberos\b/i,/\bspn\b/i],ui_ux:[/\bui\b/i,/\bux\b/i,/\buser\s+experience\b/i,/\buser\s+interface\b/i,/\bvisual\s+design\b/i,/\binteraction\s+design\b/i,/\bdesign\s+system\b/i,/\bwireframe\b/i,/\bprototype\b/i,/\baccessibility\b/i,/\btypography\b/i,/\blayout\b/i,/\bresponsive\b/i]},detect_domains=createSwarmTool({description:"Detect which SME domains are relevant for a given text. Returns a list of domain names (windows, powershell, python, oracle, network, security, linux, vmware, azure, active_directory, ui_ux) that match patterns in the input text.",args:{text:exports_external.string().describe("The text to analyze for domain patterns")},execute:async(args2)=>{let text=(typeof args2.text==="string"?args2.text:String(args2.text)).toLowerCase(),detected=[];for(let[domain3,patterns]of Object.entries(DOMAIN_PATTERNS))for(let pattern of patterns)if(pattern.test(text)){detected.push(domain3);break}if(detected.length===0)return"No specific domains detected. The Architect should determine requirements from context.";return`Detected domains: ${detected.join(", ")}
|
|
5899
5899
|
|
|
@@ -5925,7 +5925,7 @@ Resolution: call \`declare_scope\` once for EACH of those task ids, passing the
|
|
|
5925
5925
|
`;if(errors5.length>0){result+=`
|
|
5926
5926
|
Errors:
|
|
5927
5927
|
`;for(let err of errors5)result+=` - ${err}
|
|
5928
|
-
`}return result}});init_zod();init_state2();function slugify3(str){return str.replace(/[^a-zA-Z0-9_-]/g,"_").replace(/_+/g,"_")}function sanitizeFilename2(filename){return filename.replace(/[\p{Cc}"'`]/gu,"_")}function extractJsonArray(text){let trimmed=text.trim(),fenceMatch=trimmed.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);if(fenceMatch)return fenceMatch[1].trim();let start=trimmed.search(/\[\s*[{["0-9\]tfn]/),end=trimmed.lastIndexOf("]");if(start!==-1&&end>start)return trimmed.slice(start,end+1);return trimmed}async function generateMutants(files,ctx){if(!ctx)return
|
|
5928
|
+
`}return result}});init_zod();init_state2();init_logger();function slugify3(str){return str.replace(/[^a-zA-Z0-9_-]/g,"_").replace(/_+/g,"_")}function sanitizeFilename2(filename){return filename.replace(/[\p{Cc}"'`]/gu,"_")}function extractJsonArray(text){let trimmed=text.trim(),fenceMatch=trimmed.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);if(fenceMatch)return fenceMatch[1].trim();let start=trimmed.search(/\[\s*[{["0-9\]tfn]/),end=trimmed.lastIndexOf("]");if(start!==-1&&end>start)return trimmed.slice(start,end+1);return trimmed}async function generateMutants(files,ctx){if(!ctx)return log("[generateMutants] No ToolContext — cannot call LLM; returning empty patch set"),[];let client=swarmState.opencodeClient;if(!client)return log("[generateMutants] opencodeClient not available; returning empty patch set"),[];let directory=ctx.directory??process.cwd(),ephemeralSessionId,promptController=new AbortController,cleanup=()=>{if(promptController.abort(),ephemeralSessionId){let id=ephemeralSessionId;ephemeralSessionId=void 0,client.session.delete({path:{id}}).catch(()=>{})}};try{let createResult=await client.session.create({...ctx?.sessionID?{body:{parentID:ctx.sessionID,title:"mutation_generator background"}}:{},query:{directory}});if(!createResult.data)return log(`[generateMutants] Failed to create session: ${JSON.stringify(createResult.error)}; returning empty patch set`),[];ephemeralSessionId=createResult.data.id;let mutationTypes=["off-by-one","null-substitution","operator-swap","guard-removal","branch-swap","side-effect-deletion"].join(", "),promptText=`Generate mutation testing patches for the following files: ${files.map(sanitizeFilename2).join(", ")}
|
|
5929
5929
|
|
|
5930
5930
|
Return a JSON array where each element has:
|
|
5931
5931
|
{ id, filePath, functionName, mutationType, patch, lineNumber }
|
|
@@ -5935,8 +5935,8 @@ Return a JSON array where each element has:
|
|
|
5935
5935
|
- patch: unified diff format (--- a/file\\n+++ a/file\\n@@ ... @@\\n-old\\n+new)
|
|
5936
5936
|
- Generate 3-5 mutations per function
|
|
5937
5937
|
|
|
5938
|
-
Return ONLY a valid JSON array. No markdown, no code fences, no explanation. Start your response with [ and end with ].`,promptResult=await client.session.prompt({path:{id:ephemeralSessionId},body:{agent:void 0,tools:{write:!1,edit:!1,patch:!1},parts:[{type:"text",text:promptText}]},signal:promptController.signal});if(!promptResult.data)return
|
|
5939
|
-
`),parsed;try{parsed=JSON.parse(extractJsonArray(rawText))}catch(error93){let msg=error93 instanceof Error?error93.message:String(error93),hint=msg.includes("EOF")||msg.includes("Unexpected end")?" (response appears truncated — LLM may have hit an output token limit)":"";return console.warn(`[generateMutants] Failed to parse LLM response as MutationPatch[]: ${msg}${hint}; returning empty patch set`),[]}if(!Array.isArray(parsed)||parsed.length===0)return[];let patches=[];for(let item of parsed){if(typeof item!=="object"||item===null||typeof item.filePath!=="string"||typeof item.functionName!=="string"||typeof item.mutationType!=="string"||typeof item.patch!=="string")continue;let mutationType=item.mutationType,fileSlug=slugify3(item.filePath),fnSlug=slugify3(item.functionName),typeSlug=slugify3(mutationType),idStr=typeof item.id==="string"?item.id:"",id=idStr.startsWith("mut-")?idStr:`mut-${fileSlug}-${fnSlug}-${typeSlug}-${String(patches.length+1).padStart(3,"0")}`;patches.push({id,filePath:item.filePath,functionName:item.functionName,mutationType,patch:item.patch,lineNumber:typeof item.lineNumber==="number"?item.lineNumber:void 0})}return patches}catch(error93){return console.warn(`[generateMutants] LLM call failed: ${error93 instanceof Error?error93.message:String(error93)}; returning empty patch set`),[]}finally{cleanup()}}init_create_tool();var generate_mutants=createSwarmTool({description:"Generate LLM-based mutation testing patches for the specified source files. Returns MutationPatch[] for direct consumption by the mutation_test tool. On LLM failure or when no patches can be generated, returns a SKIP verdict with a diagnostic message rather than throwing.",args:{files:exports_external.array(exports_external.string()).describe("Array of source file paths to generate mutation patches for")},async execute(args2,_directory,ctx){let typedArgs=args2;if(!typedArgs.files||!Array.isArray(typedArgs.files)||typedArgs.files.length===0)return JSON.stringify({verdict:"SKIP",patches:[],count:0,message:"generate_mutants: files must be a non-empty array"},null,2);try{let patches=await generateMutants(typedArgs.files,ctx);if(patches.length===0)return JSON.stringify({verdict:"SKIP",patches:[],count:0,message:"generate_mutants: LLM returned no patches — skipping mutation gate"},null,2);let result={verdict:"ready",patches,count:patches.length};return JSON.stringify(result,null,2)}catch(error93){let result={verdict:"SKIP",patches:[],count:0,message:`generate_mutants: unexpected error — ${error93 instanceof Error?error93.message:String(error93)}`};return JSON.stringify(result,null,2)}}});init_zod();init_qa_gate_profile();init_ledger();init_manager();init_utils3();init_create_tool();function summarizePlan(plan){return{title:plan.title,swarm:plan.swarm,current_phase:plan.current_phase??0,phase_count:plan.phases.length,phases:plan.phases.map((p)=>({id:p.id,name:p.name,status:p.status,task_count:p.tasks.length}))}}async function executeGetApprovedPlan(args2,directory){let currentPlan=await loadPlanJsonOnly(directory);if(!currentPlan){if(await loadLastApprovedPlan(directory))return{success:!0,approved_plan:void 0,current_plan:null,drift_detected:"unknown",current_plan_error:"plan.json not found or invalid"};return{success:!1,reason:"no_approved_snapshot"}}let expectedPlanId=derivePlanId(currentPlan),profile=getProfile(directory,expectedPlanId),qaProfileHash=profile?computeProfileHash(profile):null,approved=await loadLastApprovedPlan(directory,expectedPlanId);if(!approved){if(await loadLastApprovedPlan(directory))return{success:!0,approved_plan:void 0,current_plan:null,drift_detected:!0,current_plan_error:"Plan identity (swarm/title) was mutated after approval — "+`expected plan_id '${expectedPlanId}' but approved snapshot has a different identity. This is a form of plan tampering.`,qa_profile_hash:qaProfileHash};return{success:!1,reason:"no_approved_snapshot",qa_profile_hash:qaProfileHash}}let summaryOnly=args2.summary_only===!0,approvedPayload={plan:summaryOnly?summarizePlan(approved.plan):approved.plan,approval_metadata:approved.approval,snapshot_seq:approved.seq,snapshot_timestamp:approved.timestamp,payload_hash:approved.payloadHash,execution_profile:approved.plan.execution_profile??null},currentHash=computePlanHash(currentPlan),driftDetected=currentHash!==approved.payloadHash,currentPayload={plan:summaryOnly?summarizePlan(currentPlan):currentPlan,current_hash:currentHash};return{success:!0,approved_plan:approvedPayload,current_plan:currentPayload,drift_detected:driftDetected,qa_profile_hash:qaProfileHash}}var get_approved_plan=createSwarmTool({description:"Retrieve the last critic-approved immutable plan snapshot for baseline drift comparison. Returns the approved plan, its approval metadata, and optionally compares against the current plan.json to detect silent mutations. Read-only.",args:{summary_only:exports_external.boolean().optional().describe("When true, returns only structural metadata (title, phases, task counts) instead of full plan objects. Reduces output size for large plans.")},execute:async(args2,directory)=>{return JSON.stringify(await executeGetApprovedPlan(args2,directory),null,2)}});init_qa_gate_profile();init_manager();init_utils3();init_create_tool();async function executeGetQaGateProfile(_args,directory){let plan=await loadPlanJsonOnly(directory);if(!plan)return{success:!1,reason:"plan_json_unavailable"};let planId=derivePlanId(plan),profile=getProfile(directory,planId);if(!profile)return{success:!1,reason:"no_profile",plan_id:planId};return{success:!0,plan_id:planId,profile:{plan_id:profile.plan_id,project_type:profile.project_type,gates:{...profile.gates},locked_at:profile.locked_at,locked_by_snapshot_seq:profile.locked_by_snapshot_seq,created_at:profile.created_at,profile_hash:computeProfileHash(profile)}}}var get_qa_gate_profile=createSwarmTool({description:"Retrieve the QA gate profile for the current plan. Returns the spec-level "+"gates, lock state, and a SHA-256 profile hash. Read-only — does not "+"create a profile if none exists. plan_id is derived automatically from plan.json (swarm + title).",args:{},execute:async(args2,directory)=>{return JSON.stringify(await executeGetQaGateProfile(args2??{},directory),null,2)}});init_zod();init_external_tool_runner();init_path_security();init_create_tool();var GH_TIMEOUT_MS=20000,GH_MAX_STDOUT_BYTES=2097152,GH_MAX_STDERR_BYTES=131072,DEFAULT_PR_FIELDS=["number","title","state","isDraft","author","headRefName","headRefOid","baseRefName","baseRefOid","mergeable","mergeStateStatus","reviewDecision","statusCheckRollup","url"],DEFAULT_ISSUE_FIELDS=["number","title","state","author","labels","assignees","url"],PR_FIELD_ALLOWLIST=new Set([...DEFAULT_PR_FIELDS,"additions","body","changedFiles","commits","deletions","files","latestReviews","reviews"]),ISSUE_FIELD_ALLOWLIST=new Set([...DEFAULT_ISSUE_FIELDS,"body","comments","closed","closedAt","createdAt","milestone","updatedAt"]),DEFAULT_RUN_FIELDS=["status","conclusion","htmlUrl","headBranch","headSha"],RUN_FIELD_ALLOWLIST=new Set([...DEFAULT_RUN_FIELDS,"name","workflowId","runNumber","event","runStartedAt","createdAt","updatedAt"]);function resolveGhBinary(){return _internals125.resolveExecutableFromPath(["gh"])}function normalizeRepo(value){if(value===void 0||value===null||value==="")return;if(typeof value!=="string"||containsControlChars(value))return{error:!0,type:"invalid-input",message:"repo must be an owner/name string"};if(!/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(value))return{error:!0,type:"invalid-input",message:"repo must match owner/name"};return value}function normalizeFields(target,value){let defaults=target==="pr"?Array.from(DEFAULT_PR_FIELDS):target==="issue"?Array.from(DEFAULT_ISSUE_FIELDS):Array.from(DEFAULT_RUN_FIELDS);if(value===void 0||value===null||value==="")return defaults;let raw=Array.isArray(value)?value:typeof value==="string"?value.split(","):null;if(!raw||raw.some((f)=>typeof f!=="string"))return{error:!0,type:"invalid-input",message:"fields must be a comma-separated string or string array"};let allowlist=target==="pr"?PR_FIELD_ALLOWLIST:target==="issue"?ISSUE_FIELD_ALLOWLIST:RUN_FIELD_ALLOWLIST,fields=Array.from(new Set(raw.map((f)=>f.trim()).filter(Boolean)));if(fields.length===0||fields.some((f)=>containsControlChars(f)||!allowlist.has(f)))return{error:!0,type:"invalid-input",message:`fields must be selected from the ${target} allowlist`};return fields}function sanitizeParsedJson(value){if(Array.isArray(value))return value.map(sanitizeParsedJson);if(value&&typeof value==="object"){let out={};for(let[key,entry]of Object.entries(value)){if(typeof entry==="string"){let bounded=entry.length>20000?`${entry.slice(0,20000)}... [truncated]`:entry;out[key]=key==="body"?neutralizeUntrustedMarkdown(bounded,"GitHub body"):bounded;continue}out[key]=sanitizeParsedJson(entry)}return out}return value}var gh_evidence=createSwarmTool({description:"Fetch bounded GitHub pull request or issue metadata via gh for review evidence. Read-only; resolves gh lazily.",args:{target:exports_external.enum(["pr","issue","run"]).default("pr").describe("GitHub object type to view: pr, issue, or run"),number:exports_external.number().describe("Pull request, issue, or run number"),repo:exports_external.string().optional().describe("Optional owner/repo. If omitted, gh uses the current repo."),fields:exports_external.union([exports_external.string(),exports_external.array(exports_external.string())]).optional().describe("Optional JSON fields. Defaults to high-signal bounded PR or issue fields. Ignored for run with log_failed."),log_failed:exports_external.boolean().optional().default(!1).describe("When true with target=run, fetches failed job logs instead of JSON")},execute:async(args2,directory)=>{let obj=typeof args2==="object"&&args2!==null?args2:{},rawTarget=obj.target,target=rawTarget==="issue"?"issue":rawTarget==="run"?"run":"pr",number7=typeof obj.number==="number"?obj.number:NaN;if(!Number.isInteger(number7)||number7<=0)return JSON.stringify({error:!0,type:"invalid-input",message:"number must be a positive integer"},null,2);let repo=normalizeRepo(obj.repo);if(repo&&typeof repo==="object")return JSON.stringify(repo,null,2);let logFailed=obj.log_failed===!0,fields=normalizeFields(target,obj.fields);if(!Array.isArray(fields))return JSON.stringify(fields,null,2);let executable=_internals125.resolveGhBinary();if(!executable)return JSON.stringify({error:!0,type:"gh-not-found",message:"GitHub CLI executable not found. Install gh and ensure it is on PATH."},null,2);let ghArgs=[target,"view",String(number7)],isLogFailedMode=target==="run"&&logFailed;if(!isLogFailedMode)ghArgs.push("--json",fields.join(","));if(repo)ghArgs.push("--repo",repo);if(isLogFailedMode)ghArgs.push("--log-failed");let run=await _internals125.runExternalTool({executable,args:ghArgs,cwd:directory,timeoutMs:GH_TIMEOUT_MS,maxStdoutBytes:GH_MAX_STDOUT_BYTES,maxStderrBytes:GH_MAX_STDERR_BYTES});if(run.status==="timeout")return JSON.stringify({error:!0,type:"timeout",message:`gh ${target} view timed out after ${GH_TIMEOUT_MS}ms`},null,2);if(run.status==="spawn-error")return JSON.stringify({error:!0,type:"unknown",message:run.message??"gh failed to start"},null,2);if(run.exitCode!==0)return JSON.stringify({error:!0,type:"unknown",message:run.stderr.split(`
|
|
5938
|
+
Return ONLY a valid JSON array. No markdown, no code fences, no explanation. Start your response with [ and end with ].`,promptResult=await client.session.prompt({path:{id:ephemeralSessionId},body:{agent:void 0,tools:{write:!1,edit:!1,patch:!1},parts:[{type:"text",text:promptText}]},signal:promptController.signal});if(!promptResult.data)return log(`[generateMutants] LLM prompt failed: ${JSON.stringify(promptResult.error)}; returning empty patch set`),[];let rawText=promptResult.data.parts.filter((p)=>p.type==="text").map((p)=>p.text).join(`
|
|
5939
|
+
`),parsed;try{parsed=JSON.parse(extractJsonArray(rawText))}catch(error93){let msg=error93 instanceof Error?error93.message:String(error93),hint=msg.includes("EOF")||msg.includes("Unexpected end")?" (response appears truncated — LLM may have hit an output token limit)":"";return log(`[generateMutants] Failed to parse LLM response as MutationPatch[]: ${msg}${hint}; returning empty patch set`),[]}if(!Array.isArray(parsed)||parsed.length===0)return[];let patches=[];for(let item of parsed){if(typeof item!=="object"||item===null||typeof item.filePath!=="string"||typeof item.functionName!=="string"||typeof item.mutationType!=="string"||typeof item.patch!=="string")continue;let mutationType=item.mutationType,fileSlug=slugify3(item.filePath),fnSlug=slugify3(item.functionName),typeSlug=slugify3(mutationType),idStr=typeof item.id==="string"?item.id:"",id=idStr.startsWith("mut-")?idStr:`mut-${fileSlug}-${fnSlug}-${typeSlug}-${String(patches.length+1).padStart(3,"0")}`;patches.push({id,filePath:item.filePath,functionName:item.functionName,mutationType,patch:item.patch,lineNumber:typeof item.lineNumber==="number"?item.lineNumber:void 0})}return patches}catch(error93){return log(`[generateMutants] LLM call failed: ${error93 instanceof Error?error93.message:String(error93)}; returning empty patch set`),[]}finally{cleanup()}}init_create_tool();var generate_mutants=createSwarmTool({description:"Generate LLM-based mutation testing patches for the specified source files. Returns MutationPatch[] for direct consumption by the mutation_test tool. On LLM failure or when no patches can be generated, returns a SKIP verdict with a diagnostic message rather than throwing.",args:{files:exports_external.array(exports_external.string()).describe("Array of source file paths to generate mutation patches for")},async execute(args2,_directory,ctx){let typedArgs=args2;if(!typedArgs.files||!Array.isArray(typedArgs.files)||typedArgs.files.length===0)return JSON.stringify({verdict:"SKIP",patches:[],count:0,message:"generate_mutants: files must be a non-empty array"},null,2);try{let patches=await generateMutants(typedArgs.files,ctx);if(patches.length===0)return JSON.stringify({verdict:"SKIP",patches:[],count:0,message:"generate_mutants: LLM returned no patches — skipping mutation gate"},null,2);let result={verdict:"ready",patches,count:patches.length};return JSON.stringify(result,null,2)}catch(error93){let result={verdict:"SKIP",patches:[],count:0,message:`generate_mutants: unexpected error — ${error93 instanceof Error?error93.message:String(error93)}`};return JSON.stringify(result,null,2)}}});init_zod();init_qa_gate_profile();init_ledger();init_manager();init_utils3();init_create_tool();function summarizePlan(plan){return{title:plan.title,swarm:plan.swarm,current_phase:plan.current_phase??0,phase_count:plan.phases.length,phases:plan.phases.map((p)=>({id:p.id,name:p.name,status:p.status,task_count:p.tasks.length}))}}async function executeGetApprovedPlan(args2,directory){let currentPlan=await loadPlanJsonOnly(directory);if(!currentPlan){if(await loadLastApprovedPlan(directory))return{success:!0,approved_plan:void 0,current_plan:null,drift_detected:"unknown",current_plan_error:"plan.json not found or invalid"};return{success:!1,reason:"no_approved_snapshot"}}let expectedPlanId=derivePlanId(currentPlan),profile=getProfile(directory,expectedPlanId),qaProfileHash=profile?computeProfileHash(profile):null,approved=await loadLastApprovedPlan(directory,expectedPlanId);if(!approved){if(await loadLastApprovedPlan(directory))return{success:!0,approved_plan:void 0,current_plan:null,drift_detected:!0,current_plan_error:"Plan identity (swarm/title) was mutated after approval — "+`expected plan_id '${expectedPlanId}' but approved snapshot has a different identity. This is a form of plan tampering.`,qa_profile_hash:qaProfileHash};return{success:!1,reason:"no_approved_snapshot",qa_profile_hash:qaProfileHash}}let summaryOnly=args2.summary_only===!0,approvedPayload={plan:summaryOnly?summarizePlan(approved.plan):approved.plan,approval_metadata:approved.approval,snapshot_seq:approved.seq,snapshot_timestamp:approved.timestamp,payload_hash:approved.payloadHash,execution_profile:approved.plan.execution_profile??null},currentHash=computePlanHash(currentPlan),driftDetected=currentHash!==approved.payloadHash,currentPayload={plan:summaryOnly?summarizePlan(currentPlan):currentPlan,current_hash:currentHash};return{success:!0,approved_plan:approvedPayload,current_plan:currentPayload,drift_detected:driftDetected,qa_profile_hash:qaProfileHash}}var get_approved_plan=createSwarmTool({description:"Retrieve the last critic-approved immutable plan snapshot for baseline drift comparison. Returns the approved plan, its approval metadata, and optionally compares against the current plan.json to detect silent mutations. Read-only.",args:{summary_only:exports_external.boolean().optional().describe("When true, returns only structural metadata (title, phases, task counts) instead of full plan objects. Reduces output size for large plans.")},execute:async(args2,directory)=>{return JSON.stringify(await executeGetApprovedPlan(args2,directory),null,2)}});init_qa_gate_profile();init_manager();init_utils3();init_create_tool();async function executeGetQaGateProfile(_args,directory){let plan=await loadPlanJsonOnly(directory);if(!plan)return{success:!1,reason:"plan_json_unavailable"};let planId=derivePlanId(plan),profile=getProfile(directory,planId);if(!profile)return{success:!1,reason:"no_profile",plan_id:planId};return{success:!0,plan_id:planId,profile:{plan_id:profile.plan_id,project_type:profile.project_type,gates:{...profile.gates},locked_at:profile.locked_at,locked_by_snapshot_seq:profile.locked_by_snapshot_seq,created_at:profile.created_at,profile_hash:computeProfileHash(profile)}}}var get_qa_gate_profile=createSwarmTool({description:"Retrieve the QA gate profile for the current plan. Returns the spec-level "+"gates, lock state, and a SHA-256 profile hash. Read-only — does not "+"create a profile if none exists. plan_id is derived automatically from plan.json (swarm + title).",args:{},execute:async(args2,directory)=>{return JSON.stringify(await executeGetQaGateProfile(args2??{},directory),null,2)}});init_zod();init_external_tool_runner();init_path_security();init_create_tool();var GH_TIMEOUT_MS=20000,GH_MAX_STDOUT_BYTES=2097152,GH_MAX_STDERR_BYTES=131072,DEFAULT_PR_FIELDS=["number","title","state","isDraft","author","headRefName","headRefOid","baseRefName","baseRefOid","mergeable","mergeStateStatus","reviewDecision","statusCheckRollup","url"],DEFAULT_ISSUE_FIELDS=["number","title","state","author","labels","assignees","url"],PR_FIELD_ALLOWLIST=new Set([...DEFAULT_PR_FIELDS,"additions","body","changedFiles","commits","deletions","files","latestReviews","reviews"]),ISSUE_FIELD_ALLOWLIST=new Set([...DEFAULT_ISSUE_FIELDS,"body","comments","closed","closedAt","createdAt","milestone","updatedAt"]),DEFAULT_RUN_FIELDS=["status","conclusion","htmlUrl","headBranch","headSha"],RUN_FIELD_ALLOWLIST=new Set([...DEFAULT_RUN_FIELDS,"name","workflowId","runNumber","event","runStartedAt","createdAt","updatedAt"]);function resolveGhBinary(){return _internals125.resolveExecutableFromPath(["gh"])}function normalizeRepo(value){if(value===void 0||value===null||value==="")return;if(typeof value!=="string"||containsControlChars(value))return{error:!0,type:"invalid-input",message:"repo must be an owner/name string"};if(!/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(value))return{error:!0,type:"invalid-input",message:"repo must match owner/name"};return value}function normalizeFields(target,value){let defaults=target==="pr"?Array.from(DEFAULT_PR_FIELDS):target==="issue"?Array.from(DEFAULT_ISSUE_FIELDS):Array.from(DEFAULT_RUN_FIELDS);if(value===void 0||value===null||value==="")return defaults;let raw=Array.isArray(value)?value:typeof value==="string"?value.split(","):null;if(!raw||raw.some((f)=>typeof f!=="string"))return{error:!0,type:"invalid-input",message:"fields must be a comma-separated string or string array"};let allowlist=target==="pr"?PR_FIELD_ALLOWLIST:target==="issue"?ISSUE_FIELD_ALLOWLIST:RUN_FIELD_ALLOWLIST,fields=Array.from(new Set(raw.map((f)=>f.trim()).filter(Boolean)));if(fields.length===0||fields.some((f)=>containsControlChars(f)||!allowlist.has(f)))return{error:!0,type:"invalid-input",message:`fields must be selected from the ${target} allowlist`};return fields}function sanitizeParsedJson(value){if(Array.isArray(value))return value.map(sanitizeParsedJson);if(value&&typeof value==="object"){let out={};for(let[key,entry]of Object.entries(value)){if(typeof entry==="string"){let bounded=entry.length>20000?`${entry.slice(0,20000)}... [truncated]`:entry;out[key]=key==="body"?neutralizeUntrustedMarkdown(bounded,"GitHub body"):bounded;continue}out[key]=sanitizeParsedJson(entry)}return out}return value}var gh_evidence=createSwarmTool({description:"Fetch bounded GitHub pull request or issue metadata via gh for review evidence. Read-only; resolves gh lazily.",args:{target:exports_external.enum(["pr","issue","run"]).default("pr").describe("GitHub object type to view: pr, issue, or run"),number:exports_external.number().describe("Pull request, issue, or run number"),repo:exports_external.string().optional().describe("Optional owner/repo. If omitted, gh uses the current repo."),fields:exports_external.union([exports_external.string(),exports_external.array(exports_external.string())]).optional().describe("Optional JSON fields. Defaults to high-signal bounded PR or issue fields. Ignored for run with log_failed."),log_failed:exports_external.boolean().optional().default(!1).describe("When true with target=run, fetches failed job logs instead of JSON")},execute:async(args2,directory)=>{let obj=typeof args2==="object"&&args2!==null?args2:{},rawTarget=obj.target,target=rawTarget==="issue"?"issue":rawTarget==="run"?"run":"pr",number7=typeof obj.number==="number"?obj.number:NaN;if(!Number.isInteger(number7)||number7<=0)return JSON.stringify({error:!0,type:"invalid-input",message:"number must be a positive integer"},null,2);let repo=normalizeRepo(obj.repo);if(repo&&typeof repo==="object")return JSON.stringify(repo,null,2);let logFailed=obj.log_failed===!0,fields=normalizeFields(target,obj.fields);if(!Array.isArray(fields))return JSON.stringify(fields,null,2);let executable=_internals125.resolveGhBinary();if(!executable)return JSON.stringify({error:!0,type:"gh-not-found",message:"GitHub CLI executable not found. Install gh and ensure it is on PATH."},null,2);let ghArgs=[target,"view",String(number7)],isLogFailedMode=target==="run"&&logFailed;if(!isLogFailedMode)ghArgs.push("--json",fields.join(","));if(repo)ghArgs.push("--repo",repo);if(isLogFailedMode)ghArgs.push("--log-failed");let run=await _internals125.runExternalTool({executable,args:ghArgs,cwd:directory,timeoutMs:GH_TIMEOUT_MS,maxStdoutBytes:GH_MAX_STDOUT_BYTES,maxStderrBytes:GH_MAX_STDERR_BYTES});if(run.status==="timeout")return JSON.stringify({error:!0,type:"timeout",message:`gh ${target} view timed out after ${GH_TIMEOUT_MS}ms`},null,2);if(run.status==="spawn-error")return JSON.stringify({error:!0,type:"unknown",message:run.message??"gh failed to start"},null,2);if(run.exitCode!==0)return JSON.stringify({error:!0,type:"unknown",message:run.stderr.split(`
|
|
5940
5940
|
`)[0]||`gh exited ${run.exitCode}`},null,2);let data,runStatus,runConclusion,runHtmlUrl,runHeadBranch,runHeadSha;if(isLogFailedMode)data=neutralizeUntrustedMarkdown(run.stdout,"GitHub Actions failed-job log");else{let parsed;try{parsed=JSON.parse(run.stdout)}catch{return JSON.stringify({error:!0,type:"unknown",message:"gh output was not valid JSON"},null,2)}if(data=sanitizeParsedJson(parsed),target==="run"&&parsed!==null&&(Array.isArray(parsed)||typeof parsed!=="object"))return JSON.stringify({error:!0,type:"invalid-input",message:"gh run view --json returned an array or primitive instead of a run object"},null,2);if(target==="run"&&parsed&&typeof parsed==="object"){let runData=parsed;runStatus=typeof runData.status==="string"?runData.status:void 0,runConclusion=runData.conclusion===null?null:typeof runData.conclusion==="string"?runData.conclusion:void 0,runHtmlUrl=typeof runData.htmlUrl==="string"?runData.htmlUrl:void 0,runHeadBranch=typeof runData.headBranch==="string"?runData.headBranch:void 0,runHeadSha=typeof runData.headSha==="string"?runData.headSha:void 0}}return JSON.stringify({target,number:number7,repo,fields:isLogFailedMode?[]:fields,command:["gh",...ghArgs],data,outputTruncated:run.stdoutTruncated||run.stderrTruncated,...target==="run"&&{runStatus,runConclusion,runHtmlUrl,runHeadBranch,runHeadSha}},null,2)}}),_internals125={resolveExecutableFromPath,resolveGhBinary,runExternalTool};init_zod();init_path_security();init_create_tool();import*as child_process16 from"node:child_process";import*as fs117 from"node:fs";import*as path192 from"node:path";var BLAME_TIMEOUT_MS=30000,MAX_OUTPUT_LINES2=500,MAX_PATH_LENGTH2=500,MAX_LINE_NUMBER=1e6,SHELL_METACHARACTERS3=/[;|&$`(){}<>!'"]/,BINARY_EXTENSIONS=new Set([".png",".jpg",".jpeg",".gif",".bmp",".ico",".svg",".webp",".mp3",".mp4",".wav",".avi",".mov",".wmv",".flv",".zip",".tar",".gz",".rar",".7z",".bz2",".pdf",".doc",".docx",".xls",".xlsx",".ppt",".pptx",".exe",".dll",".so",".dylib",".bin",".dat",".o",".obj",".woff",".woff2",".ttf",".eot",".otf",".sqlite",".db"]);function validateFilePath(filePath){if(!filePath||filePath.length===0)return"file path is required";if(filePath.length>MAX_PATH_LENGTH2)return`file path exceeds maximum length of ${MAX_PATH_LENGTH2}`;if(path192.isAbsolute(filePath)||/^[A-Za-z]:[\\/]/.test(filePath)||filePath.startsWith("\\\\"))return"absolute paths are not allowed; use a relative path from the project root";if(containsPathTraversal(filePath))return"path traversal detected";if(containsControlChars(filePath))return"file path contains control characters";if(SHELL_METACHARACTERS3.test(filePath))return"file path contains shell metacharacters";if(filePath.startsWith("-"))return'file path cannot start with "-"';return null}function validateLineNumber(value,name){if(typeof value>"u")return null;if(typeof value!=="number"||!Number.isInteger(value)||value<1)return`${name} must be a positive integer`;if(value>MAX_LINE_NUMBER)return`${name} exceeds maximum value of ${MAX_LINE_NUMBER}`;return null}function isBinaryFile2(filePath){let ext=path192.extname(filePath).toLowerCase();return BINARY_EXTENSIONS.has(ext)}function parsePorcelainBlame(output,linesCap){let entries=[],cappedLines=output.split(`
|
|
5941
5941
|
`).slice(0,linesCap*8),commitCache=new Map,currentSha="",currentLine=0,currentAuthor="",currentAuthorTime="",currentSummary="";for(let rawLine of cappedLines){let headerMatch=rawLine.match(/^([0-9a-f]{40})\s+(\d+)\s+(\d+)/);if(headerMatch){currentSha=headerMatch[1],currentLine=Number.parseInt(headerMatch[3],10);let cached3=commitCache.get(currentSha);if(cached3)currentAuthor=cached3.author,currentAuthorTime=cached3.authorTime,currentSummary=cached3.summary;else currentAuthor="",currentAuthorTime="",currentSummary="";continue}if(rawLine.startsWith("author ")){currentAuthor=rawLine.slice(7);let meta3=commitCache.get(currentSha);if(!meta3)meta3={author:"",authorTime:"",summary:""},commitCache.set(currentSha,meta3);meta3.author=currentAuthor;continue}if(rawLine.startsWith("author-time ")){currentAuthorTime=rawLine.slice(12);let meta3=commitCache.get(currentSha);if(!meta3)meta3={author:"",authorTime:"",summary:""},commitCache.set(currentSha,meta3);meta3.authorTime=currentAuthorTime;continue}if(rawLine.startsWith("summary ")){currentSummary=rawLine.slice(8);let meta3=commitCache.get(currentSha);if(!meta3)meta3={author:"",authorTime:"",summary:""},commitCache.set(currentSha,meta3);meta3.summary=currentSummary;continue}if(rawLine.startsWith("\t")){if(entries.push({line:currentLine,sha:currentSha.slice(0,8),author:currentAuthor,authorTime:currentAuthorTime,summary:currentSummary,content:rawLine.slice(1)}),entries.length>=linesCap)break}}return entries.slice(0,linesCap)}var git_blame=createSwarmTool({description:"Analyze per-line git blame metadata for a file. Returns sha (abbreviated), author, date (ISO), summary, and content for each line. Uses git blame --porcelain. Rejects binary files and validates paths.",args:{file:exports_external.string().describe("Relative file path to blame (required, relative to project root)"),start:exports_external.number().optional().describe("Optional start line number (1-indexed). Requires end parameter."),end:exports_external.number().optional().describe("Optional end line number (1-indexed, inclusive). Requires start parameter.")},async execute(args2,directory){let fileInput,startInput,endInput;try{if(args2&&typeof args2==="object"){let obj=args2;fileInput=typeof obj.file==="string"?obj.file:void 0,startInput=typeof obj.start==="number"?obj.start:void 0,endInput=typeof obj.end==="number"?obj.end:void 0}}catch{}if(!fileInput)return JSON.stringify({error:"file path is required",file:String(fileInput??""),lineCount:0,lines:[]});let file3=fileInput,pathError=validateFilePath(file3);if(pathError)return JSON.stringify({error:pathError,file:file3,lineCount:0,lines:[]});let startError=validateLineNumber(startInput,"start");if(startError)return JSON.stringify({error:startError,file:file3,lineCount:0,lines:[]});let endError=validateLineNumber(endInput,"end");if(endError)return JSON.stringify({error:endError,file:file3,lineCount:0,lines:[]});if(startInput!==void 0&&endInput===void 0||startInput===void 0&&endInput!==void 0)return JSON.stringify({error:"both start and end must be provided together for a line range",file:file3,lineCount:0,lines:[]});if(startInput!==void 0&&endInput!==void 0&&startInput>endInput)return JSON.stringify({error:"start must be less than or equal to end",file:file3,lineCount:0,lines:[]});let resolvedPath=path192.resolve(directory,file3);if(!fs117.existsSync(resolvedPath))return JSON.stringify({error:`file not found: ${file3}`,file:file3,lineCount:0,lines:[]});let realDir=fs117.realpathSync(directory),realPath=fs117.realpathSync(resolvedPath),relative40=path192.relative(realDir,realPath);if(relative40.startsWith("..")||path192.isAbsolute(relative40))return JSON.stringify({error:"file path resolves outside the workspace",file:file3,lineCount:0,lines:[]});if(fs117.statSync(resolvedPath).isDirectory())return JSON.stringify({error:"path is a directory, not a file",file:file3,lineCount:0,lines:[]});if(isBinaryFile2(file3))return JSON.stringify({error:"binary files are not supported for git blame",file:file3,lineCount:0,lines:[]});let gitArgs=["blame","--porcelain"];if(startInput!==void 0&&endInput!==void 0)gitArgs.push("-L",`${startInput},${endInput}`);gitArgs.push("--",file3);let result=child_process16.spawnSync("git",gitArgs,{cwd:directory,encoding:"utf-8",timeout:BLAME_TIMEOUT_MS,windowsHide:!0,maxBuffer:5242880,stdio:["ignore","pipe","pipe"]});if(result.error){if("code"in result.error&&result.error.code==="ETIMEDOUT")return JSON.stringify({error:"git blame timed out",file:file3,lineCount:0,lines:[]});let message=result.error instanceof Error?result.error.message:String(result.error);if(message.includes("ENOENT")||message.includes("not found"))return JSON.stringify({error:"git is not available or not in PATH",file:file3,lineCount:0,lines:[]});return JSON.stringify({error:`git execution failed: ${message}`,file:file3,lineCount:0,lines:[]})}if(result.status!==0){let stderr=(result.stderr??"").trim();if(stderr.includes("not a git repository")||stderr.includes("not in a git repository"))return JSON.stringify({error:"not a git repository",file:file3,lineCount:0,lines:[]});if(stderr.includes("no such path")||stderr.includes("did not match any files"))return JSON.stringify({error:`file not tracked by git: ${file3}`,file:file3,lineCount:0,lines:[]});return JSON.stringify({error:`git blame failed: ${stderr||`exit code ${result.status}`}`,file:file3,lineCount:0,lines:[]})}if(result.signal==="SIGTERM"||result.signal==="SIGKILL")return JSON.stringify({error:"git blame timed out",file:file3,lineCount:0,lines:[]});let stdout=result.stdout??"";if(!stdout.trim())return JSON.stringify({error:"no blame output (file may be empty or untracked)",file:file3,lineCount:0,lines:[]});let lines=parsePorcelainBlame(stdout,MAX_OUTPUT_LINES2).map((entry)=>({line:entry.line,sha:entry.sha,author:entry.author,date:Number.parseInt(entry.authorTime,10)>0?new Date(Number.parseInt(entry.authorTime,10)*1000).toISOString().slice(0,10):entry.authorTime,summary:entry.summary,content:entry.content})),resultJson={file:file3,lineCount:lines.length,lines};return JSON.stringify(resultJson,null,2)}});init_zod();init_knowledge_validator();function scanInvisibleFormatChars2(text){let findings=[],matches=text.match(INVISIBLE_FORMAT_CHARS);if(matches!==null&&matches.length>0)for(let match of matches)findings.push({pattern:"invisible_format_chars",field:"external_content",description:`Invisible format characters detected (${matches.length} occurrence(s))`,severity:"error",match:match.slice(0,100)});return findings}function neutralizeThreatPatterns(text,findings){if(findings.length===0)return text;let result=text;for(let finding of findings.filter((f)=>f.severity==="error")){let escapedMatch=finding.match.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),pattern=new RegExp(escapedMatch,"g");result=result.replace(pattern,()=>`[EXTERNAL_CONTENT_THREAT: ${finding.pattern}] ${finding.match} [/EXTERNAL_CONTENT_THREAT]`)}return result}function scanExternalContent(text,options){let trustLevel=options?.trustLevel??"low",maxLength=options?.maxLength??50000;if(text==null)text="";let originalLength=text.length,findings=[];if(text.length>maxLength)findings.push({pattern:"oversized_content",field:"external_content",description:`External content exceeds safe size threshold (${text.length} > ${maxLength} bytes)`,severity:"error",match:`${text.length} bytes`});findings.push(...scanInvisibleFormatChars2(text));for(let entry of PROMPT_INJECTION_PATTERNS){let match=entry.pattern.exec(text);if(match!==null)findings.push({pattern:entry.name,field:"external_content",description:entry.description,severity:entry.severity,match:match[0]})}for(let entry of UNSAFE_INSTRUCTION_PATTERNS){let match=entry.pattern.exec(text);if(match!==null)findings.push({pattern:entry.name,field:"external_content",description:entry.description,severity:entry.severity,match:match[0]})}let promoteWarnings=trustLevel==="low",modulatedFindings=findings.map((f)=>promoteWarnings&&f.severity==="warning"?{...f,severity:"error"}:f),hasErrors=modulatedFindings.some((f)=>f.severity==="error"),hasWarnings=modulatedFindings.some((f)=>f.severity==="warning"),threatLevel;if(hasErrors)threatLevel="error";else if(hasWarnings)threatLevel="warning";else threatLevel="none";let neutralized=neutralizeThreatPatterns(text,modulatedFindings.filter((f)=>f.severity==="error"));return{clean:threatLevel==="none",findings:modulatedFindings,threatLevel,originalLength,neutralized}}init_create_tool();var GITINGEST_TIMEOUT_MS=1e4,GITINGEST_MAX_RESPONSE_BYTES=5242880,GITINGEST_MAX_RETRIES=2,delay=(ms)=>new Promise((resolve73)=>setTimeout(resolve73,ms));async function fetchGitingest(args2){for(let attempt=0;attempt<=GITINGEST_MAX_RETRIES;attempt++)try{let controller=new AbortController,timeoutId=setTimeout(()=>controller.abort(),GITINGEST_TIMEOUT_MS),response=await fetch("https://gitingest.com/api/ingest",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({input_text:args2.url,max_file_size:args2.maxFileSize??50000,pattern:args2.pattern??"",pattern_type:args2.patternType??"exclude"}),signal:controller.signal});if(clearTimeout(timeoutId),response.status>=500&&attempt<GITINGEST_MAX_RETRIES){let backoff=200*2**attempt;await delay(backoff);continue}if(response.status>=400&&response.status<500)throw Error(`gitingest API error: ${response.status} ${response.statusText}`);if(!response.ok)throw Error(`gitingest API error: ${response.status} ${response.statusText}`);let contentLength=Number(response.headers.get("content-length"));if(Number.isFinite(contentLength)&&contentLength>GITINGEST_MAX_RESPONSE_BYTES)throw Error("gitingest response too large");let text,reader=response.body?.getReader();if(reader){let buffer="",decoder=new TextDecoder,totalBytes=0;try{while(!0){let{done,value}=await reader.read();if(done)break;if(totalBytes+=value.byteLength,totalBytes>GITINGEST_MAX_RESPONSE_BYTES)throw Error("gitingest response too large");buffer+=decoder.decode(value,{stream:!0})}buffer+=decoder.decode(),text=buffer}finally{reader.cancel().catch(()=>{})}}else text=await response.text();if(Buffer.byteLength(text)>GITINGEST_MAX_RESPONSE_BYTES)throw Error("gitingest response too large");let data;try{data=JSON.parse(text)}catch{throw Error(`gitingest API returned non-JSON response (${text.length} chars, starts: ${text.slice(0,80)})`)}let combined=`${data.summary}
|
|
5942
5942
|
|
|
@@ -5951,7 +5951,7 @@ ${scanResult.findings.filter((f)=>f.severity==="error").map((f)=>`- ${f.pattern}
|
|
|
5951
5951
|
${scanResult.neutralized}`;return result}catch(error93){if(error93 instanceof DOMException&&(error93.name==="TimeoutError"||error93.name==="AbortError")){if(attempt>=GITINGEST_MAX_RETRIES)throw Error("gitingest request timed out");let backoff=200*2**attempt;await delay(backoff);continue}if(error93 instanceof Error&&error93.message.startsWith("gitingest "))throw error93;if(attempt<GITINGEST_MAX_RETRIES){let backoff=200*2**attempt;await delay(backoff);continue}throw error93}throw Error("gitingest request failed after retries")}var gitingest=createSwarmTool({description:"Fetch a GitHub repository's full content via gitingest.com. Returns summary, directory tree, and file contents optimized for LLM analysis. Use when you need to understand an external repository's structure or code.",args:{url:exports_external.string().describe("GitHub repository URL (e.g., https://github.com/owner/repo)"),maxFileSize:exports_external.number().optional().describe("Maximum file size in bytes to include (default: 50000)"),pattern:exports_external.string().optional().describe("Glob pattern to filter files (e.g., '*.ts' or 'src/**/*.py')"),patternType:exports_external.enum(["include","exclude"]).optional().describe("Whether pattern includes or excludes matching files (default: exclude)")},async execute(args2,_directory,_ctx){return fetchGitingest(args2)}});init_zod();init_create_tool();init_path_security();import*as fs118 from"node:fs";import*as path193 from"node:path";var MAX_FILE_PATH_LENGTH2=500,MAX_SYMBOL_LENGTH=256,MAX_FILE_SIZE_BYTES6=1048576,MAX_CONSUMERS=100,SUPPORTED_EXTENSIONS3=[".ts",".tsx",".js",".jsx",".mjs",".cjs"],BINARY_SIGNATURES2=[0,2303741511,4292411360,1195984440,626017350,1347093252],BINARY_PREFIX_BYTES2=4,BINARY_NULL_CHECK_BYTES2=8192,BINARY_NULL_THRESHOLD2=0.1;function validateFileInput(file3){if(!file3||file3.length===0)return"file is required";if(file3.length>MAX_FILE_PATH_LENGTH2)return`file exceeds maximum length of ${MAX_FILE_PATH_LENGTH2}`;if(containsControlChars(file3))return"file contains control characters";if(containsPathTraversal(file3))return"file contains path traversal";return null}function validateSymbolInput(symbol3){if(symbol3===void 0||symbol3==="")return null;if(symbol3.length>MAX_SYMBOL_LENGTH)return`symbol exceeds maximum length of ${MAX_SYMBOL_LENGTH}`;if(containsControlChars(symbol3))return"symbol contains control characters";if(containsPathTraversal(symbol3))return"symbol contains path traversal";return null}function isBinaryFile3(filePath,buffer){let ext=path193.extname(filePath).toLowerCase();if(ext===".json"||ext===".md"||ext===".txt")return!1;if(buffer.length>=BINARY_PREFIX_BYTES2){let uint323=buffer.subarray(0,BINARY_PREFIX_BYTES2).readUInt32BE(0);for(let sig of BINARY_SIGNATURES2)if(uint323===sig)return!0}let nullCount=0,checkLen=Math.min(buffer.length,BINARY_NULL_CHECK_BYTES2);for(let i=0;i<checkLen;i++)if(buffer[i]===0)nullCount++;return nullCount>checkLen*BINARY_NULL_THRESHOLD2}function parseImports(content,targetFile,targetSymbol){let imports=[],_resolvedTarget;try{_resolvedTarget=path193.resolve(targetFile)}catch{_resolvedTarget=targetFile}let targetBasename=path193.basename(targetFile,path193.extname(targetFile)),targetWithExt=targetFile,targetWithoutExt=targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i,""),normalizedTargetWithExt=path193.normalize(targetWithExt).replace(/\\/g,"/"),normalizedTargetWithoutExt=path193.normalize(targetWithoutExt).replace(/\\/g,"/"),importRegex=/import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;for(let match=importRegex.exec(content);match!==null;match=importRegex.exec(content)){let modulePath=match[1]||match[2]||match[3];if(!modulePath)continue;let lineNum=(content.substring(0,match.index).match(/\n/g)||[]).length+1,matchedString=match[0],importType="named";if(matchedString.includes("* as"))importType="namespace";else if(/^import\s+\{/.test(matchedString))importType="named";else if(/^import\s+\w+\s+from\s+['"`]/.test(matchedString))importType="default";else if(/^import\s+['"`]/m.test(matchedString))importType="sideeffect";else if(matchedString.includes("require("))importType="require";let _normalizedModule=modulePath.replace(/^\.\//,"").replace(/^\.\.\\/,"../"),isMatch=!1,_targetDir=path193.dirname(targetFile),targetExt=path193.extname(targetFile),targetBasenameNoExt=path193.basename(targetFile,targetExt),moduleNormalized=modulePath.replace(/\\/g,"/").replace(/^\.\//,""),moduleName=modulePath.split(/[/\\]/).pop()||"",moduleNameNoExt=moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i,"");if(modulePath===targetBasename||modulePath===targetBasenameNoExt||modulePath===`./${targetBasename}`||modulePath===`./${targetBasenameNoExt}`||modulePath===`../${targetBasename}`||modulePath===`../${targetBasenameNoExt}`||moduleNormalized===normalizedTargetWithExt||moduleNormalized===normalizedTargetWithoutExt||modulePath.endsWith(`/${targetBasename}`)||modulePath.endsWith(`\\${targetBasename}`)||modulePath.endsWith(`/${targetBasenameNoExt}`)||modulePath.endsWith(`\\${targetBasenameNoExt}`)||moduleNameNoExt===targetBasenameNoExt||`./${moduleNameNoExt}`===targetBasenameNoExt||moduleName===targetBasename||moduleName===targetBasenameNoExt)isMatch=!0;if(isMatch&&targetSymbol)if(importType==="namespace"||importType==="sideeffect")isMatch=!1;else{let namedMatch=matchedString.match(/import\s+\{([\s\S]*?)\}\s+from/);if(namedMatch)isMatch=namedMatch[1].split(",").map((s)=>{let parts=s.trim().split(/\s+as\s+/i),originalName=parts[0].trim(),aliasName=parts[1]?.trim();return{original:originalName,alias:aliasName}}).some(({original,alias})=>original===targetSymbol||alias===targetSymbol);else if(importType==="default"){let defaultMatch=matchedString.match(/^import\s+(\w+)\s+from/m);if(defaultMatch)isMatch=defaultMatch[1]===targetSymbol}}if(isMatch)imports.push({line:lineNum,imports:modulePath,importType,raw:matchedString.trim()})}return imports}var SKIP_DIRECTORIES4=new Set(["node_modules",".git","dist","build","out","coverage",".next",".nuxt",".cache","vendor",".svn",".hg"]);function findSourceFiles2(dir,files=[],stats2={skippedDirs:[],skippedFiles:0,fileErrors:[]}){let entries;try{entries=fs118.readdirSync(dir)}catch(e){return stats2.fileErrors.push({path:dir,reason:e instanceof Error?e.message:"readdir failed"}),files}entries.sort((a,b)=>a.toLowerCase().localeCompare(b.toLowerCase()));for(let entry of entries){if(SKIP_DIRECTORIES4.has(entry)){stats2.skippedDirs.push(path193.join(dir,entry));continue}let fullPath=path193.join(dir,entry),stat14;try{stat14=fs118.statSync(fullPath)}catch(e){stats2.fileErrors.push({path:fullPath,reason:e instanceof Error?e.message:"stat failed"});continue}if(stat14.isDirectory())findSourceFiles2(fullPath,files,stats2);else if(stat14.isFile()){let ext=path193.extname(fullPath).toLowerCase();if(SUPPORTED_EXTENSIONS3.includes(ext))files.push(fullPath)}}return files}var imports=createSwarmTool({description:"Find all reverse dependencies (consumers) that import from a given file. Returns JSON with file path, line numbers, and import metadata for each consumer. Use this to understand who depends on a module before refactoring.",args:{file:exports_external.string().describe('Source file path to find importers for (e.g., "./src/utils.ts")'),symbol:exports_external.string().optional().describe('Optional specific symbol to filter imports (e.g., "MyClass")')},async execute(args2,_directory,_ctx){let typedArgs=args2,file3,symbol3;try{if(typedArgs&&typeof typedArgs==="object")file3=typedArgs.file,symbol3=typedArgs.symbol}catch{}if(file3===void 0)return JSON.stringify({error:"invalid arguments: file is required",target:"",symbol:void 0,consumers:[],count:0},null,2);let fileValidationError=validateFileInput(file3);if(fileValidationError){let errorResult={error:`invalid file: ${fileValidationError}`,target:file3,symbol:symbol3,consumers:[],count:0};return JSON.stringify(errorResult,null,2)}let symbolValidationError=validateSymbolInput(symbol3);if(symbolValidationError){let errorResult={error:`invalid symbol: ${symbolValidationError}`,target:file3,symbol:symbol3,consumers:[],count:0};return JSON.stringify(errorResult,null,2)}try{let targetFile=path193.resolve(file3);if(!fs118.existsSync(targetFile)){let errorResult={error:`target file not found: ${file3}`,target:file3,symbol:symbol3,consumers:[],count:0};return JSON.stringify(errorResult,null,2)}if(!fs118.statSync(targetFile).isFile())return JSON.stringify({error:"target must be a file, not a directory",target:file3,symbol:symbol3,consumers:[],count:0},null,2);let baseDir=path193.dirname(targetFile),filesToScan=findSourceFiles2(baseDir,[],{skippedDirs:[],skippedFiles:0,fileErrors:[]}).filter((f)=>f!==targetFile).sort((a,b)=>a.toLowerCase().localeCompare(b.toLowerCase())).slice(0,MAX_CONSUMERS*10),consumers=[],skippedFileCount=0,totalMatchesFound=0;for(let filePath of filesToScan){if(consumers.length>=MAX_CONSUMERS)break;try{if(fs118.statSync(filePath).size>MAX_FILE_SIZE_BYTES6){skippedFileCount++;continue}let buffer=fs118.readFileSync(filePath);if(isBinaryFile3(filePath,buffer)){skippedFileCount++;continue}let content=buffer.toString("utf-8"),fileImports=parseImports(content,targetFile,symbol3);for(let imp of fileImports){if(totalMatchesFound++,consumers.length>=MAX_CONSUMERS)continue;if(consumers.some((c)=>c.file===filePath&&c.line===imp.line))continue;consumers.push({file:filePath,line:imp.line,imports:imp.imports,importType:imp.importType,raw:imp.raw})}}catch(_e){skippedFileCount++}}let result={target:file3,symbol:symbol3,consumers,count:consumers.length},parts=[];if(filesToScan.length>=MAX_CONSUMERS*10)parts.push(`Scanned ${filesToScan.length} files`);if(skippedFileCount>0)parts.push(`${skippedFileCount} skipped (size/binary/errors)`);if(consumers.length>=MAX_CONSUMERS){let hidden=totalMatchesFound-consumers.length;if(hidden>0)parts.push(`Results limited to ${MAX_CONSUMERS} consumers (${hidden} hidden)`);else parts.push(`Results limited to ${MAX_CONSUMERS} consumers`)}if(parts.length>0)result.message=`${parts.join("; ")}.`;return JSON.stringify(result,null,2)}catch(e){let errorResult={error:e instanceof Error?`scan failed: ${e.message||"internal error"}`:"scan failed: unknown error",target:file3,symbol:symbol3,consumers:[],count:0};return JSON.stringify(errorResult,null,2)}}});init_zod();init_config();init_knowledge_reinforcement();init_knowledge_store();init_knowledge_validator();init_manager();init_create_tool();import{randomUUID as randomUUID14}from"node:crypto";var VALID_CATEGORIES2=["process","architecture","tooling","security","testing","debugging","performance","integration","todo","other"],knowledge_add=createSwarmTool({description:"Store a new lesson in the knowledge base for future reference. The lesson will be available for retrieval via knowledge_recall.",args:{lesson:exports_external.string().min(15).max(280).describe("The lesson to store (15-280 characters)"),category:exports_external.enum(VALID_CATEGORIES2).describe("Knowledge category for the lesson"),tags:exports_external.array(exports_external.string()).optional().describe("Optional tags for better searchability"),scope:exports_external.string().optional().describe("Scope of the lesson (global or stack:<name>)"),applies_to_agents:exports_external.array(exports_external.string()).optional().describe('Agent roles this lesson applies to (e.g. ["coder"]). REQUIRED (or applies_to_tools) for the lesson to become active.'),applies_to_tools:exports_external.array(exports_external.string()).optional().describe('Tool names this lesson applies to (e.g. ["edit","bash"]). REQUIRED (or applies_to_agents) for the lesson to become active.'),required_actions:exports_external.array(exports_external.string()).optional().describe("Concrete actions to always take. At least one predicate field (required_actions / forbidden_actions / verification_checks) is REQUIRED for the lesson to become active."),forbidden_actions:exports_external.array(exports_external.string()).optional().describe("Concrete actions to never take."),verification_checks:exports_external.array(exports_external.string()).optional().describe("Checks a reviewer can run to verify compliance.")},execute:async(args2,directory)=>{let lessonInput,categoryInput,tagsInput,scopeInput;try{if(args2&&typeof args2==="object"){let obj2=args2;lessonInput=obj2.lesson,categoryInput=obj2.category,tagsInput=obj2.tags,scopeInput=obj2.scope}}catch{}if(typeof lessonInput!=="string")return JSON.stringify({success:!1,error:"lesson must be a string"});let lesson=lessonInput;if(lesson.length<15||lesson.length>280)return JSON.stringify({success:!1,error:"lesson must be between 15 and 280 characters"});if(typeof categoryInput!=="string")return JSON.stringify({success:!1,error:"category must be a string"});let category=categoryInput;if(!VALID_CATEGORIES2.includes(category))return JSON.stringify({success:!1,error:`category must be one of: ${VALID_CATEGORIES2.join(", ")}`});let tags=[];if(tagsInput!==void 0){if(Array.isArray(tagsInput))tags=tagsInput.filter((t)=>typeof t==="string").slice(0,20)}let scope=typeof scopeInput==="string"&&scopeInput.length>0?scopeInput:"global",strArray=(v)=>Array.isArray(v)?v.filter((x)=>typeof x==="string").slice(0,20):void 0,obj=args2&&typeof args2==="object"?args2:{},actionable={applies_to_agents:strArray(obj.applies_to_agents),applies_to_tools:strArray(obj.applies_to_tools),required_actions:strArray(obj.required_actions),forbidden_actions:strArray(obj.forbidden_actions),verification_checks:strArray(obj.verification_checks)},shape=validateActionableFields(actionable);if(!shape.valid)return JSON.stringify({success:!1,error:`invalid actionability fields: ${shape.errors.join("; ")}`});let project_name="",phase_number=1;try{let plan=await loadPlan(directory);if(project_name=plan?.title??"",typeof plan?.current_phase==="number")phase_number=plan.current_phase}catch{}let entry={id:randomUUID14(),tier:"swarm",lesson,category,tags,scope,confidence:0.5,status:"candidate",confirmed_by:[],project_name,retrieval_outcomes:{applied_count:0,succeeded_after_count:0,failed_after_count:0},schema_version:1,created_at:new Date().toISOString(),updated_at:new Date().toISOString(),auto_generated:!1,hive_eligible:!1,...actionable},config3,dedupThreshold=0.6;try{if(config3=loadPluginConfigWithMeta(directory).config,dedupThreshold=config3.knowledge?.dedup_threshold??0.6,config3.knowledge?.validation_enabled!==!1){let validation2=validateLesson(lesson,[],{category,scope,confidence:0.5});if(!validation2.valid)return JSON.stringify({success:!1,error:`Validation failed: ${validation2.reason}`})}}catch{}let actionability=validateActionability(entry);if(!actionability.actionable){try{await appendUnactionable(directory,entry,actionability.reason??"unactionable")}catch{}return JSON.stringify({success:!1,quarantined:!0,id:entry.id,reason:actionability.reason,hint:"Provide at least one of required_actions/forbidden_actions/verification_checks AND at least one of applies_to_agents/applies_to_tools, then retry."})}try{let maxEntries=config3?.knowledge?.swarm_max_entries??100,duplicateResponse;if(await transactKnowledge(resolveSwarmKnowledgePath(directory),(existingEntries)=>{let activeDuplicate=findActiveSwarmNearDuplicate(lesson,existingEntries,dedupThreshold);if(activeDuplicate){let result=reinforceSwarmKnowledgeEntry(activeDuplicate,{phase_number,confirmed_at:new Date().toISOString(),project_name});return duplicateResponse={id:activeDuplicate.id,reinforced:result.reinforced,idempotent:result.reason==="already_confirmed_phase",inactive:!1},result.reinforced?existingEntries:null}let inactiveDuplicate=findNearDuplicate(lesson,existingEntries,dedupThreshold);if(inactiveDuplicate)return duplicateResponse={id:inactiveDuplicate.id,reinforced:!1,idempotent:!1,inactive:!0},null;let updated=[...existingEntries,entry];if(updated.length>maxEntries)return updated.slice(updated.length-maxEntries);return updated}),duplicateResponse){if(duplicateResponse.inactive)return JSON.stringify({success:!1,id:duplicateResponse.id,message:"near-duplicate of inactive existing entry"});return JSON.stringify({success:!0,id:duplicateResponse.id,reinforced:duplicateResponse.reinforced,idempotent:duplicateResponse.idempotent,message:duplicateResponse.reinforced?"near-duplicate reinforced existing entry":"near-duplicate already confirmed for this phase"})}}catch(err){let message=err instanceof Error?err.message:"Unknown error";return JSON.stringify({success:!1,error:message})}return JSON.stringify({success:!0,id:entry.id,category})}});init_zod();init_knowledge_store();init_knowledge_validator();init_skill_invalidator();init_logger();init_create_tool();var MODES2=["archive","quarantine","purge"],TIERS=["swarm","hive"],knowledge_archive=createSwarmTool({description:"Archive (default), quarantine, or purge a swarm or hive knowledge entry by ID, appending an immutable audit tombstone. 'archive'/'quarantine' set the entry status reversibly and hide it from recall; 'purge' hard-deletes and requires allow_purge:true.",args:{id:exports_external.string().min(1).describe("UUID of the knowledge entry"),tier:exports_external.enum(TIERS).optional().describe("Knowledge tier to modify; default 'swarm'"),reason:exports_external.string().min(1).max(500).describe("Why the entry is being archived/quarantined/purged"),evidence:exports_external.string().max(1000).optional().describe('Supporting evidence (e.g. "ignored 8 times, contradicted by tests")'),mode:exports_external.enum(MODES2).optional().describe("Default 'archive'"),allow_purge:exports_external.boolean().optional().describe("Admin flag required when mode='purge'")},execute:async(args2,directory,ctx)=>{let a=args2??{},id=typeof a.id==="string"?a.id:"";if(!id)return JSON.stringify({success:!1,error:"id must be a non-empty string"});let reason=typeof a.reason==="string"?a.reason:"";if(!reason)return JSON.stringify({success:!1,error:"reason is required"});let evidence=typeof a.evidence==="string"?a.evidence:void 0,tier=a.tier==="hive"?"hive":"swarm",mode=a.mode==="quarantine"||a.mode==="purge"?a.mode:"archive";if(mode==="purge"&&a.allow_purge!==!0)return JSON.stringify({success:!1,error:"purge requires allow_purge:true (admin flag)"});if(mode==="quarantine"){if(tier==="hive")return JSON.stringify({success:!1,error:"quarantine via the archive tool is swarm-only; use tier:'swarm' or the /swarm knowledge quarantine command"});try{if(!(await readKnowledge(resolveSwarmKnowledgePath(directory))).some((e)=>e.id===id))return JSON.stringify({success:!1,message:"entry not found"});let reportedBy=ctx?.agent==="architect"?"architect":"user";await quarantineEntry(directory,id,reason,reportedBy)}catch(err){return JSON.stringify({success:!1,error:err instanceof Error?err.message:"Unknown error during quarantine"})}return JSON.stringify({success:!0,id,tier,mode,status:"quarantined"})}let knowledgePath=tier==="hive"?resolveHiveKnowledgePath():resolveSwarmKnowledgePath(directory),found=!1,previousStatus,now=new Date().toISOString(),resultStatus;try{await transactKnowledge(knowledgePath,(entries)=>{let target=entries.find((e)=>e.id===id);if(!target)return null;if(found=!0,previousStatus=target.status,mode==="purge")return warn(`[knowledge_archive] PURGE: hard-deleting ${tier} entry id=${id} actor=${ctx?.agent??"unknown"} reason=${reason}`),resultStatus="purged",entries.filter((e)=>e.id!==id);if(target.status==="archived")return resultStatus="archived",entries;return resultStatus="archived",entries.map((e)=>e.id===id?{...e,status:"archived",archived_from:target.status,archived_at:now,updated_at:now}:e)})}catch(err){return JSON.stringify({success:!1,error:err instanceof Error?err.message:"Unknown error"})}if(!found)return JSON.stringify({success:!1,message:"entry not found"});return await writeArchiveTombstoneAndInvalidateSkills({directory,entryId:id,tier,actor:ctx?.agent??"unknown",reason,mode,evidence,previousStatus,sourceLabel:"knowledge-archive"}),JSON.stringify({success:!0,id,tier,mode,previous_status:previousStatus,status:resultStatus})}});init_zod();init_config();init_knowledge_store();init_create_tool();import{existsSync as existsSync110}from"node:fs";var DEFAULT_LIMIT=10,MAX_LESSON_LENGTH=200,VALID_CATEGORIES3=["process","architecture","tooling","security","testing","debugging","performance","integration","todo","other"],VALID_STATUSES=["candidate","established","promoted","archived"],DEFAULT_QUERY_STATUSES=new Set(["established","promoted"]),VALID_TIERS=["swarm","hive","all"];function validateTierInput(tier){if(typeof tier!=="string")return null;let normalized=tier.toLowerCase().trim();if(VALID_TIERS.includes(normalized))return normalized;return null}function validateStatusInput(status){if(typeof status!=="string")return null;let normalized=status.toLowerCase().trim();if(VALID_STATUSES.includes(normalized))return normalized;return null}function validateCategoryInput(category){if(typeof category!=="string")return null;let normalized=category.toLowerCase().trim();if(VALID_CATEGORIES3.includes(normalized))return normalized;return null}function validateMinScore(score){if(typeof score==="number"&&!Number.isNaN(score))return Math.max(0,Math.min(1,score));if(typeof score==="string"){let parsed=Number.parseFloat(score);if(!Number.isNaN(parsed))return Math.max(0,Math.min(1,parsed))}return null}function validateLimit(limit){if(typeof limit==="number"&&!Number.isNaN(limit)&&limit>0)return Math.min(limit,100);if(typeof limit==="string"){let parsed=Number.parseInt(limit,10);if(!Number.isNaN(parsed)&&parsed>0)return Math.min(parsed,100)}return DEFAULT_LIMIT}async function readSwarmKnowledge(directory){let swarmPath=resolveSwarmKnowledgePath(directory);if(!existsSync110(swarmPath))return[];return readKnowledge(swarmPath)}async function readHiveKnowledge(){let hivePath=resolveHiveKnowledgePath();if(!existsSync110(hivePath))return[];return readKnowledge(hivePath)}function filterSwarmEntries(entries,filters,suppressedLessons,scopeFilter){return entries.filter((entry)=>{if(filters.status){if(entry.status!==filters.status)return!1}else if(!DEFAULT_QUERY_STATUSES.has(entry.status))return!1;if(filters.category&&entry.category!==filters.category)return!1;if(filters.minScore!==void 0&&entry.confidence<filters.minScore)return!1;if(scopeFilter&&scopeFilter.length>0){let entryScope=entry.scope??"global";if(!scopeFilter.some((pattern)=>entryScope===pattern))return!1}if(suppressedLessons.has(normalize5(entry.lesson)))return!1;return!0})}function filterHiveEntries(entries,filters,suppressedLessons,scopeFilter){return entries.filter((entry)=>{if(filters.status){if(entry.status!==filters.status)return!1}else if(!DEFAULT_QUERY_STATUSES.has(entry.status))return!1;if(filters.category&&entry.category!==filters.category)return!1;if(filters.minScore!==void 0&&entry.confidence<filters.minScore)return!1;if(scopeFilter&&scopeFilter.length>0){let entryScope=entry.scope??"global";if(!scopeFilter.some((pattern)=>entryScope===pattern))return!1}if(suppressedLessons.has(normalize5(entry.lesson)))return!1;return!0})}function truncateLesson3(lesson,maxLength){if(lesson.length<=maxLength)return lesson;return`${lesson.slice(0,maxLength-3)}...`}function formatSwarmEntry(entry){let lines=[];return lines.push(`[${entry.tier.toUpperCase()}] ${entry.id}`),lines.push(` Lesson: ${truncateLesson3(entry.lesson,MAX_LESSON_LENGTH)}`),lines.push(` Category: ${entry.category}`),lines.push(` Status: ${entry.status}`),lines.push(` Confidence: ${entry.confidence.toFixed(2)}`),lines.push(` Confirmed by: ${entry.confirmed_by.length} phase(s)`),lines.push(` Project: ${entry.project_name}`),lines.join(`
|
|
5952
5952
|
`)}function formatHiveEntry(entry){let lines=[];return lines.push(`[${entry.tier.toUpperCase()}] ${entry.id}`),lines.push(` Lesson: ${truncateLesson3(entry.lesson,MAX_LESSON_LENGTH)}`),lines.push(` Category: ${entry.category}`),lines.push(` Status: ${entry.status}`),lines.push(` Confidence: ${entry.confidence.toFixed(2)}`),lines.push(` Encounter Score: ${entry.encounter_score?.toFixed(2)??"N/A"}`),lines.push(` Source Project: ${entry.source_project}`),lines.push(` Confirmed by: ${entry.confirmed_by.length} project(s)`),lines.join(`
|
|
5953
5953
|
`)}var knowledge_query=createSwarmTool({description:"Performs structured filter-based retrieval of swarm knowledge (project-level) or hive knowledge (cross-project). Returns formatted text for human inspection. This is the tool to use when the user knows the CATEGORY, STATUS, or SCORE they want to filter by. For semantic natural-language search, use `knowledge_recall` instead.",args:{tier:exports_external.string().optional().describe("Knowledge tier to query: 'swarm', 'hive', or 'all' (default: 'all')"),status:exports_external.string().optional().describe("Filter by status: 'candidate', 'established', 'promoted', or 'archived'"),category:exports_external.string().optional().describe("Filter by category: 'process', 'architecture', 'tooling', 'security', 'testing', 'debugging', 'performance', 'integration', 'todo', or 'other'"),min_score:exports_external.number().optional().describe("Minimum confidence score filter (0.0-1.0)"),limit:exports_external.number().optional().describe(`Maximum number of results to return (default: ${DEFAULT_LIMIT}, max: 100)`)},async execute(args2,directory){let tierInput,statusInput,categoryInput,minScoreInput,limitInput;try{if(args2&&typeof args2==="object"){let obj=args2;tierInput=obj.tier,statusInput=obj.status,categoryInput=obj.category,minScoreInput=obj.min_score,limitInput=obj.limit}}catch{}let tier=validateTierInput(tierInput)??"all",status=validateStatusInput(statusInput)??null,category=validateCategoryInput(categoryInput)??null,minScore=validateMinScore(minScoreInput)??null,limit=validateLimit(limitInput),filters={status:status??void 0,category:category??void 0,minScore:minScore??void 0},retractionRecords=await readRetractionRecords(directory),suppressedLessons=new Set(retractionRecords.map((record3)=>record3.normalized_lesson).filter((value)=>typeof value==="string"&&value.length>0)),results=[],scopeFilter;try{let{config:config3}=loadPluginConfigWithMeta(directory);scopeFilter=config3.knowledge?.scope_filter}catch{}if(tier==="swarm"||tier==="all"){let swarmEntries=await readSwarmKnowledge(directory),filtered=filterSwarmEntries(swarmEntries,filters,suppressedLessons,scopeFilter);for(let entry of filtered)results.push({entry,tier:"swarm"})}if(tier==="hive"||tier==="all"){let hiveEntries=await readHiveKnowledge(),filtered=filterHiveEntries(hiveEntries,filters,suppressedLessons,scopeFilter);for(let entry of filtered)results.push({entry,tier:"hive"})}let limitedResults=results.slice(0,limit);if(limitedResults.length===0){let tierDesc=tier==="all"?"swarm or hive":tier,filterParts=[];if(status)filterParts.push(`status=${status}`);if(category)filterParts.push(`category=${category}`);if(minScore!==null)filterParts.push(`min_score=${minScore}`);let filterDesc=filterParts.length>0?` with filters: ${filterParts.join(", ")}`:"";return`No knowledge entries found for tier '${tierDesc}'${filterDesc}.`}let outputLines=[];outputLines.push(`=== Knowledge Query Results (${limitedResults.length} of ${results.length} shown) ===`),outputLines.push("");for(let{entry,tier:entryTier}of limitedResults){if(entryTier==="hive")outputLines.push(formatHiveEntry(entry));else outputLines.push(formatSwarmEntry(entry));outputLines.push("")}if(outputLines.push("---"),outputLines.push(`Total matched: ${results.length} | Tier: ${tier} | Limit: ${limit}`),status)outputLines.push(`Status filter: ${status}`);if(category)outputLines.push(`Category filter: ${category}`);if(minScore!==null)outputLines.push(`Min score filter: ${minScore}`);return outputLines.join(`
|
|
5954
|
-
`)}});init_knowledge_recall();init_zod();init_knowledge_events();init_logger();init_create_tool();var IGNORE_REASONS=["not_relevant","stale","superseded","unsafe","too_generic","already_satisfied","other"],PROPOSED_ACTIONS=["archive","revise","quarantine"],VERIFIED_BY=["reviewer","test_engineer","architect"],appliedItem=exports_external.object({id:exports_external.string().min(1),how:exports_external.string().min(1).max(500),evidence_files:exports_external.array(exports_external.string()).optional(),evidence_commands:exports_external.array(exports_external.string()).optional(),verified_by:exports_external.enum(VERIFIED_BY).optional()}),ignoredItem=exports_external.object({id:exports_external.string().min(1),reason:exports_external.enum(IGNORE_REASONS),note:exports_external.string().max(500).optional()}),contradictedItem=exports_external.object({id:exports_external.string().min(1),evidence:exports_external.string().min(1).max(500),proposed_action:exports_external.enum(PROPOSED_ACTIONS)}),newLessonItem=exports_external.object({lesson:exports_external.string().min(15).max(280),category:exports_external.string().min(1),evidence:exports_external.string().max(500).optional(),applies_to_agents:exports_external.array(exports_external.string()).optional(),applies_to_tools:exports_external.array(exports_external.string()).optional(),required_actions:exports_external.array(exports_external.string()).optional(),forbidden_actions:exports_external.array(exports_external.string()).optional(),verification_checks:exports_external.array(exports_external.string()).optional()}),knowledge_receipt=createSwarmTool({description:"File a receipt for knowledge surfaced by a retrieval (by trace_id): which entries were applied (with evidence), ignored (with reason), or contradicted (with proposed remediation), plus any new lessons. Each item is recorded as an immutable knowledge event. Set no_relevant_knowledge:true when a retrieval surfaced nothing useful.",args:{trace_id:exports_external.string().min(1).describe("trace_id from a prior knowledge_recall/injection, or 'none' if no retrieval occurred"),task_id:exports_external.string().optional(),phase:exports_external.string().optional(),applied:exports_external.array(appliedItem).optional(),ignored:exports_external.array(ignoredItem).optional(),contradicted:exports_external.array(contradictedItem).optional(),new_lessons:exports_external.array(newLessonItem).optional(),no_relevant_knowledge:exports_external.boolean().optional()},execute:async(args2,directory,ctx)=>{let a=args2??{},traceId=typeof a.trace_id==="string"?a.trace_id:"";if(!traceId)return JSON.stringify({recorded:!1,error:'trace_id is required (use "none" if no retrieval occurred)'});let taskId=typeof a.task_id==="string"?a.task_id:void 0,phase=typeof a.phase==="string"?a.phase:void 0,applied=Array.isArray(a.applied)?a.applied:[],ignored=Array.isArray(a.ignored)?a.ignored:[],contradicted=Array.isArray(a.contradicted)?a.contradicted:[],newLessons=Array.isArray(a.new_lessons)?a.new_lessons:[],noRelevant=a.no_relevant_knowledge===!0;if(applied.length===0&&ignored.length===0&&contradicted.length===0&&newLessons.length===0&&!noRelevant)return JSON.stringify({recorded:!1,error:"empty receipt: provide at least one applied/ignored/contradicted entry, a new lesson, or set no_relevant_knowledge:true"});let sessionId=ctx?.sessionID??"unknown",agent=ctx?.agent??"unknown",base={trace_id:traceId,session_id:sessionId,phase,task_id:taskId,agent},recordedEventIds=[],emit2=async(event)=>{let written=await recordKnowledgeEvent(directory,event);if(written&&written.event_id!==void 0)recordedEventIds.push(written.event_id)};for(let item of applied)await emit2({type:"applied",...base,knowledge_id:item.id,reason:item.how,evidence:{files:item.evidence_files,commands:item.evidence_commands,summary:item.verified_by?`verified_by=${item.verified_by}`:void 0}});for(let item of ignored)await emit2({type:"ignored",...base,knowledge_id:item.id,reason:item.note?`${item.reason}: ${item.note}`:item.reason});for(let item of contradicted)await emit2({type:"contradicted",...base,knowledge_id:item.id,reason:`${item.proposed_action}: ${item.evidence}`,evidence:{summary:item.evidence}});let newLessonResults=[];for(let item of newLessons){let raw=await knowledge_add.execute({lesson:item.lesson,category:item.category,applies_to_agents:item.applies_to_agents,applies_to_tools:item.applies_to_tools,required_actions:item.required_actions,forbidden_actions:item.forbidden_actions,verification_checks:item.verification_checks},ctx);try{let output=typeof raw==="string"?raw:typeof raw==="object"&&raw!==null&&("output"in raw)&&typeof raw.output==="string"?raw.output:"";newLessonResults.push(JSON.parse(output))}catch{newLessonResults.push({success:!1})}}return log("[knowledge_receipt] completed",{agent,session_id:sessionId,trace_id:traceId,applied:applied.length,ignored:ignored.length,contradicted:contradicted.length,new_lessons:newLessonResults.length,no_relevant_knowledge:noRelevant,event_count:recordedEventIds.length}),JSON.stringify({recorded:!0,trace_id:traceId,applied:applied.length,ignored:ignored.length,contradicted:contradicted.length,new_lessons:newLessonResults,no_relevant_knowledge:noRelevant,event_ids:recordedEventIds})}});init_zod();init_knowledge_store();init_skill_invalidator();init_create_tool();var _internals126={transactKnowledge,writeArchiveTombstoneAndInvalidateSkills},knowledge_remove=createSwarmTool({description:"Delete an outdated swarm knowledge entry by ID (swarm tier only — does not affect hive). Promoted entries cannot be deleted. Double-deletion is idempotent — removing a non-existent entry returns a clear message without error.",args:{id:exports_external.string().min(1).describe("UUID of the knowledge entry to remove")},execute:async(args2,directory)=>{let idInput;try{if(args2&&typeof args2==="object")idInput=args2.id}catch{}if(typeof idInput!=="string"||idInput.length<1)return JSON.stringify({success:!1,error:"id must be a non-empty string"});let id=idInput,swarmPath=resolveSwarmKnowledgePath(directory),found=!1,remaining=0,isPromoted=!1;try{await _internals126.transactKnowledge(swarmPath,(entries)=>{let entryToDelete=entries.find((entry)=>entry.id===id);if(!entryToDelete)return null;if(entryToDelete.status==="promoted")return isPromoted=!0,null;let filtered=entries.filter((entry)=>entry.id!==id);if(filtered.length===entries.length)return null;return found=!0,remaining=filtered.length,filtered})}catch(err){let message=err instanceof Error?err.message:"Unknown error";return JSON.stringify({success:!1,error:message})}if(isPromoted)return JSON.stringify({success:!1,message:"cannot delete promoted entry — this entry has been promoted to cross-project consensus"});if(!found)return JSON.stringify({success:!1,message:"entry not found"});return await _internals126.writeArchiveTombstoneAndInvalidateSkills({directory,entryId:id,tier:"swarm",actor:"knowledge_remove",reason:"hard-delete via knowledge_remove tool",mode:"purge",skipTombstone:!0,sourceLabel:"knowledge-remove"}),JSON.stringify({success:!0,removed:1,remaining})}});init_zod();init_file_locks();init_create_tool();async function executeLeanTurboAcquireLocks(args2){let{directory,laneId,files,agent,taskId,sessionID}=args2;try{let result=await acquireLaneLocks(directory,laneId,files,agent,taskId,sessionID);if(result.acquired)return{success:!0,locks:result.locks};else return{success:!1,conflicts:result.conflicts}}catch(error93){return{success:!1,errors:[error93 instanceof Error?error93.message:String(error93)]}}}var lean_turbo_acquire_locks=createSwarmTool({description:"Acquire file locks for all files in a lane (all-or-nothing). Wraps acquireLaneLocks from src/parallel/file-locks. If any file is already locked, releases all previously acquired locks.",args:{directory:exports_external.string().describe("Project root directory"),laneId:exports_external.string().describe('Unique lane identifier (e.g., "lane-1")'),files:exports_external.array(exports_external.string().min(1)).min(1).describe("Array of file paths to lock"),agent:exports_external.string().describe("Agent name acquiring the locks"),taskId:exports_external.string().describe('Task ID (e.g., "4.1")'),sessionID:exports_external.string().describe("Session ID for the Lean Turbo run")},execute:async(args2,_directory)=>{return JSON.stringify(await executeLeanTurboAcquireLocks({...args2,directory:_directory}),null,2)}});init_zod();init_constants();import*as fs119 from"node:fs";import*as path194 from"node:path";init_create_tool();function readPlanJson2(directory){let planPath=path194.join(directory,".swarm","plan.json");if(!fs119.existsSync(planPath))return null;try{return JSON.parse(fs119.readFileSync(planPath,"utf-8"))}catch{return null}}async function executeLeanTurboPlanLanes(args2){let{directory,phase,scopes}=args2,plan=readPlanJson2(directory);if(!plan)return{success:!1,errors:["plan.json not found in .swarm directory"]};let defaultConfig={...DEFAULT_LEAN_TURBO_CONFIG};try{let lanePlan=planLeanTurboLanes(directory,phase,plan,defaultConfig,scopes);return{success:!0,plan:lanePlan,lanes:lanePlan.lanes,degradedTasks:lanePlan.degradedTasks,serializedTasks:lanePlan.serializedTasks}}catch(error93){return{success:!1,errors:[error93 instanceof Error?error93.message:String(error93)]}}}var lean_turbo_plan_lanes=createSwarmTool({description:"Partition phase tasks into parallel lanes based on file-scope conflicts. Wraps planLeanTurboLanes for Lean Turbo lane planning.",args:{directory:exports_external.string().describe("Project root directory where .swarm/plan.json is located"),phase:exports_external.number().int().positive().describe("Phase number to plan"),scopes:exports_external.record(exports_external.string(),exports_external.array(exports_external.string())).optional().describe("Optional pre-loaded scopes map (taskId -> file paths)")},execute:async(args2,_directory)=>{return JSON.stringify(await executeLeanTurboPlanLanes({...args2,directory:_directory}),null,2)}});init_zod();init_config();init_create_tool();async function executeLeanTurboReview(args2){let{directory,phase,sessionID}=args2,requireDiffSummary=!0;try{let{config:config3}=loadPluginConfigWithMeta(directory);if(config3?.turbo?.lean?.integrated_diff_required!==void 0)requireDiffSummary=config3.turbo.lean.integrated_diff_required}catch{}try{let result=await dispatchPhaseReviewer(directory,phase,sessionID,{requireDiffSummary});return{success:!0,verdict:result.verdict,reason:result.reason,evidencePath:result.evidencePath}}catch(error93){return{success:!1,errors:[error93 instanceof Error?error93.message:String(error93)]}}}var lean_turbo_review=createSwarmTool({description:"Dispatch a read-only reviewer agent to evaluate a completed Lean Turbo phase. Wraps dispatchPhaseReviewer from src/turbo/lean/reviewer. Returns verdict (APPROVED/NEEDS_REVISION/REJECTED), reason, and evidence path.",args:{directory:exports_external.string().describe("Project root directory"),phase:exports_external.number().int().positive().describe("Phase number being reviewed"),sessionID:exports_external.string().describe("Lean Turbo session ID")},execute:async(args2,_directory)=>{return JSON.stringify(await executeLeanTurboReview({...args2,directory:_directory}),null,2)}});init_zod();init_config();init_state2();init_create_tool();var _internals127={LeanTurboRunner,loadPluginConfigWithMeta};async function executeLeanTurboRunPhase(args2){let{directory,phase,sessionID}=args2,runResult=null,runError=null,runner=null;try{let{config:config3}=_internals127.loadPluginConfigWithMeta(directory),leanConfig=config3.turbo?.strategy==="lean"?config3.turbo.lean:void 0;runner=new _internals127.LeanTurboRunner({directory,sessionID,opencodeClient:swarmState.opencodeClient??null,generatedAgentNames:swarmState.generatedAgentNames,leanConfig}),runResult=await runner.runPhase(phase)}catch(error93){runError=error93 instanceof Error?error93:Error(String(error93))}if(runner)try{if(runError||!runResult?.ok)await runner.cleanupAfterFailure();else await runner.cleanupAfterSuccess()}catch(cleanupError){console.error("[lean_turbo_run_phase] Cleanup failed:",cleanupError)}if(runError)return{success:!1,errors:[runError.message]};return{success:runResult.ok,lanes:runResult.lanes,degradedTasks:runResult.degradedTasks,serializedTasks:runResult.serializedTasks,mergeBackFailures:runResult.mergeBackFailures,reason:runResult.reason}}var lean_turbo_run_phase=createSwarmTool({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.",args:{directory:exports_external.string().describe("Project root directory"),phase:exports_external.number().int().positive().describe("Phase number to execute"),sessionID:exports_external.string().describe("Lean Turbo session ID")},execute:async(args2,_directory)=>{let{phase,sessionID}=args2;return JSON.stringify(await executeLeanTurboRunPhase({phase,sessionID,directory:_directory}),null,2)}});init_zod();init_state4();init_create_tool();async function executeLeanTurboRunnerStatus(args2){let{directory,sessionID}=args2;try{let runState=loadLeanTurboRunState(directory,sessionID);if(!runState)return{success:!1,errors:["No Lean Turbo run state found for this session"]};return{success:!0,status:runState.status,phase:runState.phase,lanes:runState.lanes,degradedTasks:runState.degradedTasks,maxParallelCoders:runState.maxParallelCoders,sessionID:runState.sessionID,strategy:runState.strategy}}catch(error93){return{success:!1,errors:[error93 instanceof Error?error93.message:String(error93)]}}}var lean_turbo_runner_status=createSwarmTool({description:"Read Lean Turbo run state from .swarm/turbo-state.json. Returns status, phase, lanes, degraded tasks, and max parallel coders.",args:{directory:exports_external.string().describe("Project root directory where .swarm/turbo-state.json is located"),sessionID:exports_external.string().describe("Session ID for the Lean Turbo run")},execute:async(args2,_directory)=>{return JSON.stringify(await executeLeanTurboRunnerStatus({...args2,directory:_directory}),null,2)}});init_zod();init_constants();init_state4();init_create_tool();async function executeLeanTurboStatus(args2){let{directory,sessionID}=args2;try{let runState=loadLeanTurboRunState(directory,sessionID),defaultConfig={max_parallel_coders:DEFAULT_LEAN_TURBO_CONFIG.max_parallel_coders,require_declared_scope:DEFAULT_LEAN_TURBO_CONFIG.require_declared_scope,degrade_on_risk:DEFAULT_LEAN_TURBO_CONFIG.degrade_on_risk,conflict_policy:DEFAULT_LEAN_TURBO_CONFIG.conflict_policy};if(runState)return{success:!0,strategy:"lean",leanActive:runState.status==="running",config:defaultConfig,status:runState.status,phase:runState.phase,lanes:runState.lanes.length,degradedTasks:runState.degradedTasks.length};return{success:!0,strategy:"lean",leanActive:!1,config:defaultConfig,status:"idle",phase:void 0,lanes:0,degradedTasks:0}}catch(error93){return{success:!1,errors:[error93 instanceof Error?error93.message:String(error93)]}}}var lean_turbo_status=createSwarmTool({description:"Returns Lean Turbo configuration and active status for the current session. Shows whether lean turbo is active, current status, and configuration values.",args:{directory:exports_external.string().describe("Project root directory"),sessionID:exports_external.string().describe("Session ID to check status for")},execute:async(args2,_directory)=>{return JSON.stringify(await executeLeanTurboStatus({...args2,directory:_directory}),null,2)}});init_lint();init_spec_schema();init_effective_spec();init_create_tool();var OBLIGATION_KEYWORDS=["MUST","SHALL","SHOULD","MAY"],FR_ID_PATTERN2=/\bFR-(?!000)\d{3}\b/,OBLIGATION_PATTERN2=/\b(MUST|SHALL|SHOULD|MAY)\b/g,SCENARIO_PATTERN=/^##\s+Scenario\s*:/gm,GIVEN_WHEN_THEN_PATTERN=/\b(Given|When|Then|And|But)[:\s]/gi;function countRequirementsByObligation(content){let counts={MUST:0,SHALL:0,SHOULD:0,MAY:0},lines=content.replace(/```[\s\S]*?```/g,"").replace(/`[^`]*`/g,"").split(`
|
|
5954
|
+
`)}});init_knowledge_recall();init_zod();init_knowledge_events();init_logger();init_create_tool();var IGNORE_REASONS=["not_relevant","stale","superseded","unsafe","too_generic","already_satisfied","other"],PROPOSED_ACTIONS=["archive","revise","quarantine"],VERIFIED_BY=["reviewer","test_engineer","architect"],appliedItem=exports_external.object({id:exports_external.string().min(1),how:exports_external.string().min(1).max(500),evidence_files:exports_external.array(exports_external.string()).optional(),evidence_commands:exports_external.array(exports_external.string()).optional(),verified_by:exports_external.enum(VERIFIED_BY).optional()}),ignoredItem=exports_external.object({id:exports_external.string().min(1),reason:exports_external.enum(IGNORE_REASONS),note:exports_external.string().max(500).optional()}),contradictedItem=exports_external.object({id:exports_external.string().min(1),evidence:exports_external.string().min(1).max(500),proposed_action:exports_external.enum(PROPOSED_ACTIONS)}),newLessonItem=exports_external.object({lesson:exports_external.string().min(15).max(280),category:exports_external.string().min(1),evidence:exports_external.string().max(500).optional(),applies_to_agents:exports_external.array(exports_external.string()).optional(),applies_to_tools:exports_external.array(exports_external.string()).optional(),required_actions:exports_external.array(exports_external.string()).optional(),forbidden_actions:exports_external.array(exports_external.string()).optional(),verification_checks:exports_external.array(exports_external.string()).optional()}),knowledge_receipt=createSwarmTool({description:"File a receipt for knowledge surfaced by a retrieval (by trace_id): which entries were applied (with evidence), ignored (with reason), or contradicted (with proposed remediation), plus any new lessons. Each item is recorded as an immutable knowledge event. Set no_relevant_knowledge:true when a retrieval surfaced nothing useful.",args:{trace_id:exports_external.string().min(1).describe("trace_id from a prior knowledge_recall/injection, or 'none' if no retrieval occurred"),task_id:exports_external.string().optional(),phase:exports_external.string().optional(),applied:exports_external.array(appliedItem).optional(),ignored:exports_external.array(ignoredItem).optional(),contradicted:exports_external.array(contradictedItem).optional(),new_lessons:exports_external.array(newLessonItem).optional(),no_relevant_knowledge:exports_external.boolean().optional()},execute:async(args2,directory,ctx)=>{let a=args2??{},traceId=typeof a.trace_id==="string"?a.trace_id:"";if(!traceId)return JSON.stringify({recorded:!1,error:'trace_id is required (use "none" if no retrieval occurred)'});let taskId=typeof a.task_id==="string"?a.task_id:void 0,phase=typeof a.phase==="string"?a.phase:void 0,applied=Array.isArray(a.applied)?a.applied:[],ignored=Array.isArray(a.ignored)?a.ignored:[],contradicted=Array.isArray(a.contradicted)?a.contradicted:[],newLessons=Array.isArray(a.new_lessons)?a.new_lessons:[],noRelevant=a.no_relevant_knowledge===!0;if(applied.length===0&&ignored.length===0&&contradicted.length===0&&newLessons.length===0&&!noRelevant)return JSON.stringify({recorded:!1,error:"empty receipt: provide at least one applied/ignored/contradicted entry, a new lesson, or set no_relevant_knowledge:true"});let sessionId=ctx?.sessionID??"unknown",agent=ctx?.agent??"unknown",base={trace_id:traceId,session_id:sessionId,phase,task_id:taskId,agent},recordedEventIds=[],emit2=async(event)=>{let written=await recordKnowledgeEvent(directory,event);if(written&&written.event_id!==void 0)recordedEventIds.push(written.event_id)};for(let item of applied)await emit2({type:"applied",...base,knowledge_id:item.id,reason:item.how,evidence:{files:item.evidence_files,commands:item.evidence_commands,summary:item.verified_by?`verified_by=${item.verified_by}`:void 0}});for(let item of ignored)await emit2({type:"ignored",...base,knowledge_id:item.id,reason:item.note?`${item.reason}: ${item.note}`:item.reason});for(let item of contradicted)await emit2({type:"contradicted",...base,knowledge_id:item.id,reason:`${item.proposed_action}: ${item.evidence}`,evidence:{summary:item.evidence}});let newLessonResults=[];for(let item of newLessons){let raw=await knowledge_add.execute({lesson:item.lesson,category:item.category,applies_to_agents:item.applies_to_agents,applies_to_tools:item.applies_to_tools,required_actions:item.required_actions,forbidden_actions:item.forbidden_actions,verification_checks:item.verification_checks},ctx);try{let output=typeof raw==="string"?raw:typeof raw==="object"&&raw!==null&&("output"in raw)&&typeof raw.output==="string"?raw.output:"";newLessonResults.push(JSON.parse(output))}catch{newLessonResults.push({success:!1})}}return log("[knowledge_receipt] completed",{agent,session_id:sessionId,trace_id:traceId,applied:applied.length,ignored:ignored.length,contradicted:contradicted.length,new_lessons:newLessonResults.length,no_relevant_knowledge:noRelevant,event_count:recordedEventIds.length}),JSON.stringify({recorded:!0,trace_id:traceId,applied:applied.length,ignored:ignored.length,contradicted:contradicted.length,new_lessons:newLessonResults,no_relevant_knowledge:noRelevant,event_ids:recordedEventIds})}});init_zod();init_knowledge_store();init_skill_invalidator();init_create_tool();var _internals126={transactKnowledge,writeArchiveTombstoneAndInvalidateSkills},knowledge_remove=createSwarmTool({description:"Delete an outdated swarm knowledge entry by ID (swarm tier only — does not affect hive). Promoted entries cannot be deleted. Double-deletion is idempotent — removing a non-existent entry returns a clear message without error.",args:{id:exports_external.string().min(1).describe("UUID of the knowledge entry to remove")},execute:async(args2,directory)=>{let idInput;try{if(args2&&typeof args2==="object")idInput=args2.id}catch{}if(typeof idInput!=="string"||idInput.length<1)return JSON.stringify({success:!1,error:"id must be a non-empty string"});let id=idInput,swarmPath=resolveSwarmKnowledgePath(directory),found=!1,remaining=0,isPromoted=!1;try{await _internals126.transactKnowledge(swarmPath,(entries)=>{let entryToDelete=entries.find((entry)=>entry.id===id);if(!entryToDelete)return null;if(entryToDelete.status==="promoted")return isPromoted=!0,null;let filtered=entries.filter((entry)=>entry.id!==id);if(filtered.length===entries.length)return null;return found=!0,remaining=filtered.length,filtered})}catch(err){let message=err instanceof Error?err.message:"Unknown error";return JSON.stringify({success:!1,error:message})}if(isPromoted)return JSON.stringify({success:!1,message:"cannot delete promoted entry — this entry has been promoted to cross-project consensus"});if(!found)return JSON.stringify({success:!1,message:"entry not found"});return await _internals126.writeArchiveTombstoneAndInvalidateSkills({directory,entryId:id,tier:"swarm",actor:"knowledge_remove",reason:"hard-delete via knowledge_remove tool",mode:"purge",skipTombstone:!0,sourceLabel:"knowledge-remove"}),JSON.stringify({success:!0,removed:1,remaining})}});init_zod();init_file_locks();init_create_tool();async function executeLeanTurboAcquireLocks(args2){let{directory,laneId,files,agent,taskId,sessionID}=args2;try{let result=await acquireLaneLocks(directory,laneId,files,agent,taskId,sessionID);if(result.acquired)return{success:!0,locks:result.locks};else return{success:!1,conflicts:result.conflicts}}catch(error93){return{success:!1,errors:[error93 instanceof Error?error93.message:String(error93)]}}}var lean_turbo_acquire_locks=createSwarmTool({description:"Acquire file locks for all files in a lane (all-or-nothing). Wraps acquireLaneLocks from src/parallel/file-locks. If any file is already locked, releases all previously acquired locks.",args:{directory:exports_external.string().describe("Project root directory"),laneId:exports_external.string().describe('Unique lane identifier (e.g., "lane-1")'),files:exports_external.array(exports_external.string().min(1)).min(1).describe("Array of file paths to lock"),agent:exports_external.string().describe("Agent name acquiring the locks"),taskId:exports_external.string().describe('Task ID (e.g., "4.1")'),sessionID:exports_external.string().describe("Session ID for the Lean Turbo run")},execute:async(args2,_directory)=>{return JSON.stringify(await executeLeanTurboAcquireLocks({...args2,directory:_directory}),null,2)}});init_zod();init_constants();import*as fs119 from"node:fs";import*as path194 from"node:path";init_create_tool();function readPlanJson2(directory){let planPath=path194.join(directory,".swarm","plan.json");if(!fs119.existsSync(planPath))return null;try{return JSON.parse(fs119.readFileSync(planPath,"utf-8"))}catch{return null}}async function executeLeanTurboPlanLanes(args2){let{directory,phase,scopes}=args2,plan=readPlanJson2(directory);if(!plan)return{success:!1,errors:["plan.json not found in .swarm directory"]};let defaultConfig={...DEFAULT_LEAN_TURBO_CONFIG};try{let lanePlan=planLeanTurboLanes(directory,phase,plan,defaultConfig,scopes);return{success:!0,plan:lanePlan,lanes:lanePlan.lanes,degradedTasks:lanePlan.degradedTasks,serializedTasks:lanePlan.serializedTasks}}catch(error93){return{success:!1,errors:[error93 instanceof Error?error93.message:String(error93)]}}}var lean_turbo_plan_lanes=createSwarmTool({description:"Partition phase tasks into parallel lanes based on file-scope conflicts. Wraps planLeanTurboLanes for Lean Turbo lane planning.",args:{directory:exports_external.string().describe("Project root directory where .swarm/plan.json is located"),phase:exports_external.number().int().positive().describe("Phase number to plan"),scopes:exports_external.record(exports_external.string(),exports_external.array(exports_external.string())).optional().describe("Optional pre-loaded scopes map (taskId -> file paths)")},execute:async(args2,_directory)=>{return JSON.stringify(await executeLeanTurboPlanLanes({...args2,directory:_directory}),null,2)}});init_zod();init_config();init_create_tool();async function executeLeanTurboReview(args2){let{directory,phase,sessionID}=args2,requireDiffSummary=!0;try{let{config:config3}=loadPluginConfigWithMeta(directory);if(config3?.turbo?.lean?.integrated_diff_required!==void 0)requireDiffSummary=config3.turbo.lean.integrated_diff_required}catch{}try{let result=await dispatchPhaseReviewer(directory,phase,sessionID,{requireDiffSummary});return{success:!0,verdict:result.verdict,reason:result.reason,evidencePath:result.evidencePath}}catch(error93){return{success:!1,errors:[error93 instanceof Error?error93.message:String(error93)]}}}var lean_turbo_review=createSwarmTool({description:"Dispatch a read-only reviewer agent to evaluate a completed Lean Turbo phase. Wraps dispatchPhaseReviewer from src/turbo/lean/reviewer. Returns verdict (APPROVED/NEEDS_REVISION/REJECTED), reason, and evidence path.",args:{directory:exports_external.string().describe("Project root directory"),phase:exports_external.number().int().positive().describe("Phase number being reviewed"),sessionID:exports_external.string().describe("Lean Turbo session ID")},execute:async(args2,_directory)=>{return JSON.stringify(await executeLeanTurboReview({...args2,directory:_directory}),null,2)}});init_zod();init_config();init_state2();init_logger();init_create_tool();var _internals127={LeanTurboRunner,loadPluginConfigWithMeta};async function executeLeanTurboRunPhase(args2){let{directory,phase,sessionID}=args2,runResult=null,runError=null,runner=null;try{let{config:config3}=_internals127.loadPluginConfigWithMeta(directory),leanConfig=config3.turbo?.strategy==="lean"?config3.turbo.lean:void 0;runner=new _internals127.LeanTurboRunner({directory,sessionID,opencodeClient:swarmState.opencodeClient??null,generatedAgentNames:swarmState.generatedAgentNames,leanConfig}),runResult=await runner.runPhase(phase)}catch(error93){runError=error93 instanceof Error?error93:Error(String(error93))}if(runner)try{if(runError||!runResult?.ok)await runner.cleanupAfterFailure();else await runner.cleanupAfterSuccess()}catch(cleanupError){log("[lean_turbo_run_phase] Cleanup failed:",cleanupError)}if(runError)return{success:!1,errors:[runError.message]};return{success:runResult.ok,lanes:runResult.lanes,degradedTasks:runResult.degradedTasks,serializedTasks:runResult.serializedTasks,mergeBackFailures:runResult.mergeBackFailures,reason:runResult.reason}}var lean_turbo_run_phase=createSwarmTool({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.",args:{directory:exports_external.string().describe("Project root directory"),phase:exports_external.number().int().positive().describe("Phase number to execute"),sessionID:exports_external.string().describe("Lean Turbo session ID")},execute:async(args2,_directory)=>{let{phase,sessionID}=args2;return JSON.stringify(await executeLeanTurboRunPhase({phase,sessionID,directory:_directory}),null,2)}});init_zod();init_state4();init_create_tool();async function executeLeanTurboRunnerStatus(args2){let{directory,sessionID}=args2;try{let runState=loadLeanTurboRunState(directory,sessionID);if(!runState)return{success:!1,errors:["No Lean Turbo run state found for this session"]};return{success:!0,status:runState.status,phase:runState.phase,lanes:runState.lanes,degradedTasks:runState.degradedTasks,maxParallelCoders:runState.maxParallelCoders,sessionID:runState.sessionID,strategy:runState.strategy}}catch(error93){return{success:!1,errors:[error93 instanceof Error?error93.message:String(error93)]}}}var lean_turbo_runner_status=createSwarmTool({description:"Read Lean Turbo run state from .swarm/turbo-state.json. Returns status, phase, lanes, degraded tasks, and max parallel coders.",args:{directory:exports_external.string().describe("Project root directory where .swarm/turbo-state.json is located"),sessionID:exports_external.string().describe("Session ID for the Lean Turbo run")},execute:async(args2,_directory)=>{return JSON.stringify(await executeLeanTurboRunnerStatus({...args2,directory:_directory}),null,2)}});init_zod();init_constants();init_state4();init_create_tool();async function executeLeanTurboStatus(args2){let{directory,sessionID}=args2;try{let runState=loadLeanTurboRunState(directory,sessionID),defaultConfig={max_parallel_coders:DEFAULT_LEAN_TURBO_CONFIG.max_parallel_coders,require_declared_scope:DEFAULT_LEAN_TURBO_CONFIG.require_declared_scope,degrade_on_risk:DEFAULT_LEAN_TURBO_CONFIG.degrade_on_risk,conflict_policy:DEFAULT_LEAN_TURBO_CONFIG.conflict_policy};if(runState)return{success:!0,strategy:"lean",leanActive:runState.status==="running",config:defaultConfig,status:runState.status,phase:runState.phase,lanes:runState.lanes.length,degradedTasks:runState.degradedTasks.length};return{success:!0,strategy:"lean",leanActive:!1,config:defaultConfig,status:"idle",phase:void 0,lanes:0,degradedTasks:0}}catch(error93){return{success:!1,errors:[error93 instanceof Error?error93.message:String(error93)]}}}var lean_turbo_status=createSwarmTool({description:"Returns Lean Turbo configuration and active status for the current session. Shows whether lean turbo is active, current status, and configuration values.",args:{directory:exports_external.string().describe("Project root directory"),sessionID:exports_external.string().describe("Session ID to check status for")},execute:async(args2,_directory)=>{return JSON.stringify(await executeLeanTurboStatus({...args2,directory:_directory}),null,2)}});init_lint();init_spec_schema();init_effective_spec();init_create_tool();var OBLIGATION_KEYWORDS=["MUST","SHALL","SHOULD","MAY"],FR_ID_PATTERN2=/\bFR-(?!000)\d{3}\b/,OBLIGATION_PATTERN2=/\b(MUST|SHALL|SHOULD|MAY)\b/g,SCENARIO_PATTERN=/^##\s+Scenario\s*:/gm,GIVEN_WHEN_THEN_PATTERN=/\b(Given|When|Then|And|But)[:\s]/gi;function countRequirementsByObligation(content){let counts={MUST:0,SHALL:0,SHOULD:0,MAY:0},lines=content.replace(/```[\s\S]*?```/g,"").replace(/`[^`]*`/g,"").split(`
|
|
5955
5955
|
`);for(let line of lines){if(!line.match(FR_ID_PATTERN2))continue;let matches=line.matchAll(OBLIGATION_PATTERN2);for(let match of matches){let keyword=match[1];if(OBLIGATION_KEYWORDS.includes(keyword))counts[keyword]++}}return counts}function countScenarios(content){let scenarioCount=0,scenarioMatches=content.match(SCENARIO_PATTERN);if(scenarioMatches)scenarioCount+=scenarioMatches.length;let givenWhenThenMatches=content.match(GIVEN_WHEN_THEN_PATTERN);if(givenWhenThenMatches&&givenWhenThenMatches.length>0){if(scenarioCount===0)scenarioCount=(content.match(/\bWhen\s+/gi)||[]).length}return scenarioCount}var lint_spec=createSwarmTool({description:"Reads .swarm/spec.md, lints markdown spec for FR-IDs, obligations, and structure, and returns requirement counts by obligation level, scenario count, and any errors or warnings found.",args:{},async execute(_args,directory){let errors5=[],warnings=[],spec=readEffectiveSpecSync(directory);if(!spec)return JSON.stringify({valid:!1,specMtime:null,requirementCount:{MUST:0,SHALL:0,SHOULD:0,MAY:0,total:0},scenarioCount:0,errors:["spec.md not found and no valid OpenSpec-compatible projection available"],warnings:[]},null,2);let{mtime:specMtime,content}=spec,contentValidation=validateSpecContent(content);if(!contentValidation.valid)for(let issue3 of contentValidation.issues)errors5.push(`Line ${issue3.line}: ${issue3.message}`);let obligationCounts=countRequirementsByObligation(content),totalRequirements=Object.values(obligationCounts).reduce((sum,count)=>sum+count,0),scenarioCount=countScenarios(content),result={valid:errors5.length===0,specMtime,requirementCount:{...obligationCounts,total:totalRequirements},scenarioCount,errors:errors5,warnings:[...warnings,...spec.warnings]};return JSON.stringify(result,null,2)}});init_zod();import*as fs120 from"node:fs";import*as path196 from"node:path";import{spawnSync as spawnSync13}from"node:child_process";import{unlinkSync as unlinkSync28,writeFileSync as writeFileSync30}from"node:fs";import*as path195 from"node:path";function isStaticallyEquivalent(originalCode,mutatedCode){let stripCode=(code)=>{let inMultiLineComment=!1,afterMultiLine=[];for(let line of code.split(`
|
|
5956
5956
|
`))if(!inMultiLineComment){let openIndex=line.indexOf("/*");if(openIndex!==-1){let closeIndex=line.indexOf("*/",openIndex+2);if(closeIndex!==-1)afterMultiLine.push(line.substring(0,openIndex)+line.substring(closeIndex+2));else afterMultiLine.push(line.substring(0,openIndex)),inMultiLineComment=!0}else afterMultiLine.push(line)}else{let closeIndex=line.indexOf("*/");if(closeIndex!==-1)afterMultiLine.push(line.substring(closeIndex+2)),inMultiLineComment=!1}let afterSingleLine=[];for(let line of afterMultiLine){let inString=null,commentStart=-1;for(let i=0;i<line.length;i++){let ch=line[i];if(inString){if(ch==="\\"){i++;continue}if(ch===inString)inString=null}else if(ch==="'"||ch==='"'||ch==="`")inString=ch;else if(ch==="/"&&i+1<line.length&&line[i+1]==="/"){commentStart=i;break}}let processed=commentStart>=0?line.substring(0,commentStart):line;processed=processed.trimEnd(),afterSingleLine.push(processed)}return afterSingleLine.filter((line)=>{let trimmedLower=line.toLowerCase().trim();if(/^console\.(log|debug)\s*(\(|$)/.test(trimmedLower))return!1;if(trimmedLower==="debugger;")return!1;return!0}).filter((line)=>line.trim()!=="").join(`
|
|
5957
5957
|
`)},strippedOriginal=stripCode(originalCode),strippedMutated=stripCode(mutatedCode);return strippedOriginal===strippedMutated}var _internals128={isStaticallyEquivalent,checkEquivalence,batchCheckEquivalence};async function checkEquivalence(patch,originalCode,mutatedCode,llmJudge){if(isStaticallyEquivalent(originalCode,mutatedCode))return{patchId:patch.id,isEquivalent:!0,method:"static",confidence:1,reason:"Mutated code is identical to original after stripping comments, logging, and whitespace"};if(llmJudge){let context=`File: ${patch.filePath}
|
|
@@ -5991,15 +5991,15 @@ Advisory notes: ${advisoryNotes.join("; ")}`:"";return{blocked:!0,reason:"PHASE_
|
|
|
5991
5991
|
${jsdocContent}`;else if(line.includes("*/"))break;else if(functionKeywords.test(line)||line.startsWith("function ")){_foundFunction=!0;break}else if(line.length>0&&!line.startsWith("//")&&!line.startsWith("*"))break}if(jsdocContent){if(/@returns\s*(?:\{[^}]*\})?\s*(?:undefined|[A-Za-z_]\w*)/i.test(jsdocContent))return!0}let braceCount=0,inFunction=!1;for(let i=currentLineIdx;i>=0;i--){let line=lines[i];for(let char of line)if(char==="{")braceCount++,inFunction=!0;else if(char==="}")braceCount--;if(inFunction&&braceCount===0&&i<currentLineIdx)break}let errorReturnPattern=/return\s+["'`][[:ascii:]]*["'`]\s*;/;for(let i=currentLineIdx-1;i>=0&&i>=currentLineIdx-MAX_SEARCH_LINES;i--){let line=lines[i].trim();if(functionKeywords.test(line)||line.startsWith("function "))break;if(errorReturnPattern.test(line))return!0}return!1}function scanWithRegex(content,filePath,denyPatterns,addedLines){let findings=[],lines=content.split(`
|
|
5992
5992
|
`),filterByAddedLines=addedLines!==void 0;for(let i=0;i<lines.length;i++){let line=lines[i],lineNumber=i+1;if(filterByAddedLines&&!addedLines.has(lineNumber))continue;let lineCommentMatch=line.match(/(?:\/\/|#|<!--)\s*(.*)$/);if(lineCommentMatch){let commentText=lineCommentMatch[1];for(let{pattern,rule_id}of denyPatterns.comment)if(pattern.test(commentText)){findings.push({path:filePath,line:lineNumber,kind:"comment",excerpt:line.substring(0,100),rule_id});break}}let blockCommentMatch=line.match(/\/\*([\s\S]*?)\*\//);if(blockCommentMatch){let commentText=blockCommentMatch[1];for(let{pattern,rule_id}of denyPatterns.comment)if(pattern.test(commentText)){findings.push({path:filePath,line:lineNumber,kind:"comment",excerpt:line.substring(0,100),rule_id});break}}let stringMatches=line.match(/(["'`])(?:(?!\1)[^\\]|\\.)*\1/g);if(stringMatches){for(let stringContent of stringMatches)for(let{pattern,rule_id}of denyPatterns.string)if(pattern.test(stringContent)){findings.push({path:filePath,line:lineNumber,kind:"string",excerpt:line.substring(0,100),rule_id});break}}for(let{pattern,rule_id}of denyPatterns.code)if(!(line.includes("describe(")||line.includes("it(")||line.includes("test(")||line.includes("expect("))&&pattern.test(line)){if(rule_id==="placeholder/code-stub-return"&&/return\s+undefined\s*;/.test(line)){if(isValidationPattern(lines,i))continue}findings.push({path:filePath,line:lineNumber,kind:"function_body",excerpt:line.substring(0,100),rule_id})}}return findings}async function scanWithParser(content,filePath,denyPatterns,addedLines){let findings=[],regexFindings=scanWithRegex(content,filePath,denyPatterns,addedLines);findings.push(...regexFindings);let parser=await getParserForFile(filePath);if(!parser)return findings;try{let walkNode=function(node){let{type:nodeType,text:nodeText}=node,lineNum=node.startPosition.row+1;if(filterByAddedLines?addedLines.has(lineNum):!0){if(nodeType==="comment"||nodeType==="line_comment"||nodeType==="block_comment"||nodeType==="documentation_comment"||nodeType==="doc_comment")for(let{pattern,rule_id}of denyPatterns.comment){let key=`${lineNum}:${rule_id}`;if(!seenKeys.has(key)&&pattern.test(nodeText))seenKeys.add(key),findings.push({path:filePath,line:lineNum,kind:"comment",excerpt:nodeText.substring(0,100),rule_id})}if(nodeType==="string"||nodeType==="template_string"||nodeType==="string_literal"||nodeType==="string_fragment")for(let{pattern,rule_id}of denyPatterns.string){let key=`${lineNum}:${rule_id}`;if(!seenKeys.has(key)&&pattern.test(nodeText))seenKeys.add(key),findings.push({path:filePath,line:lineNum,kind:"string",excerpt:nodeText.substring(0,100),rule_id})}}if(node.children)for(let child of node.children)walkNode(child)},tree=parser.parse(content);if(!tree||!tree.rootNode)return findings;let seenKeys=new Set;for(let f of findings)seenKeys.add(`${f.line}:${f.rule_id}`);let filterByAddedLines=addedLines!==void 0;walkNode(tree.rootNode),tree.delete()}catch{}return findings}async function placeholderScan(input,directory){let{changed_files,allow_globs,deny_patterns,added_lines,sentinel_allowlist,allow_sentinels}=input,sentinelPatterns=[...DEFAULT_SENTINEL_ALLOWLIST,...sentinel_allowlist??allow_sentinels??[]].map((sentinel)=>new RegExp(escapeRegex2(sentinel),"i"));function isSentinelAllowed(excerpt){for(let pattern of sentinelPatterns)if(pattern.test(excerpt))return!0;return!1}let commentPatterns=DEFAULT_COMMENT_PATTERNS,stringPatterns=DEFAULT_STRING_PATTERNS,codePatterns=DEFAULT_CODE_PATTERNS;if(deny_patterns&&deny_patterns.length>0)commentPatterns=deny_patterns.map((p)=>({pattern:new RegExp(`\\b${escapeRegex2(p)}\\b`,"i"),rule_id:`placeholder/custom-${p.toLowerCase()}`})),stringPatterns=[],codePatterns=[];let denyPatterns={comment:commentPatterns,string:stringPatterns,code:codePatterns},findings=[],filesScanned=0,filesWithFindings=new Set;for(let filePath of changed_files){let fullPath=path211.isAbsolute(filePath)?filePath:path211.resolve(directory,filePath),resolvedDirectory=path211.resolve(directory);if(!fullPath.startsWith(resolvedDirectory+path211.sep)&&fullPath!==resolvedDirectory)continue;if(!fs133.existsSync(fullPath))continue;if(isAllowedByGlobs(filePath,allow_globs))continue;let relativeFilePath=path211.relative(directory,fullPath).replace(/\\/g,"/");if(FILE_ALLOWLIST.some((allowed)=>relativeFilePath.endsWith(allowed)))continue;let content;try{if(fs133.statSync(fullPath).size>MAX_FILE_SIZE)continue;content=fs133.readFileSync(fullPath,"utf-8")}catch{continue}if(content.includes("\x00"))continue;let isScaffold=isScaffoldFile(filePath);if(isTestFile2(filePath)&&!isScaffold)continue;filesScanned++;let addedLinesForFile=normalizeAddedLines(added_lines?.[relativeFilePath]??added_lines?.[filePath]),fileFindings;if(isPlanFile(filePath))fileFindings=scanPlanFileForPlaceholders(content,filePath,addedLinesForFile);else if(isParserSupported(filePath))fileFindings=await scanWithParser(content,filePath,denyPatterns,addedLinesForFile);else fileFindings=scanWithRegex(content,filePath,denyPatterns,addedLinesForFile);let filteredFindings=sentinelPatterns.length>0?fileFindings.filter((f)=>!isSentinelAllowed(f.excerpt)):fileFindings;if(filteredFindings.length>0)findings.push(...filteredFindings),filesWithFindings.add(filePath)}let verdict=findings.length>0?"fail":"pass";return await saveEvidence(directory,"placeholder_scan",{task_id:"placeholder_scan",type:"placeholder",timestamp:new Date().toISOString(),agent:"placeholder_scan",verdict,summary:`Scanned ${filesScanned} files, found ${findings.length} placeholder(s)`,files_scanned:filesScanned,findings_count:findings.length,files_with_findings:filesWithFindings.size,findings}),{verdict,findings,summary:{files_scanned:filesScanned,findings_count:findings.length,files_with_findings:filesWithFindings.size}}}var placeholder_scan=createSwarmTool({description:"Scan source files for placeholder content (TODO/FIXME comments, stub implementations, unimplemented functions). Returns JSON with findings grouped by file and rule.",args:{changed_files:exports_external.array(exports_external.string()).describe("Files to scan for placeholders"),allow_globs:exports_external.array(exports_external.string()).optional().describe("Globs to allow (skip scanning)"),deny_patterns:exports_external.array(exports_external.string()).optional().describe("Custom deny patterns to search for"),added_lines:exports_external.record(exports_external.string(),exports_external.array(exports_external.number().int().positive())).optional().describe("Optional map of file path to PR-added line numbers"),sentinel_allowlist:exports_external.array(exports_external.string()).optional().describe("Intentional sentinel strings that suppress matching findings"),allow_sentinels:exports_external.array(exports_external.string()).optional().describe("Deprecated alias for sentinel_allowlist")},async execute(args2,directory){let result=await placeholderScan(args2,directory);return JSON.stringify(result)}});import*as path215 from"node:path";init_zod();init_manager2();init_utils();init_bun_compat();init_create_tool();init_lint();init_zod();init_manager2();init_create_tool();function validateInput(input){if(!input||typeof input!=="object")return{valid:!1,error:"Input must be an object"};let typedInput=input;if(!Array.isArray(typedInput.changed_files))return{valid:!1,error:"changed_files must be an array"};for(let file3 of typedInput.changed_files)if(typeof file3!=="string")return{valid:!1,error:"changed_files must contain strings"};if(typedInput.config!==void 0){if(!typedInput.config||typeof typedInput.config!=="object")return{valid:!1,error:"config must be an object if provided"}}return{valid:!0}}async function qualityBudget(input,directory){let validation2=validateInput(input);if(!validation2.valid)throw Error(`Invalid input: ${validation2.error}`);let{changed_files:changedFiles,config:config3}=input,thresholds={enabled:config3?.enabled??!0,max_complexity_delta:config3?.max_complexity_delta??5,max_public_api_delta:config3?.max_public_api_delta??10,max_duplication_ratio:config3?.max_duplication_ratio??0.05,min_test_to_code_ratio:config3?.min_test_to_code_ratio??0.3,enforce_on_globs:config3?.enforce_on_globs??["src/**"],exclude_globs:config3?.exclude_globs??["docs/**","tests/**","**/*.test.*"]};if(!thresholds.enabled)return{verdict:"pass",metrics:{complexity_delta:0,public_api_delta:0,duplication_ratio:0,test_to_code_ratio:0,files_analyzed:[],thresholds,violations:[]},violations:[],summary:{files_analyzed:0,violations_count:0,errors_count:0,warnings_count:0}};let metrics=await computeQualityMetrics(changedFiles,thresholds,directory),errorsCount=metrics.violations.filter((v)=>v.severity==="error").length,warningsCount=metrics.violations.filter((v)=>v.severity==="warning").length,verdict=errorsCount>0?"fail":"pass";return await saveEvidence(directory,"quality_budget",{task_id:"quality_budget",type:"quality_budget",timestamp:new Date().toISOString(),agent:"quality_budget",verdict,summary:`Quality budget check: ${metrics.files_analyzed.length} files analyzed, ${metrics.violations.length} violation(s) found (${errorsCount} errors, ${warningsCount} warnings)`,metrics:{complexity_delta:metrics.complexity_delta,public_api_delta:metrics.public_api_delta,duplication_ratio:metrics.duplication_ratio,test_to_code_ratio:metrics.test_to_code_ratio},thresholds:{max_complexity_delta:thresholds.max_complexity_delta,max_public_api_delta:thresholds.max_public_api_delta,max_duplication_ratio:thresholds.max_duplication_ratio,min_test_to_code_ratio:thresholds.min_test_to_code_ratio},violations:metrics.violations.map((v)=>({type:v.type,message:v.message,severity:v.severity,files:v.files})),files_analyzed:metrics.files_analyzed}),{verdict,metrics,violations:metrics.violations,summary:{files_analyzed:metrics.files_analyzed.length,violations_count:metrics.violations.length,errors_count:errorsCount,warnings_count:warningsCount}}}var quality_budget=createSwarmTool({description:"Enforce maintainability budgets for changed files. Computes quality metrics (complexity, API surface, duplication, test coverage) and compares against configured thresholds. Returns JSON with metrics, violations, and verdict.",args:{changed_files:exports_external.array(exports_external.string()).describe("Files to check against quality budgets"),config:exports_external.object({enabled:exports_external.boolean().optional(),max_complexity_delta:exports_external.number().optional(),max_public_api_delta:exports_external.number().optional(),max_duplication_ratio:exports_external.number().optional(),min_test_to_code_ratio:exports_external.number().optional(),enforce_on_globs:exports_external.array(exports_external.string()).optional(),exclude_globs:exports_external.array(exports_external.string()).optional()}).optional().describe("Quality budget thresholds")},async execute(args2,directory){let result=await _internals134.qualityBudget(args2,directory);return JSON.stringify(result)}}),_internals134={qualityBudget};init_zod();init_manager2();init_detector();import*as fs136 from"node:fs";import*as path214 from"node:path";import{extname as extname20}from"node:path";var cRules=[{id:"sast/c-buffer-overflow",name:"Buffer overflow vulnerability",severity:"critical",languages:["c","cpp"],description:"strcpy/strcat to fixed-size buffer without bounds checking",remediation:"Use strncpy, snprintf, or safer alternatives that include size limits.",pattern:/\b(?:strcpy|strcat)\s*\(\s*[a-zA-Z_]/},{id:"sast/c-gets",name:"Unsafe gets() usage",severity:"critical",languages:["c","cpp"],description:"gets() does not check buffer bounds - removed from C11",remediation:"Use fgets() with proper buffer size instead of gets().",pattern:/\bgets\s*\(/},{id:"sast/c-scanf",name:"Unsafe scanf usage",severity:"high",languages:["c","cpp"],description:"scanf without width specifier can cause buffer overflow",remediation:'Use width specifiers: scanf("%99s", buffer) for a 100-byte buffer.',pattern:/\bscanf\s*\(\s*["'][^%]*%s["']/},{id:"sast/c-strlen",name:"Unsafe strlen in loop",severity:"medium",languages:["c","cpp"],description:"strlen() called in loop condition can lead to performance issues",remediation:"Cache strlen result before loop or use a pointer approach.",pattern:/for\s*\([^)]*strlen\s*\(/},{id:"sast/c-sprintf",name:"Unsafe sprintf usage",severity:"high",languages:["c","cpp"],description:"sprintf does not check buffer bounds",remediation:"Use snprintf which includes buffer size.",pattern:/\bsprintf\s*\(\s*[a-zA-Z_]/},{id:"sast/c-strdup",name:"Memory leak via strdup",severity:"low",languages:["c","cpp"],description:"strdup allocates memory that must be freed",remediation:"Ensure all strdup results are freed to prevent memory leaks.",pattern:/\bstrdup\s*\(/},{id:"sast/c-atoi",name:"Unsafe atoi usage",severity:"medium",languages:["c","cpp"],description:"atoi does not report errors, returns 0 for invalid input",remediation:"Use strtol or strtoul which provide error reporting.",pattern:/\b(?:atoi|atol|atof)\s*\(/},{id:"sast/c-format-string",name:"Format string vulnerability",severity:"high",languages:["c","cpp"],description:"User input as format string can lead to information disclosure",remediation:'Never use user input as format string: printf("%s", userInput) not printf(userInput).',pattern:/printf\s*\(\s*\$_/},{id:"sast/c-weak-random",name:"Weak random number generation",severity:"medium",languages:["c","cpp"],description:"Using rand() for security-critical randomness",remediation:"Use cryptographic random: getrandom(), arc4random(), or /dev/urandom.",pattern:/\brand\s*\(\s*\)/}];var csharpRules=[{id:"sast/cs-command-injection",name:"Command injection via Process.Start",severity:"critical",languages:["csharp"],description:"Process.Start allows command injection",remediation:"Use ProcessStartInfo with Arguments property, or sanitize input thoroughly.",pattern:/Process\.Start/,validate:(_match,context)=>{return!/UseShellExecute\s*=\s*false/i.test(context.content)}},{id:"sast/cs-sqli",name:"Potential SQL injection",severity:"critical",languages:["csharp"],description:"String concatenation in SQL query can lead to SQL injection",remediation:"Use parameterized queries or an ORM. Never concatenate user input into SQL.",pattern:/\.Execute.*\+/},{id:"sast/cs-xss",name:"Potential XSS vulnerability",severity:"high",languages:["csharp"],description:"User input in HTML response without encoding",remediation:"Use HttpUtility.HtmlEncode() or a templating engine with auto-escaping.",pattern:/Response\.Write\s*\(\s*(?:Request|Form|QueryString)/i},{id:"sast/cs-deserialization",name:"Unsafe deserialization",severity:"critical",languages:["csharp"],description:"BinaryFormatter can deserialize malicious objects",remediation:"Use System.Text.Json or Newtonsoft.Json for serialization. Never use BinaryFormatter.",pattern:/BinaryFormatter/},{id:"sast/cs-hardcoded-secret",name:"Hardcoded secret detected",severity:"critical",languages:["csharp"],description:"Potential hardcoded API key, password, or token detected",remediation:"Move secrets to configuration or environment variables.",pattern:/(?:api_key|password|secret|token|auth)[_-]?\w*\s*=\s*["'][a-zA-Z0-9_-]{10,}["']/i},{id:"sast/cs-path-traversal",name:"Path traversal vulnerability",severity:"high",languages:["csharp"],description:"File path from user input used without validation",remediation:"Use Path.GetFullPath and validate the result stays within expected directory.",pattern:/File\.(?:Read|Write|Open|AllLines)\s*\(\s*(?:Request|Form|QueryString)/i},{id:"sast/cs-xml-xxe",name:"XML External Entity vulnerability",severity:"high",languages:["csharp"],description:"XML reader without XXE protection",remediation:"Disable DTD processing: XmlReaderSettings.DtdProcessing = DtdProcessing.Prohibit",pattern:/XmlReader\.Create\s*\(/},{id:"sast/cs-weak-random",name:"Weak random for security purposes",severity:"medium",languages:["csharp"],description:"Using Random class for cryptographic randomness",remediation:"Use RandomNumberGenerator or cryptographic random: System.Security.Cryptography.RandomNumberGenerator",pattern:/new\s+Random\s*\(/},{id:"sast/cs-hardcoded-connection-string",name:"Hardcoded connection string",severity:"high",languages:["csharp"],description:"Hardcoded database connection string with credentials",remediation:"Store connection strings in configuration files with encryption or use Azure Key Vault.",pattern:/ConnectionString\s*=\s*["'][^"']*(?:uid|user|password|pwd)[^"']*["']/i},{id:"sast/cs-weak-encryption",name:"Weak encryption algorithm",severity:"high",languages:["csharp"],description:"Using weak encryption like DES or RC4",remediation:"Use AES-256 or stronger. Avoid DES, RC4, and other deprecated algorithms.",pattern:/DESCryptoServiceProvider/},{id:"sast/cs-ssl-validation-bypass",name:"SSL/TLS certificate validation bypass",severity:"critical",languages:["csharp"],description:"ServicePointManager or WebRequest with disabled certificate validation",remediation:"Never disable certificate validation in production.",pattern:/ServerCertificateValidationCallback\s*=\s*(?:AcceptAll|true)/}];var goRules=[{id:"sast/go-hardcoded-secret",name:"Hardcoded secret detected",severity:"critical",languages:["go"],description:"Potential hardcoded API key, password, or token detected",remediation:"Move secrets to environment variables using os.Getenv() or a secrets manager.",pattern:/(?:api[_-]?key|apiKey|ApiKey|apikey|api[_-]?token|apiToken|auth[_-]?token|authToken|password|passwd|secret|token|auth)[_-]?\w*\s*(?::=|=|:)\s*["'][a-zA-Z0-9_-]{10,}["']/i},{id:"sast/go-weak-tls",name:"Insecure TLS configuration",severity:"medium",languages:["go"],description:"tls.Config with InsecureSkipVerify allows MITM attacks",remediation:"Set InsecureSkipVerify to false in production. Use proper certificate validation.",pattern:/InsecureSkipVerify\s*:\s*true/},{id:"sast/go-shell-injection",name:"Shell injection via os/exec",severity:"critical",languages:["go"],description:"exec.Command with shell interpretation allows command injection",remediation:"Use exec.Command with separate arguments, avoiding shell interpretation. Never pass user input directly to command execution.",pattern:/exec\.Command/},{id:"sast/go-template-injection",name:"Template injection risk",severity:"high",languages:["go"],description:"html/template used with variable content - potential XSS",remediation:"Ensure user input is properly escaped. Use template.HTMLEscapeString() or auto-escaping features.",pattern:/template\.HTML\s*\(/},{id:"sast/go-pprof",name:"pprof endpoint exposed",severity:"medium",languages:["go"],description:"pprof debugging endpoints can expose sensitive information",remediation:"Only enable pprof in development. Ensure production does not expose /debug/pprof.",pattern:/net\/http\/pprof/}];var javaRules=[{id:"sast/java-command-injection",name:"Command injection via Runtime.exec",severity:"critical",languages:["java"],description:"Runtime.exec() with unsanitized input can lead to command injection",remediation:"Avoid Runtime.exec(). Use ProcessBuilder with separate arguments, or validate/sanitize input thoroughly.",pattern:/\.exec\s*\(/},{id:"sast/java-deserialization",name:"Unsafe object deserialization",severity:"high",languages:["java"],description:"ObjectInputStream.readObject() can lead to deserialization vulnerabilities",remediation:"Use a safe serialization format like JSON. If Java serialization is required, validate the class whitelist.",pattern:/readObject\s*\(\s*\)/},{id:"sast/java-xss",name:"Potential XSS vulnerability",severity:"high",languages:["java"],description:"Unescaped user input in HTTP response can lead to XSS",remediation:"Use OWASP Java Encoder or similar library to encode output. Enable CSRF protection.",pattern:/getWriter\(\)\.write\s*\(/},{id:"sast/java-hardcoded-secret",name:"Hardcoded secret detected",severity:"critical",languages:["java"],description:"Potential hardcoded API key, password, or token detected",remediation:"Move secrets to environment variables or a secure configuration manager.",pattern:/(?:api_key|password|secret|token|auth)[_-]?\w*\s*=\s*["'][a-zA-Z0-9_-]{10,}["']/i},{id:"sast/java-xxe",name:"XML External Entity (XXE) vulnerability",severity:"high",languages:["java"],description:"XML parser configured without XXE protection",remediation:'Configure XML parser to disable external entities: setFeature("http://apache.org/xml/features/disallow-doctype-decl", true)',pattern:/DocumentBuilderFactory\.newInstance/},{id:"sast/java-path-traversal",name:"Path traversal vulnerability",severity:"high",languages:["java"],description:"File path from user input used without validation",remediation:"Validate and sanitize file paths. Use canonical paths and allow-list validation.",pattern:/new\s+File\s*\(\s*(?:request|param)/i},{id:"sast/java-sqli",name:"Potential SQL injection",severity:"critical",languages:["java"],description:"String concatenation in SQL query can lead to SQL injection",remediation:"Use PreparedStatement with parameterized queries. Never concatenate user input into SQL.",pattern:/createStatement\s*\(\s*\).*\+/},{id:"sast/java-weak-crypto",name:"Weak cryptographic algorithm",severity:"medium",languages:["java"],description:"Using weak cryptographic algorithms (MD5, SHA1, DES)",remediation:"Use strong algorithms like AES-256, SHA-256, or stronger. Avoid MD5 and SHA-1 for security purposes.",pattern:/MessageDigest\.getInstance\s*\(\s*["'](?:MD5|SHA-?1|DES)["']/i},{id:"sast/java-trust-manager",name:"Weak SSL/TLS trust manager",severity:"high",languages:["java"],description:"Custom TrustManager that accepts all certificates - vulnerable to MITM",remediation:"Use proper certificate validation. Never implement a TrustManager that accepts all certificates.",pattern:/TrustManager\s*\{\s*public\s+void\s+checkClientTrusted/}];var javascriptRules=[{id:"sast/js-eval",name:"Dangerous eval() Usage",severity:"high",languages:["javascript","typescript"],description:"Dangerous use of eval() detected - allows arbitrary code execution",remediation:"Avoid using eval(). If you must parse dynamic content, use JSON.parse() or a proper parser instead.",pattern:/\beval\s*\(/},{id:"sast/js-dangerous-function",name:"Dangerous new Function()",severity:"high",languages:["javascript","typescript"],description:"Dangerous use of new Function() detected - allows arbitrary code execution",remediation:"Avoid using new Function(). Use a safer alternative like JSON.parse() or a proper expression parser.",pattern:/\bnew\s+Function\s*\(/},{id:"sast/js-command-injection",name:"Command Injection via child_process",severity:"critical",languages:["javascript","typescript"],description:"Potential command injection via child_process.exec() with unsanitized input",remediation:"Never pass user input directly to exec(). Use execFile() with arguments array or sanitize input thoroughly.",pattern:/exec\s*\(\s*(?:[`'"]|\w)/,validate:(_match,_context)=>{return!0}},{id:"sast/js-set-timeout-string",name:"setTimeout/setInterval with string",severity:"high",languages:["javascript","typescript"],description:"setTimeout/setInterval called with string argument - similar to eval()",remediation:'Use function references instead of strings: setTimeout(() => ..., 1000) instead of setTimeout("...", 1000)',pattern:/(?:setTimeout|setInterval)\s*\(\s*['"`]/},{id:"sast/js-innerhtml",name:"Dangerous innerHTML usage",severity:"medium",languages:["javascript","typescript"],description:"Potential XSS via innerHTML - user input may be injected into DOM",remediation:"Use textContent instead of innerHTML, or sanitize input with a library like DOMPurify.",pattern:/\.innerHTML\s*=/},{id:"sast/js-document-write",name:"Dangerous document.write usage",severity:"medium",languages:["javascript","typescript"],description:"document.write() can introduce XSS vulnerabilities",remediation:"Use DOM manipulation methods (createElement, appendChild, textContent) instead.",pattern:/document\.write\s*\(/},{id:"sast/js-postmessage",name:"Unsafely handling postMessage",severity:"medium",languages:["javascript","typescript"],description:"postMessage event listener without origin validation",remediation:"Always validate the origin in postMessage event handlers: event.origin === expectedOrigin",pattern:/addEventListener\s*\(\s*['"]message['"]/},{id:"sast/js-hardcoded-secret",name:"Hardcoded secret detected",severity:"critical",languages:["javascript","typescript"],description:"Potential hardcoded API key, password, or token detected",remediation:"Move secrets to environment variables or a secure secrets manager.",pattern:/(?:api_key|password|secret|token|auth)[_-]?\w*\s*[:=]\s*['"][a-zA-Z0-9_-]{20,}['"]/i}];var phpRules=[{id:"sast/php-unserialize",name:"Unsafe unserialize",severity:"critical",languages:["php"],description:"unserialize() on untrusted data can lead to object injection",remediation:"Use json_decode() instead of unserialize(). If you must use unserialize, validate the input with allowed_classes.",pattern:/unserialize\s*\(\s*\$_/},{id:"sast/php-command-injection",name:"Command injection",severity:"critical",languages:["php"],description:"exec(), system(), or shell_exec() with user input can lead to command injection",remediation:"Never pass user input to shell functions. Use escapeshellarg() or escapeshellcmd() for any shell commands.",pattern:/(?:exec|system|shell_exec|passthru)\s*\(\s*\$_/},{id:"sast/php-eval",name:"Dangerous eval() usage",severity:"critical",languages:["php"],description:"eval() allows arbitrary code execution",remediation:"Avoid eval(). Use a safer alternative for dynamic code execution.",pattern:/\beval\s*\(/},{id:"sast/php-include",name:"Dynamic file inclusion",severity:"high",languages:["php"],description:"include/require with user input can lead to remote/local file inclusion",remediation:"Never include files based on user input. Use a whitelist of allowed files.",pattern:/(?:include|require|include_once|require_once)\s*\(\s*\$_/},{id:"sast/php-xss",name:"Potential XSS vulnerability",severity:"high",languages:["php"],description:"User input in HTML output without escaping",remediation:"Use htmlspecialchars() or a templating engine with auto-escaping.",pattern:/(?:echo|print)\s+\$_(?:GET|POST|REQUEST|COOKIE)/},{id:"sast/php-sqli",name:"Potential SQL injection",severity:"critical",languages:["php"],description:"String concatenation in SQL query can lead to SQL injection",remediation:"Use prepared statements (PDO prepare/execute or mysqli prepared statements). Never concatenate user input into SQL.",pattern:/mysql_query\s*\([^)]*\$_/i},{id:"sast/php-file-read",name:"Arbitrary file read",severity:"high",languages:["php"],description:"file_get_contents or fopen with user input can read arbitrary files",remediation:"Validate and sanitize file paths. Use a whitelist of allowed directories.",pattern:/(?:file_get_contents|fopen|readfile|file)\s*\(\s*\$_/},{id:"sast/php-assert",name:"Assert with user input",severity:"medium",languages:["php"],description:"assert() with user input can lead to code execution",remediation:"Avoid using assert() with dynamic input. Use proper validation instead.",pattern:/assert\s*\(\s*\$_/},{id:"sast/php-create-function",name:"Dangerous create_function",severity:"high",languages:["php"],description:"create_function() allows arbitrary code execution",remediation:"Use anonymous functions instead of create_function().",pattern:/create_function\s*\(/},{id:"sast/php-preg-replace",name:"preg_replace code execution",severity:"high",languages:["php"],description:"preg_replace with /e modifier allows code execution",remediation:"Use preg_replace_callback instead of preg_replace with /e modifier.",pattern:/preg_replace\s*\(\s*\/[^/]*\/e/},{id:"sast/php-laravel-sql-injection",name:"Laravel raw SQL with string concatenation",severity:"high",languages:["php"],description:"DB::raw(), whereRaw(), selectRaw(), orderByRaw(), or havingRaw() with concatenated user input creates SQL injection risk",remediation:"Use parameterized queries with ? bindings instead of string concatenation.",pattern:/(?:DB::raw|->whereRaw|->selectRaw|->orderByRaw|->havingRaw)\s*\(\s*(?:["'][^"']*["']\s*\.\s*\$|\$)/},{id:"sast/php-laravel-mass-assignment",name:"Laravel mass assignment protection disabled",severity:"medium",languages:["php"],description:"$guarded = [] disables all mass-assignment protection, allowing any attribute to be set",remediation:"Use $fillable to explicitly whitelist allowed attributes, or remove $guarded = [] to keep default protection.",pattern:/(?:protected|public)\s+\$guarded\s*=\s*\[\s*\]/},{id:"sast/php-laravel-destructive-migration",name:"Destructive migration without down() method",severity:"medium",languages:["php"],description:"Destructive migration operations (drop*) without a down() method cannot be rolled back",remediation:"Add a down() method that reverses the migration, or use a safer alternative like soft deletes.",pattern:/(?:Schema::drop(?:IfExists)?\(|->dropColumn\()/,validate:(_match,context)=>{return!/function\s+down\s*\(/.test(context.content)}}];var pythonRules=[{id:"sast/py-pickle",name:"Unsafe pickle deserialization",severity:"high",languages:["python"],description:"pickle.loads() called on potentially untrusted data - can lead to arbitrary code execution",remediation:"Use a safer serialization format like JSON, or validate the data source before deserializing with pickle.",pattern:/pickle\.loads?\s*\(/},{id:"sast/py-shell-injection",name:"Shell injection via subprocess",severity:"critical",languages:["python"],description:"subprocess with shell=True allows shell injection",remediation:"Use subprocess.run() with shell=False and pass arguments as a list. Avoid shell=True.",pattern:/shell\s*=\s*True/},{id:"sast/py-yaml-unsafe",name:"Unsafe YAML loading",severity:"high",languages:["python"],description:"yaml.load() without SafeLoader can execute arbitrary code",remediation:"Use yaml.safe_load() instead of yaml.load() for untrusted input.",pattern:/yaml\.load\s*\(/,validate:(_match,context)=>{let content=context.content;if(content.includes("SafeLoader")||content.includes("safe_load"))return!1;return!0}},{id:"sast/py-eval",name:"Dangerous eval() usage",severity:"high",languages:["python"],description:"eval() allows arbitrary code execution",remediation:"Avoid eval(). Use ast.literal_eval() for safe literal evaluation or a proper parser.",pattern:/\beval\s*\(/},{id:"sast/py-exec",name:"Dangerous exec() usage",severity:"high",languages:["python"],description:"exec() allows arbitrary code execution",remediation:"Avoid exec(). Use a safer alternative for dynamic code execution.",pattern:/\bexec\s*\(/},{id:"sast/py-os-system",name:"os.system() shell injection",severity:"critical",languages:["python"],description:"os.system() passes command to shell - vulnerable to injection",remediation:"Use subprocess module with shell=False instead of os.system().",pattern:/os\.system\s*\(/},{id:"sast/py-assert",name:"Debug assert statements left in code",severity:"low",languages:["python"],description:"assert statements can be disabled with -O flag, potentially hiding security checks",remediation:"Move security-related assertions to proper validation functions that cannot be disabled.",pattern:/^\s*assert\s+/m},{id:"sast/py-sql-injection",name:"Potential SQL injection",severity:"critical",languages:["python"],description:"String concatenation in SQL query can lead to SQL injection",remediation:"Use parameterized queries or an ORM. Never concatenate user input into SQL strings.",pattern:/execute\s*\(\s*f["']/},{id:"sast/py-hardcoded-secret",name:"Hardcoded secret detected",severity:"critical",languages:["python"],description:"Potential hardcoded API key, password, or token detected",remediation:"Move secrets to environment variables or a secure secrets manager.",pattern:/(?:api_key|password|secret|token|auth)[_-]?\w*\s*=\s*['"][a-zA-Z0-9_-]{20,}['"]/i},{id:"sast/py-marshal",name:"Unsafe marshal deserialization",severity:"high",languages:["python"],description:"marshal.loads() can execute arbitrary code",remediation:"Use JSON or other safe serialization formats instead of marshal.",pattern:/marshal\.loads?\s*\(/}];var rustRules=[{id:"sast/rust-hardcoded-secret",name:"Hardcoded secret detected",severity:"critical",languages:["rust"],description:"Potential hardcoded API key, password, or token detected",remediation:"Move secrets to environment variables or a secrets manager; do not commit credentials.",pattern:/(?:api_key|password|secret|token|auth)[_-]?\w*\s*(?::\s*&?str)?\s*(?:=|:)\s*["'][a-zA-Z0-9_-]{10,}["']/i},{id:"sast/rust-command-injection",name:"Shell command injection risk",severity:"critical",languages:["rust"],description:"std::process::Command invokes a shell interpreter, which can enable command injection when user input is passed as arguments.",remediation:"Invoke the target binary directly and pass arguments separately; avoid sh -c, bash -c, cmd /C, and powershell -Command with user input.",pattern:/Command::new\s*\(\s*["'](?:sh|bash|cmd|powershell|pwsh)["']\s*\)/},{id:"sast/rust-unsafe-block",name:"Unsafe Rust block",severity:"medium",languages:["rust"],description:"Unsafe blocks bypass Rust safety checks and require careful manual validation.",remediation:"Minimize unsafe code and document invariants with a SAFETY comment.",pattern:/\bunsafe\s*\{/}];var allRules=[...javascriptRules,...pythonRules,...goRules,...rustRules,...javaRules,...phpRules,...cRules,...csharpRules];function getRulesForLanguage(language){let normalized=language.toLowerCase();return allRules.filter((rule)=>rule.languages.some((lang)=>lang.toLowerCase()===normalized))}function findPatternMatches(content,pattern){let matches=[],lines=content.split(`
|
|
5993
5993
|
`);for(let lineNum=0;lineNum<lines.length;lineNum++){let line=lines[lineNum],workPattern=new RegExp(pattern.source,pattern.flags.includes("g")?pattern.flags:`${pattern.flags}g`),match=workPattern.exec(line);while(match!==null){if(matches.push({text:match[0],line:lineNum+1,column:match.index+1}),match[0].length===0)workPattern.lastIndex++;match=workPattern.exec(line)}}return matches}function executeRulesSync(filePath,content,language){let findings=[],normalizedLang=language.toLowerCase(),rules=getRulesForLanguage(normalizedLang);for(let rule of rules){if(!rule.pattern)continue;let matches=findPatternMatches(content,rule.pattern);for(let match of matches){if(rule.validate){let context={filePath,content,language:normalizedLang};if(!rule.validate(match,context))continue}let excerpt=content.split(`
|
|
5994
|
-
`)[match.line-1]?.trim()||"";findings.push({rule_id:rule.id,severity:rule.severity,message:rule.description,location:{file:filePath,line:match.line,column:match.column},remediation:rule.remediation,excerpt})}}return findings}import*as child_process17 from"node:child_process";import*as fs134 from"node:fs";import*as path212 from"node:path";var semgrepAvailableCache=null,DEFAULT_RULES_DIR=".swarm/semgrep-rules",DEFAULT_TIMEOUT_MS4=30000,MAX_OUTPUT_BYTES8=10485760,KILL_GRACE_MS=2000,_internals135={isSemgrepAvailable,checkSemgrepAvailable,resetSemgrepCache,runSemgrep,getRulesDirectory,hasBundledRules,executeWithTimeout};function isSemgrepAvailable(){if(semgrepAvailableCache!==null)return semgrepAvailableCache;try{return child_process17.execFileSync("semgrep",["--version"],{encoding:"utf-8",stdio:"pipe"}),semgrepAvailableCache=!0,!0}catch{return semgrepAvailableCache=!1,!1}}async function checkSemgrepAvailable(){return _internals135.isSemgrepAvailable()}function resetSemgrepCache(){semgrepAvailableCache=null}function parseSemgrepResults(semgrepOutput){let findings=[];try{let parsed=JSON.parse(semgrepOutput),results=parsed.results||parsed;if(!Array.isArray(results))return[];for(let result of results){if(!result||typeof result!=="object")continue;let severity=mapSemgrepSeverity(result.extra?.severity||result.severity);findings.push({rule_id:result.check_id||result.rule_id||"unknown",severity,message:result.extra?.message||result.message||"Security issue detected",location:{file:result.path||result.start?.filename||result.file||"unknown",line:result.start?.line||result.line||1,column:result.start?.col||result.column},remediation:result.extra?.fix,excerpt:result.extra?.lines||result.lines||""})}}catch{return[]}return findings}function mapSemgrepSeverity(severity){switch((severity||"").toLowerCase()){case"error":case"critical":return"critical";case"warning":case"high":return"high";case"info":case"low":return"low";default:return"medium"}}async function executeWithTimeout(command,args2,options){let maxOutputBytes=options.maxOutputBytes??MAX_OUTPUT_BYTES8;return new Promise((resolve81)=>{let child=child_process17.spawn(command,args2,{shell:!1,cwd:options.cwd,stdio:["ignore","pipe","pipe"]});options.onSpawn?.(child.pid);let stdout="",stderr="",stdoutBytes=0,stderrBytes=0,stdoutTruncated=!1,stderrTruncated=!1,settled=!1,timeout,escalation,settle=(result)=>{if(settled)return;if(settled=!0,timeout)clearTimeout(timeout);if(escalation)clearTimeout(escalation);let truncated=stdoutTruncated||stderrTruncated;if(child.exitCode===null&&child.signalCode===null){try{child.kill("SIGTERM")}catch(e){if(e instanceof Error&&!e.message.includes("ESRCH"))
|
|
5994
|
+
`)[match.line-1]?.trim()||"";findings.push({rule_id:rule.id,severity:rule.severity,message:rule.description,location:{file:filePath,line:match.line,column:match.column},remediation:rule.remediation,excerpt})}}return findings}init_logger();import*as child_process17 from"node:child_process";import*as fs134 from"node:fs";import*as path212 from"node:path";var semgrepAvailableCache=null,DEFAULT_RULES_DIR=".swarm/semgrep-rules",DEFAULT_TIMEOUT_MS4=30000,MAX_OUTPUT_BYTES8=10485760,KILL_GRACE_MS=2000,_internals135={isSemgrepAvailable,checkSemgrepAvailable,resetSemgrepCache,runSemgrep,getRulesDirectory,hasBundledRules,executeWithTimeout};function isSemgrepAvailable(){if(semgrepAvailableCache!==null)return semgrepAvailableCache;try{return child_process17.execFileSync("semgrep",["--version"],{encoding:"utf-8",stdio:"pipe"}),semgrepAvailableCache=!0,!0}catch{return semgrepAvailableCache=!1,!1}}async function checkSemgrepAvailable(){return _internals135.isSemgrepAvailable()}function resetSemgrepCache(){semgrepAvailableCache=null}function parseSemgrepResults(semgrepOutput){let findings=[];try{let parsed=JSON.parse(semgrepOutput),results=parsed.results||parsed;if(!Array.isArray(results))return[];for(let result of results){if(!result||typeof result!=="object")continue;let severity=mapSemgrepSeverity(result.extra?.severity||result.severity);findings.push({rule_id:result.check_id||result.rule_id||"unknown",severity,message:result.extra?.message||result.message||"Security issue detected",location:{file:result.path||result.start?.filename||result.file||"unknown",line:result.start?.line||result.line||1,column:result.start?.col||result.column},remediation:result.extra?.fix,excerpt:result.extra?.lines||result.lines||""})}}catch{return[]}return findings}function mapSemgrepSeverity(severity){switch((severity||"").toLowerCase()){case"error":case"critical":return"critical";case"warning":case"high":return"high";case"info":case"low":return"low";default:return"medium"}}async function executeWithTimeout(command,args2,options){let maxOutputBytes=options.maxOutputBytes??MAX_OUTPUT_BYTES8;return new Promise((resolve81)=>{let child=child_process17.spawn(command,args2,{shell:!1,cwd:options.cwd,stdio:["ignore","pipe","pipe"]});options.onSpawn?.(child.pid);let stdout="",stderr="",stdoutBytes=0,stderrBytes=0,stdoutTruncated=!1,stderrTruncated=!1,settled=!1,timeout,escalation,settle=(result)=>{if(settled)return;if(settled=!0,timeout)clearTimeout(timeout);if(escalation)clearTimeout(escalation);let truncated=stdoutTruncated||stderrTruncated;if(child.exitCode===null&&child.signalCode===null){try{child.kill("SIGTERM")}catch(e){if(e instanceof Error&&!e.message.includes("ESRCH"))log("[semgrep] child.kill failed:",e.message)}if(escalation=setTimeout(()=>{try{child.kill("SIGKILL")}catch(e){if(e instanceof Error&&!e.message.includes("ESRCH"))log("[semgrep] child.kill failed:",e.message)}},KILL_GRACE_MS),typeof escalation.unref==="function")escalation.unref()}resolve81({...result,truncated})};if(timeout=setTimeout(()=>{settle({stdout,stderr:"Process timed out",exitCode:124})},options.timeoutMs),typeof timeout.unref==="function")timeout.unref();child.stdout?.on("data",(data)=>{if(stdoutTruncated)return;let chunk=data.toString(),chunkBytes=Buffer.byteLength(chunk,"utf8");if(stdoutBytes+chunkBytes>maxOutputBytes){let remaining=Math.max(0,maxOutputBytes-stdoutBytes);stdout+=Buffer.from(chunk,"utf8").subarray(0,remaining).toString("utf8"),stdoutBytes=maxOutputBytes,stdoutTruncated=!0,settle({stdout,stderr,exitCode:-1});try{child.kill("SIGTERM")}catch(e){if(e instanceof Error&&!e.message.includes("ESRCH"))log("[semgrep] child.kill failed:",e.message)}}else stdout+=chunk,stdoutBytes+=chunkBytes}),child.stderr?.on("data",(data)=>{if(stderrTruncated)return;let chunk=data.toString(),chunkBytes=Buffer.byteLength(chunk,"utf8");if(stderrBytes+chunkBytes>maxOutputBytes){let remaining=Math.max(0,maxOutputBytes-stderrBytes);stderr+=Buffer.from(chunk,"utf8").subarray(0,remaining).toString("utf8"),stderrBytes=maxOutputBytes,stderrTruncated=!0,settle({stdout,stderr,exitCode:-1});try{child.kill("SIGTERM")}catch(e){if(e instanceof Error&&!e.message.includes("ESRCH"))log("[semgrep] child.kill failed:",e.message)}}else stderr+=chunk,stderrBytes+=chunkBytes}),child.on("close",(code)=>{settle({stdout,stderr,exitCode:code??0})}),child.on("error",(err)=>{settle({stdout,stderr:err.message,exitCode:1})})})}async function runSemgrep(options){let files=options.files||[],rulesDir=options.rulesDir||DEFAULT_RULES_DIR,timeoutMs=options.timeoutMs||DEFAULT_TIMEOUT_MS4;if(files.length===0)return{available:_internals135.isSemgrepAvailable(),findings:[],engine:"tier_a"};if(!_internals135.isSemgrepAvailable())return{available:!1,findings:[],error:"Semgrep is not installed or not available on PATH",engine:"tier_a"};let args2=[options.useAutoConfig?"--config=auto":`--config=./${rulesDir}`,"--json","--quiet"];if(options.lang)args2.push(`--lang=${options.lang}`);args2.push(...files);try{let result=await executeWithTimeout("semgrep",args2,{timeoutMs,cwd:options.cwd});if(result.truncated)return{available:!0,findings:[],error:`Semgrep output exceeded ${MAX_OUTPUT_BYTES8} bytes and was truncated; results incomplete`,engine:"tier_a"};if(result.exitCode!==0){if(result.exitCode===1&&result.stdout)return{available:!0,findings:parseSemgrepResults(result.stdout),engine:"tier_a+tier_b"};return{available:!0,findings:[],error:result.stderr||`Semgrep exited with code ${result.exitCode}`,engine:"tier_a"}}return{available:!0,findings:parseSemgrepResults(result.stdout),engine:"tier_a+tier_b"}}catch(error93){let errorMessage3=error93 instanceof Error?error93.message:"Unknown error running Semgrep";return{available:!0,findings:[],error:errorMessage3,engine:"tier_a"}}}function getRulesDirectory(projectRoot){if(projectRoot)return path212.resolve(projectRoot,DEFAULT_RULES_DIR);return DEFAULT_RULES_DIR}function hasBundledRules(projectRoot){let rulesDir=getRulesDirectory(projectRoot);try{return fs134.existsSync(rulesDir)}catch{return!1}}init_utils();init_create_tool();init_utils2();import*as crypto13 from"node:crypto";import*as fs135 from"node:fs";import*as path213 from"node:path";var BASELINE_SCHEMA_VERSION="1.0.0",MAX_BASELINE_FINDINGS=2000,MAX_BASELINE_BYTES=2097152,LOCK_RETRY_DELAYS_MS=[50,100,200,400,800];function normalizeFindingPath(directory,file3){let resolved=path213.isAbsolute(file3)?file3:path213.resolve(directory,file3);return path213.relative(path213.resolve(directory),resolved).replace(/\\/g,"/")}function baselineRelPath(phase){return path213.join("evidence",String(phase),"sast-baseline.json")}function tempRelPath(phase){return path213.join("evidence",String(phase),`sast-baseline.json.tmp.${Date.now()}.${process.pid}`)}function lockRelPath(phase){return path213.join("evidence",String(phase),"sast-baseline.json.lock")}function getLine(lines,idx){if(idx<0||idx>=lines.length)return"";return(lines[idx]??"").trim()}function fingerprintFinding(finding,directory,occurrenceIndex){let relFile=normalizeFindingPath(directory,finding.location.file);if(relFile.startsWith(".."))return{fingerprint:`${relFile}|${finding.rule_id}|L${finding.location.line}|UNSTABLE|#${occurrenceIndex}`,stable:!1};let lineNum=finding.location.line;try{let lines=fs135.readFileSync(finding.location.file,"utf-8").split(`
|
|
5995
5995
|
`),idx=lineNum-1,window2=[getLine(lines,idx-1),getLine(lines,idx),getLine(lines,idx+1)].join(`
|
|
5996
5996
|
`),hash4=crypto13.createHash("sha256").update(window2).digest("hex").slice(0,16);return{fingerprint:`${relFile}|${finding.rule_id}|${hash4}|#${occurrenceIndex}`,stable:!0}}catch{return{fingerprint:`${relFile}|${finding.rule_id}|L${lineNum}|UNSTABLE|#${occurrenceIndex}`,stable:!1}}}function assignOccurrenceIndices(findings,directory){let countMap=new Map;return findings.map((finding)=>{let relFile=normalizeFindingPath(directory,finding.location.file),lineNum=finding.location.line,baseKey;try{if(relFile.startsWith(".."))throw Error("escapes workspace");let lines=fs135.readFileSync(finding.location.file,"utf-8").split(`
|
|
5997
5997
|
`),idx=lineNum-1,window2=[getLine(lines,idx-1),getLine(lines,idx),getLine(lines,idx+1)].join(`
|
|
5998
5998
|
`),hash4=crypto13.createHash("sha256").update(window2).digest("hex").slice(0,16);baseKey=`${relFile}|${finding.rule_id}|${hash4}`}catch{baseKey=`${relFile}|${finding.rule_id}|L${lineNum}|UNSTABLE`}let occIdx=countMap.get(baseKey)??0;countMap.set(baseKey,occIdx+1);let fp=_internals136.fingerprintFinding(finding,directory,occIdx);return{finding,index:occIdx,stable:fp.stable,fingerprint:fp.fingerprint}})}async function acquireLock2(lockPath){for(let attempt=0;attempt<=LOCK_RETRY_DELAYS_MS.length;attempt++)try{let fd=fs135.openSync(lockPath,"wx");return fs135.closeSync(fd),()=>{try{fs135.unlinkSync(lockPath)}catch{}}}catch{if(attempt<LOCK_RETRY_DELAYS_MS.length)await new Promise((resolve82)=>setTimeout(resolve82,LOCK_RETRY_DELAYS_MS[attempt]))}return()=>{}}function validatePhase(phase){if(!Number.isInteger(phase)||phase<1)return"Invalid phase: must be a positive integer";return null}async function captureOrMergeBaseline(directory,phase,findings,engine,scannedFiles,opts){let phaseError=validatePhase(phase);if(phaseError)return{status:"error",message:phaseError};if(!scannedFiles||scannedFiles.length===0)return{status:"error",message:"capture_baseline requires non-empty changed_files"};let baselinePath,tempPath,lockPath;try{baselinePath=validateSwarmPath(directory,baselineRelPath(phase)),tempPath=validateSwarmPath(directory,tempRelPath(phase)),lockPath=validateSwarmPath(directory,lockRelPath(phase))}catch(e){return{status:"error",message:e instanceof Error?e.message:"Path validation failed"}}fs135.mkdirSync(path213.dirname(baselinePath),{recursive:!0}),fs135.mkdirSync(path213.dirname(tempPath),{recursive:!0});let releaseLock=await acquireLock2(lockPath);try{let existing=null;try{let raw=fs135.readFileSync(baselinePath,"utf-8"),parsed=JSON.parse(raw);if(parsed.schema_version===BASELINE_SCHEMA_VERSION)existing=parsed}catch{}let scannedRelFiles=new Set(scannedFiles.map((f)=>normalizeFindingPath(directory,f))),indexed=_internals136.assignOccurrenceIndices(findings,directory);if(existing&&!opts?.force){let prunedFingerprints=existing.fingerprints.filter((fp)=>{let relFile=fp.slice(0,fp.indexOf("|"));return!scannedRelFiles.has(relFile)}),prunedSnapshot=existing.findings_snapshot.filter((f)=>{return!scannedRelFiles.has(normalizeFindingPath(directory,f.location.file))}),prunedFilesIndexed=existing.files_indexed.filter((f)=>!scannedRelFiles.has(f)),mergedFingerprints=[...prunedFingerprints,...indexed.map((i)=>i.fingerprint)],mergedSnapshot=[...prunedSnapshot,...indexed.map((i)=>i.finding)],mergedFilesIndexed=[...prunedFilesIndexed,...Array.from(scannedRelFiles)],truncated2=mergedSnapshot.length>MAX_BASELINE_FINDINGS,cappedSnapshot2=truncated2?mergedSnapshot.slice(-MAX_BASELINE_FINDINGS):mergedSnapshot,cappedFingerprints2=truncated2?mergedFingerprints.slice(-MAX_BASELINE_FINDINGS):mergedFingerprints,cappedFilesIndexed=mergedFilesIndexed;if(truncated2){let survivingFiles=new Set;for(let finding of cappedSnapshot2){let relFile=normalizeFindingPath(directory,finding.location.file);survivingFiles.add(relFile)}cappedFilesIndexed=Array.from(survivingFiles)}let now2=new Date().toISOString(),bundle2={schema_version:BASELINE_SCHEMA_VERSION,phase,created_at:existing.created_at,updated_at:now2,engine,files_indexed:cappedFilesIndexed,fingerprints:cappedFingerprints2,findings_snapshot:cappedSnapshot2,truncated:truncated2},json4=JSON.stringify(bundle2,null,2);if(json4.length>MAX_BASELINE_BYTES)return{status:"error",message:`Baseline would exceed size cap (${json4.length} bytes > ${MAX_BASELINE_BYTES})`};return fs135.writeFileSync(tempPath,json4,"utf-8"),fs135.renameSync(tempPath,baselinePath),{status:"merged",path:baselinePath,fingerprint_count:cappedFingerprints2.length}}let newFingerprints=indexed.map((i)=>i.fingerprint),newSnapshot=indexed.map((i)=>i.finding),truncated=newSnapshot.length>MAX_BASELINE_FINDINGS,cappedSnapshot=truncated?newSnapshot.slice(0,MAX_BASELINE_FINDINGS):newSnapshot,cappedFingerprints=truncated?newFingerprints.slice(0,MAX_BASELINE_FINDINGS):newFingerprints,now=new Date().toISOString(),bundle={schema_version:BASELINE_SCHEMA_VERSION,phase,created_at:now,updated_at:now,engine,files_indexed:Array.from(scannedRelFiles),fingerprints:cappedFingerprints,findings_snapshot:cappedSnapshot,truncated},json3=JSON.stringify(bundle,null,2);if(json3.length>MAX_BASELINE_BYTES)return{status:"error",message:`Baseline would exceed size cap (${json3.length} bytes > ${MAX_BASELINE_BYTES})`};return fs135.writeFileSync(tempPath,json3,"utf-8"),fs135.renameSync(tempPath,baselinePath),{status:"written",path:baselinePath,fingerprint_count:cappedFingerprints.length}}finally{releaseLock()}}function loadBaseline(directory,phase){let phaseError=validatePhase(phase);if(phaseError)return{status:"invalid_schema",errors:[phaseError]};let baselinePath;try{baselinePath=validateSwarmPath(directory,baselineRelPath(phase))}catch(e){return{status:"invalid_schema",errors:[e instanceof Error?e.message:"Path validation failed"]}}try{let raw=fs135.readFileSync(baselinePath,"utf-8"),parsed=JSON.parse(raw);if(parsed.schema_version!==BASELINE_SCHEMA_VERSION)return{status:"invalid_schema",errors:[`Unknown schema version: ${String(parsed.schema_version)}`]};if(!Array.isArray(parsed.fingerprints))return{status:"invalid_schema",errors:["Missing or invalid fingerprints array"]};return{status:"found",fingerprints:new Set(parsed.fingerprints),bundle:parsed}}catch(e){if(e.code==="ENOENT")return{status:"not_found"};return{status:"invalid_schema",errors:[e instanceof Error?e.message:"Failed to read baseline"]}}}var _internals136={fingerprintFinding,assignOccurrenceIndices,captureOrMergeBaseline,loadBaseline};var MAX_FILE_SIZE_BYTES7=524288,MAX_FILES_SCANNED2=1000,MAX_FINDINGS2=100,SEVERITY_ORDER={low:0,medium:1,high:2,critical:3};function shouldSkipFile(filePath){try{let stats2=fs136.statSync(filePath);if(stats2.size>MAX_FILE_SIZE_BYTES7)return{skip:!0,reason:"file too large"};if(stats2.size===0)return{skip:!0,reason:"empty file"};let fd=fs136.openSync(filePath,"r"),buffer=Buffer.alloc(8192),bytesRead=fs136.readSync(fd,buffer,0,8192,0);if(fs136.closeSync(fd),bytesRead>0){let nullCount=0;for(let i=0;i<bytesRead;i++)if(buffer[i]===0)nullCount++;if(nullCount/bytesRead>0.1)return{skip:!0,reason:"binary file"}}return{skip:!1}}catch{return{skip:!0,reason:"cannot read file"}}}function meetsThreshold(severity,threshold){let severityLevel=SEVERITY_ORDER[severity]??0,thresholdLevel=SEVERITY_ORDER[threshold]??1;return severityLevel>=thresholdLevel}function countBySeverity(findings){let counts={critical:0,high:0,medium:0,low:0};for(let finding of findings){let severity=finding.severity.toLowerCase();if(severity in counts)counts[severity]++}return counts}function scanFileWithTierA(filePath,language){try{let content=fs136.readFileSync(filePath,"utf-8");return executeRulesSync(filePath,content,language).map((f)=>({rule_id:f.rule_id,severity:f.severity,message:f.message,location:{file:f.location.file,line:f.location.line,column:f.location.column},remediation:f.remediation}))}catch{return[]}}async function sastScan(input,directory,config3){let{changed_files,severity_threshold="medium",capture_baseline=!1,phase}=input;if(config3?.gates?.sast_scan?.enabled===!1)return{verdict:"pass",findings:[],summary:{engine:"tier_a",files_scanned:0,findings_count:0,findings_by_severity:{critical:0,high:0,medium:0,low:0}}};let allFindings=[],filesScanned=0,_filesSkipped=0,scannedFilePaths=[],semgrepAvailable=isSemgrepAvailable(),engine=semgrepAvailable?"tier_a+tier_b":"tier_a",filesByLanguage=new Map;for(let filePath of changed_files){if(typeof filePath!=="string"||!filePath){_filesSkipped++;continue}let resolvedPath=path214.isAbsolute(filePath)?filePath:path214.resolve(directory,filePath),resolvedDirectory=path214.resolve(directory);if(!resolvedPath.startsWith(resolvedDirectory+path214.sep)&&resolvedPath!==resolvedDirectory){_filesSkipped++;continue}if(!fs136.existsSync(resolvedPath)){_filesSkipped++;continue}if(shouldSkipFile(resolvedPath).skip){_filesSkipped++;continue}let ext=extname20(resolvedPath).toLowerCase(),profile=getProfileForFile(resolvedPath),langDef=getLanguageForExtension(ext);if(!profile&&!langDef){_filesSkipped++;continue}let language=profile?.id??langDef.id;if(profile?profile.sast.nativeRuleSet!==null:!!langDef){let tierAFindings=scanFileWithTierA(resolvedPath,language);allFindings.push(...tierAFindings)}if(semgrepAvailable){if(profile&&profile.sast.nativeRuleSet===null&&profile.sast.semgrepSupport!=="none"){let bucketKey=`auto:${profile.id}`,existing=filesByLanguage.get(bucketKey)||[];existing.push(resolvedPath),filesByLanguage.set(bucketKey,existing)}else if(!(profile&&profile.sast.nativeRuleSet===null&&profile.sast.semgrepSupport==="none")){let existing=filesByLanguage.get(language)||[];existing.push(resolvedPath),filesByLanguage.set(language,existing)}}if(filesScanned++,scannedFilePaths.push(resolvedPath),filesScanned>=MAX_FILES_SCANNED2){warn(`SAST Scan: Reached maximum files limit (${MAX_FILES_SCANNED2}), stopping`);break}}if(semgrepAvailable&&filesByLanguage.size>0)try{for(let[bucketKey,bucketFiles]of filesByLanguage.entries()){if(bucketFiles.length===0)continue;let semgrepResult;if(bucketKey.startsWith("auto:")){let lang=bucketKey.slice(5);semgrepResult=await runSemgrep({files:bucketFiles,lang,useAutoConfig:!0})}else semgrepResult=await runSemgrep({files:bucketFiles});if(semgrepResult.findings.length>0){let semgrepFindings=semgrepResult.findings.map((f)=>({rule_id:f.rule_id,severity:f.severity,message:f.message,location:{file:f.location.file,line:f.location.line,column:f.location.column},remediation:f.remediation})),existingKeys=new Set(allFindings.map((f)=>`${f.rule_id}:${f.location.file}:${f.location.line}`));for(let finding of semgrepFindings){let key=`${finding.rule_id}:${finding.location.file}:${finding.location.line}`;if(!existingKeys.has(key))allFindings.push(finding),existingKeys.add(key)}}}}catch(error93){warn(`SAST Scan: Semgrep failed, falling back to Tier A: ${error93}`)}if(capture_baseline){if(phase===void 0||!Number.isInteger(phase)||phase<1)return{verdict:"fail",findings:allFindings.slice(0,MAX_FINDINGS2),summary:{engine,files_scanned:filesScanned,findings_count:Math.min(allFindings.length,MAX_FINDINGS2),findings_by_severity:countBySeverity(allFindings.slice(0,MAX_FINDINGS2))}};if(scannedFilePaths.length===0){let finalFindings3=allFindings.slice(0,MAX_FINDINGS2);return{verdict:"fail",error:"capture_baseline requires changed_files to produce a non-empty baseline",findings:finalFindings3,summary:{engine,files_scanned:filesScanned,findings_count:finalFindings3.length,findings_by_severity:countBySeverity(finalFindings3)}}}let captureFindings=allFindings.slice(0,MAX_BASELINE_FINDINGS),captureResult=await captureOrMergeBaseline(directory,phase,captureFindings,engine,scannedFilePaths),captureStatus=captureResult.status==="written"?"baseline_captured":captureResult.status==="merged"?"baseline_merged":void 0;if(captureResult.status==="error")warn(`SAST Baseline: capture failed — ${captureResult.message}`);let finalFindings2=allFindings.slice(0,MAX_FINDINGS2),summary2={engine,files_scanned:filesScanned,findings_count:finalFindings2.length,findings_by_severity:countBySeverity(finalFindings2)};return await saveEvidence(directory,"sast_scan",{task_id:"sast_scan",type:"sast",timestamp:new Date().toISOString(),agent:"sast_scan",verdict:"pass",summary:`Baseline capture: scanned ${filesScanned} files, recorded ${captureFindings.length} finding(s)`,...summary2,findings:finalFindings2,baseline_used:!1}),{verdict:"pass",findings:finalFindings2,summary:summary2,status:captureStatus,finding_count:captureResult.status!=="error"?captureResult.fingerprint_count:void 0,baseline_used:!1}}let newFindings,preExistingFindings,baselineUsed=!1,truncatedPreExisting=!1;if(phase!==void 0&&Number.isInteger(phase)&&phase>=1){let baselineResult=loadBaseline(directory,phase);if(baselineResult.status==="found"){baselineUsed=!0;let baselineSet=baselineResult.fingerprints,indexed=assignOccurrenceIndices(allFindings,directory),rawNew=[],rawPreExisting=[];for(let{finding,stable,fingerprint}of indexed)if(!stable||!baselineSet.has(fingerprint))rawNew.push(finding);else rawPreExisting.push(finding);newFindings=rawNew.slice(0,MAX_FINDINGS2);let preExistingBudget=Math.max(0,MAX_FINDINGS2-newFindings.length);preExistingFindings=rawPreExisting.slice(0,preExistingBudget),truncatedPreExisting=rawPreExisting.length>preExistingBudget}else if(baselineResult.status==="invalid_schema")warn(`SAST Baseline: could not load baseline for phase ${phase} — ${baselineResult.errors.join(", ")}. Falling back to legacy behavior.`)}let finalFindings;if(!baselineUsed){if(finalFindings=allFindings,allFindings.length>MAX_FINDINGS2)finalFindings=allFindings.slice(0,MAX_FINDINGS2),warn(`SAST Scan: Found ${allFindings.length} findings, limiting to ${MAX_FINDINGS2}`)}else finalFindings=[...newFindings??[],...preExistingFindings??[]].slice(0,MAX_FINDINGS2);let findingsBySeverity=countBySeverity(finalFindings),verdictSource=baselineUsed?newFindings??[]:finalFindings,verdict="pass";for(let finding of verdictSource)if(meetsThreshold(finding.severity,severity_threshold)){verdict="fail";break}if(filesScanned===0)verdict="fail";let summary={engine,files_scanned:filesScanned,findings_count:finalFindings.length,findings_by_severity:findingsBySeverity};await saveEvidence(directory,"sast_scan",{task_id:"sast_scan",type:"sast",timestamp:new Date().toISOString(),agent:"sast_scan",verdict,summary:`Scanned ${filesScanned} files, found ${finalFindings.length} finding(s) using ${engine}`,...summary,findings:finalFindings,...baselineUsed&&{new_findings:newFindings,pre_existing_findings:preExistingFindings,baseline_used:!0}});let result={verdict,findings:finalFindings,summary};if(baselineUsed){if(result.new_findings=newFindings,result.pre_existing_findings=preExistingFindings,result.baseline_used=!0,truncatedPreExisting)result.truncated_pre_existing=!0}return result}var sast_scan=createSwarmTool({description:"Static Application Security Testing (SAST) scan. Scans files for security vulnerabilities using built-in rules (Tier A) and optional Semgrep (Tier B). Supports phase-scoped baseline diffing: set capture_baseline:true before first coder delegation to snapshot pre-existing findings; subsequent scans with the same phase only fail on NEW findings.",args:{directory:exports_external.string().describe("Directory to scan for security vulnerabilities"),changed_files:exports_external.array(exports_external.string()).optional().describe("List of files to scan (leave empty to scan none)"),severity_threshold:exports_external.enum(["low","medium","high","critical"]).optional().default("medium").describe("Minimum severity that causes failure"),capture_baseline:exports_external.boolean().optional().describe("When true, capture/merge a phase-scoped baseline of pre-existing findings. Requires phase. Subsequent scans with phase only fail on NEW findings."),phase:exports_external.number().int().min(1).optional().describe("Current phase number (positive integer >= 1). Required with capture_baseline. Enables baseline diff when provided on non-capture scans.")},execute:async(args2,directory)=>{let safeArgs;try{if(args2&&typeof args2==="object"){let{phase:rawPhase,capture_baseline:rawCapture}=args2;safeArgs={directory:args2.directory,changed_files:args2.changed_files,severity_threshold:args2.severity_threshold,phase:typeof rawPhase==="number"&&Number.isInteger(rawPhase)&&rawPhase>=1?rawPhase:void 0,capture_baseline:typeof rawCapture==="boolean"?rawCapture:void 0}}else safeArgs={directory:void 0,changed_files:void 0,severity_threshold:void 0,capture_baseline:void 0,phase:void 0}}catch{safeArgs={directory:void 0,changed_files:void 0,severity_threshold:void 0,capture_baseline:void 0,phase:void 0}}if(safeArgs.directory===void 0)return JSON.stringify({verdict:"fail",findings:[],summary:{engine:"tier_a",files_scanned:0,findings_count:0,findings_by_severity:{critical:0,high:0,medium:0,low:0}}},null,2);let input={changed_files:safeArgs.changed_files??[],severity_threshold:safeArgs.severity_threshold??"medium",capture_baseline:safeArgs.capture_baseline,phase:safeArgs.phase},result=await _internals137.sastScan(input,directory);return JSON.stringify(result,null,2)}}),_internals137={sastScan,sast_scan};init_secretscan();var TOOL_TIMEOUT_MS=60000,MAX_COMBINED_BYTES=500000,MAX_CONCURRENT=4,MAX_FILES=100,_internals138={qualityBudget};function isWindowsAbsolutePath(inputPath){return/^[A-Za-z]:[/\\]/.test(inputPath)}function validatePath(inputPath,baseDir,workspaceDir){if(typeof inputPath!=="string")return"path must be a string";if(!inputPath||inputPath.trim().length===0)return"path is required";let resolved,isWinAbs=isWindowsAbsolutePath(inputPath);if(isWinAbs)resolved=path215.win32.resolve(inputPath);else if(path215.isAbsolute(inputPath))resolved=path215.resolve(inputPath);else resolved=path215.resolve(baseDir,inputPath);let workspaceResolved=path215.resolve(workspaceDir),relative46;if(isWinAbs)relative46=path215.win32.relative(workspaceResolved,resolved);else relative46=path215.relative(workspaceResolved,resolved);if(relative46.startsWith(".."))return"path traversal detected";return null}function validateDirectory2(dir,workspaceDir){if(!dir||dir.length===0)return"directory is required";if(dir.length>500)return"directory path too long";let traversalCheck=validatePath(dir,workspaceDir,workspaceDir);if(traversalCheck)return traversalCheck;return null}async function runWithTimeout2(promise3,timeoutMs){let timeoutPromise=new Promise((_,reject)=>{setTimeout(()=>reject(Error(`Timeout after ${timeoutMs}ms`)),timeoutMs)});return Promise.race([promise3,timeoutPromise])}async function runLintWrapped(files,directory,_config){let start=process.hrtime.bigint();try{let linter=await detectAvailableLinter(directory);if(!linter)return{ran:!1,error:"No linter found (biome or eslint)",duration_ms:Number(process.hrtime.bigint()-start)/1e6};if(files&&files.length>0)return{ran:!0,result:await runLintOnFiles(linter,files,directory),duration_ms:Number(process.hrtime.bigint()-start)/1e6};return{ran:!0,result:await runWithTimeout2(runLint(linter,"check",directory),TOOL_TIMEOUT_MS),duration_ms:Number(process.hrtime.bigint()-start)/1e6}}catch(error93){return{ran:!0,error:error93 instanceof Error?error93.message:"Unknown error",duration_ms:Number(process.hrtime.bigint()-start)/1e6}}}async function runLintOnFiles(linter,files,workspaceDir){let validatedFiles=[];for(let file3 of files){if(typeof file3!=="string")continue;let resolvedPath=path215.resolve(file3);if(validatePath(resolvedPath,workspaceDir,workspaceDir))continue;validatedFiles.push(resolvedPath)}if(validatedFiles.length===0)return{success:!1,mode:"check",linter,command:[],error:"No valid files after security validation"};let resolvedBin=resolveLinterBinPath(linter,workspaceDir),command;if(linter==="biome")command=[resolvedBin,"check",...validatedFiles];else command=[resolvedBin,...validatedFiles];try{let proc=bunSpawn(command,{stdout:"pipe",stderr:"pipe",cwd:workspaceDir}),[stdout,stderr]=await Promise.all([proc.stdout.text(),proc.stderr.text()]),exitCode=await proc.exited,output=stdout;if(stderr)output+=(output?`
|
|
5999
5999
|
`:"")+stderr;if(output.length>512000)output=`${output.slice(0,512000)}
|
|
6000
6000
|
... (output truncated)`;let result={success:!0,mode:"check",linter,command,exitCode,output};if(exitCode===0)result.message=`${linter} check completed successfully with no issues`;else result.message=`${linter} check found issues (exit code ${exitCode}).`;return result}catch(error93){return{success:!1,mode:"check",linter,command,error:error93 instanceof Error?`Execution failed: ${error93.message}`:"Execution failed: unknown error"}}}async function runSecretscanWrapped(files,directory,_config){let start=process.hrtime.bigint();try{if(files&&files.length>0)return{ran:!0,result:await runWithTimeout2(runSecretscanOnFiles(files,directory),TOOL_TIMEOUT_MS),duration_ms:Number(process.hrtime.bigint()-start)/1e6};return{ran:!0,result:await runWithTimeout2(runSecretscan(directory),TOOL_TIMEOUT_MS),duration_ms:Number(process.hrtime.bigint()-start)/1e6}}catch(error93){return{ran:!0,error:error93 instanceof Error?error93.message:"Unknown error",duration_ms:Number(process.hrtime.bigint()-start)/1e6}}}async function runSastScanWrapped(changedFiles,directory,severityThreshold,config3,phase){let start=process.hrtime.bigint();try{return{ran:!0,result:await runWithTimeout2(sastScan({changed_files:changedFiles,severity_threshold:severityThreshold,phase},directory,config3),TOOL_TIMEOUT_MS),duration_ms:Number(process.hrtime.bigint()-start)/1e6}}catch(error93){return{ran:!0,error:error93 instanceof Error?error93.message:"Unknown error",duration_ms:Number(process.hrtime.bigint()-start)/1e6}}}async function runQualityBudgetWrapped(changedFiles,directory,config3){let start=process.hrtime.bigint();try{return{ran:!0,result:await runWithTimeout2(_internals138.qualityBudget({changed_files:changedFiles,config:config3?.gates?.quality_budget},directory),TOOL_TIMEOUT_MS),duration_ms:Number(process.hrtime.bigint()-start)/1e6}}catch(error93){return{ran:!0,error:error93 instanceof Error?error93.message:"Unknown error",duration_ms:Number(process.hrtime.bigint()-start)/1e6}}}var GATE_SEVERITIES=new Set(["high","critical"]),SEVERITY_ORDER_PCB={low:0,medium:1,high:2,critical:3};function meetsThresholdForTriage(severity,threshold){return(SEVERITY_ORDER_PCB[severity]??0)>=(SEVERITY_ORDER_PCB[threshold]??1)}async function runGitDiff(args2,directory){try{let proc=bunSpawn(["git","diff",...args2],{cwd:directory,stdout:"pipe",stderr:"pipe"}),[exitCode,stdout]=await Promise.all([proc.exited,proc.stdout.text()]);if(exitCode!==0)return null;let trimmed=stdout.trim();return trimmed.length>0?trimmed:null}catch{return null}}function parseDiffLineRanges(diffOutput){let result=new Map,currentFile=null;for(let line of diffOutput.split(`
|
|
6001
|
-
`)){if(line.startsWith("+++ b/")){if(currentFile=line.slice(6).trim(),!result.has(currentFile))result.set(currentFile,new Set);continue}if(line.startsWith("@@")&¤tFile){let match=line.match(/^@@ [^+]*\+(\d+)(?:,(\d+))? @@/);if(match){let start=parseInt(match[1],10),count=match[2]!==void 0?parseInt(match[2],10):1,lines=result.get(currentFile);for(let i=start;i<start+count;i++)lines.add(i)}}}return result}async function getChangedLineRanges(directory){try{for(let baseBranch of["origin/main","origin/master","main","master"]){let mergeBaseProc=bunSpawn(["git","merge-base",baseBranch,"HEAD"],{cwd:directory,stdout:"pipe",stderr:"pipe"}),[mbExit,mbOut]=await Promise.all([mergeBaseProc.exited,mergeBaseProc.stdout.text()]);if(mbExit===0&&mbOut.trim()){let mergeBase=mbOut.trim(),diffOut=await runGitDiff(["-U0",`${mergeBase}..HEAD`],directory);if(diffOut)return parseDiffLineRanges(diffOut)}}let diffHead1=await runGitDiff(["-U0","HEAD~1"],directory);if(diffHead1)return parseDiffLineRanges(diffHead1);let diffHead=await runGitDiff(["-U0","HEAD"],directory);if(diffHead)return parseDiffLineRanges(diffHead);return null}catch{return null}}function classifySastFindings(findings,changedLineRanges,directory){if(!changedLineRanges||changedLineRanges.size===0)return{newFindings:findings,preexistingFindings:[]};let newFindings=[],preexistingFindings=[];for(let finding of findings){let filePath=finding.location.file,normalised=path215.relative(directory,filePath).replace(/\\/g,"/");if(changedLineRanges.get(normalised)?.has(finding.location.line))newFindings.push(finding);else preexistingFindings.push(finding)}return{newFindings,preexistingFindings}}async function runPreCheckBatch(input,workspaceDir,contextDir){let effectiveWorkspaceDir=workspaceDir||input.directory||contextDir,{files,directory,sast_threshold="medium",config:config3,phase}=input,dirError=validateDirectory2(directory,effectiveWorkspaceDir);if(dirError)return warn(`pre_check_batch: Invalid directory: ${dirError}`),{gates_passed:!1,lint:{ran:!1,error:dirError,duration_ms:0},secretscan:{ran:!1,error:dirError,duration_ms:0},sast_scan:{ran:!1,error:dirError,duration_ms:0},quality_budget:{ran:!1,error:dirError,duration_ms:0},total_duration_ms:0};if(!files||files.length===0)return warn("pre_check_batch: No files provided, skipping all tools (fail-closed)"),{gates_passed:!1,lint:{ran:!1,error:"No files provided",duration_ms:0},secretscan:{ran:!1,error:"No files provided",duration_ms:0},sast_scan:{ran:!1,error:"No files provided",duration_ms:0},quality_budget:{ran:!1,error:"No files provided",duration_ms:0},total_duration_ms:0};let changedFiles=[];for(let file3 of files){if(typeof file3!=="string"){warn(`pre_check_batch: Non-string file entry rejected: ${String(file3)}`);continue}if(validatePath(file3,directory,effectiveWorkspaceDir)){warn(`pre_check_batch: Invalid file path: ${file3}`);continue}changedFiles.push(path215.resolve(directory,file3))}if(changedFiles.length===0)return warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)"),{gates_passed:!1,lint:{ran:!1,error:"No files provided",duration_ms:0},secretscan:{ran:!1,error:"No files provided",duration_ms:0},sast_scan:{ran:!1,error:"No files provided",duration_ms:0},quality_budget:{ran:!1,error:"No files provided",duration_ms:0},total_duration_ms:0};if(changedFiles.length>MAX_FILES)throw Error(`Input exceeds maximum file count: ${changedFiles.length} > ${MAX_FILES}`);let limit=pLimit(MAX_CONCURRENT),[lintResult,secretscanResult,sastScanResult,qualityBudgetResult]=await Promise.all([limit(()=>runLintWrapped(changedFiles,directory,config3)),limit(()=>runSecretscanWrapped(changedFiles,directory,config3)),limit(()=>runSastScanWrapped(changedFiles,directory,sast_threshold,config3,phase)),limit(()=>runQualityBudgetWrapped(changedFiles,directory,config3))]),totalDuration=lintResult.duration_ms+secretscanResult.duration_ms+sastScanResult.duration_ms+qualityBudgetResult.duration_ms,gatesPassed=!0;if(lintResult.ran&&lintResult.result){let lintRes=lintResult.result;if("success"in lintRes&&lintRes.success===!1)warn("pre_check_batch: Lint found issues (informational only)")}else if(lintResult.error)warn(`pre_check_batch: Lint error (informational only): ${lintResult.error}`);if(secretscanResult.ran&&secretscanResult.result){let scanResult=secretscanResult.result;if("error"in scanResult&&scanResult.error)gatesPassed=!1,warn(`pre_check_batch: Secretscan error - GATE FAILED: ${scanResult.error}`);else if("findings"in scanResult&&scanResult.findings.length>0)gatesPassed=!1,warn("pre_check_batch: Secretscan found secrets - GATE FAILED");else if(files&&files.length>0&&(scanResult.files_scanned??0)===0)gatesPassed=!1,warn("pre_check_batch: Secretscan scanned 0 files despite requested file scope - GATE FAILED (possible vacuous pass)")}else if(secretscanResult.error)gatesPassed=!1,warn(`pre_check_batch: Secretscan error - GATE FAILED: ${secretscanResult.error}`);if(secretscanResult.ran&&secretscanResult.result)try{let scanResult=secretscanResult.result,secretscanEvidence={task_id:"secretscan",type:"secretscan",timestamp:new Date().toISOString(),agent:"pre_check_batch",verdict:scanResult.count>0?"fail":"pass",summary:`Secretscan: ${scanResult.count} finding(s), ${scanResult.files_scanned??0} files scanned, ${scanResult.skipped_files??0} skipped`,findings_count:scanResult.count,scan_directory:scanResult.scan_dir,files_scanned:scanResult.files_scanned,skipped_files:scanResult.skipped_files};await saveEvidence(directory,"secretscan",secretscanEvidence)}catch(e){warn(`Failed to persist secretscan evidence: ${e instanceof Error?e.message:String(e)}`)}let sastPreexistingFindings;if(sastScanResult.ran&&sastScanResult.result){let sastResult=sastScanResult.result;if(sastResult.baseline_used){if(sastResult.pre_existing_findings&&sastResult.pre_existing_findings.length>0){if(sastPreexistingFindings=sastResult.pre_existing_findings.filter((f)=>meetsThresholdForTriage(f.severity,sast_threshold)),sastPreexistingFindings.length>0)warn(`pre_check_batch: SAST baseline diff found ${sastPreexistingFindings.length} pre-existing finding(s) - passing to reviewer for triage`)}if(sastResult.verdict==="fail")gatesPassed=!1,warn("pre_check_batch: SAST scan found new findings above threshold - GATE FAILED")}else if(sastResult.verdict==="fail"){let gateFindings=sastResult.findings.filter((f)=>GATE_SEVERITIES.has(f.severity));if(gateFindings.length>0){let changedLineRanges=await getChangedLineRanges(directory),{newFindings,preexistingFindings}=classifySastFindings(gateFindings,changedLineRanges,directory);if(newFindings.length>0)gatesPassed=!1,warn(`pre_check_batch: SAST scan found ${newFindings.length} new HIGH/CRITICAL finding(s) on changed lines - GATE FAILED`);else if(preexistingFindings.length>0)sastPreexistingFindings=preexistingFindings,warn(`pre_check_batch: SAST scan found ${preexistingFindings.length} pre-existing HIGH/CRITICAL finding(s) on unchanged lines - passing to reviewer for triage`)}else gatesPassed=!1,warn("pre_check_batch: SAST scan found vulnerabilities - GATE FAILED")}}else if(sastScanResult.error)gatesPassed=!1,warn(`pre_check_batch: SAST scan error - GATE FAILED: ${sastScanResult.error}`);if(qualityBudgetResult.ran&&qualityBudgetResult.result){if(qualityBudgetResult.result.verdict==="fail")warn("pre_check_batch: Quality budget exceeded (informational only)")}else if(qualityBudgetResult.error)warn(`pre_check_batch: Quality budget error (informational only): ${qualityBudgetResult.error}`);let result={gates_passed:gatesPassed,lint:lintResult,secretscan:secretscanResult,sast_scan:sastScanResult,quality_budget:qualityBudgetResult,total_duration_ms:Math.round(totalDuration),...sastPreexistingFindings&&sastPreexistingFindings.length>0&&{sast_preexisting_findings:sastPreexistingFindings}},outputSize=JSON.stringify(result).length;if(outputSize>MAX_COMBINED_BYTES)warn(`pre_check_batch: Large output (${outputSize} bytes)`);return result}var pre_check_batch=createSwarmTool({description:"Run multiple verification tools in parallel: lint, secretscan, SAST scan, and quality budget. Returns unified result with gates_passed status. Security tools (secretscan, sast_scan) are HARD GATES - failures block merging.",args:{files:exports_external.array(exports_external.string()).optional().describe("Specific files to check (optional, scans directory if not provided)"),directory:exports_external.string().describe("Project root directory — must be the workspace root, subdirectories are rejected"),sast_threshold:exports_external.enum(["low","medium","high","critical"]).optional().describe("Minimum severity for SAST findings to cause failure (default: medium)"),phase:exports_external.number().int().min(1).optional().describe("Current phase number (positive integer >= 1). When provided, enables SAST baseline diffing: only findings absent from the phase-scoped baseline fail the gate.")},async execute(args2,directory){if(!args2||typeof args2!=="object")return JSON.stringify({gates_passed:!1,lint:{ran:!1,error:"Invalid arguments",duration_ms:0},secretscan:{ran:!1,error:"Invalid arguments",duration_ms:0},sast_scan:{ran:!1,error:"Invalid arguments",duration_ms:0},quality_budget:{ran:!1,error:"Invalid arguments",duration_ms:0},total_duration_ms:0},null,2);if(!directory||typeof directory!=="string"||directory.trim()==="")return JSON.stringify({gates_passed:!1,lint:{ran:!1,error:"project directory is required but was not provided",duration_ms:0},secretscan:{ran:!1,error:"project directory is required but was not provided",duration_ms:0},sast_scan:{ran:!1,error:"project directory is required but was not provided",duration_ms:0},quality_budget:{ran:!1,error:"project directory is required but was not provided",duration_ms:0},total_duration_ms:0},null,2);let typedArgs=args2;if(!typedArgs.directory)return JSON.stringify({gates_passed:!1,lint:{ran:!1,error:"directory is required",duration_ms:0},secretscan:{ran:!1,error:"directory is required",duration_ms:0},sast_scan:{ran:!1,error:"directory is required",duration_ms:0},quality_budget:{ran:!1,error:"directory is required",duration_ms:0},total_duration_ms:0},null,2);let resolvedDirectory=path215.resolve(typedArgs.directory),workspaceAnchor=path215.resolve(directory);if(resolvedDirectory!==workspaceAnchor&&resolvedDirectory.startsWith(workspaceAnchor+path215.sep)){let subDirError=`directory "${typedArgs.directory}" is a subdirectory of the project root — pre_check_batch requires the project root directory "${workspaceAnchor}"`;return JSON.stringify({gates_passed:!1,lint:{ran:!1,error:subDirError,duration_ms:0},secretscan:{ran:!1,error:subDirError,duration_ms:0},sast_scan:{ran:!1,error:subDirError,duration_ms:0},quality_budget:{ran:!1,error:subDirError,duration_ms:0},total_duration_ms:0},null,2)}let dirError=validateDirectory2(resolvedDirectory,workspaceAnchor);if(dirError)return JSON.stringify({gates_passed:!1,lint:{ran:!1,error:dirError,duration_ms:0},secretscan:{ran:!1,error:dirError,duration_ms:0},sast_scan:{ran:!1,error:dirError,duration_ms:0},quality_budget:{ran:!1,error:dirError,duration_ms:0},total_duration_ms:0},null,2);try{let rawPhase=typedArgs.phase,safePhase=typeof rawPhase==="number"&&Number.isInteger(rawPhase)&&rawPhase>=1?rawPhase:void 0,result=await runPreCheckBatch({files:typedArgs.files,directory:resolvedDirectory,sast_threshold:typedArgs.sast_threshold,config:typedArgs.config,phase:safePhase},workspaceAnchor,directory);return JSON.stringify(result,null,2)}catch(error93){let errorMessage3=error93 instanceof Error?error93.message:"Unknown error";return JSON.stringify({gates_passed:!1,lint:{ran:!1,error:errorMessage3,duration_ms:0},secretscan:{ran:!1,error:errorMessage3,duration_ms:0},sast_scan:{ran:!1,error:errorMessage3,duration_ms:0},quality_budget:{ran:!1,error:errorMessage3,duration_ms:0},total_duration_ms:0},null,2)}}});init_zod();init_path_security();init_create_tool();import*as path216 from"node:path";var VALID_ACTIONS=["build","importers","dependencies","blast_radius","localization","key_files","ontology","package_boundaries","preflight_packet","callers","dead_exports","context_pack","graph_health"],MAX_FILE_PATH_LENGTH3=500,MAX_SYMBOL_LENGTH2=256;function validateFile(p){if(!p||typeof p!=="string")return"file is required";if(p.length===0)return"file is empty";if(p.length>MAX_FILE_PATH_LENGTH3)return`file exceeds maximum length of ${MAX_FILE_PATH_LENGTH3}`;if(containsControlChars(p))return"file contains control characters";if(containsPathTraversal(p))return"file contains path traversal";if(path216.isAbsolute(p)||/^[a-zA-Z]:[\\/]/.test(p))return"file must be a workspace-relative path, not absolute";return null}function validateSymbol(s){if(s.length===0)return"symbol is empty";if(s.length>MAX_SYMBOL_LENGTH2)return`symbol exceeds maximum length of ${MAX_SYMBOL_LENGTH2}`;if(containsControlChars(s))return"symbol contains control characters";return null}function err(action,message){return JSON.stringify({success:!1,action,error:message},null,2)}function ok(action,payload){return JSON.stringify({success:!0,action,...payload},null,2)}function toRelativeGraphPath(input,workspaceRoot){let normalized=input.replace(/\\/g,"/");if(path216.isAbsolute(normalized)){let rel=path216.relative(workspaceRoot,normalized).replace(/\\/g,"/");return normalizeGraphPath(rel)}return normalizeGraphPath(normalized)}async function loadOrError(directory,action){try{let graph=await loadGraph(directory);if(!graph)return{ok:!1,response:err(action,'No repo graph found at .swarm/repo-graph.json. Run repo_map with action="build" first.')};return{ok:!0,graph}}catch(error93){let message=error93 instanceof Error?error93.message:String(error93);return{ok:!1,response:err(action,`failed to load repo graph: ${message}`)}}}var repo_map=createSwarmTool({description:'Query the repository code graph for structural awareness before editing. Actions: "build" (build/refresh .swarm/repo-graph.json), "importers" (who imports a file), "dependencies" (what a file imports), "blast_radius" (transitive dependents + risk), "localization" (compact context block for a target file), "key_files" (top-N most-imported files), "ontology" (file roles/routes/data/security/findings), "package_boundaries" (inferred package/layer boundaries), "preflight_packet" (bounded ontology packet for planning), "callers" (files that reference an exported symbol, call-site granularity; needs file+symbol), "dead_exports" (advisory: exported symbols with no detected in-repo reference; results are review candidates, not delete directives), '+'"context_pack" (token-budgeted slice of source spans for a target symbol — definition + transitive callers/callees; advisory/conservative; needs file+symbol; uses max_depth for traversal depth, top_n for span cap), '+'"graph_health" (freshness and bounded extraction diagnostics; no file required). Use this before refactoring shared modules to avoid breaking unseen consumers. Note: "callers"/"dead_exports"/"context_pack" use conservative regex analysis (TS/JS/Python) and cannot see dynamic dispatch or namespace/barrel re-export usage; "dead_exports" results are review candidates, not delete directives.',args:{action:exports_external.enum(["build","importers","dependencies","blast_radius","localization","key_files","ontology","package_boundaries","preflight_packet","callers","dead_exports","context_pack","graph_health"]).describe('Query action: "build" | "importers" | "dependencies" | "blast_radius" | "localization" | "key_files" | "ontology" | "package_boundaries" | "preflight_packet" | "callers" | "dead_exports" | "context_pack" | "graph_health"'),file:exports_external.string().optional().describe("Target file (workspace-relative or absolute). Required for importers/dependencies/localization/ontology. Optional for preflight_packet."),files:exports_external.array(exports_external.string()).optional().describe("Multiple target files for blast_radius/preflight_packet. If omitted, falls back to `file`."),symbol:exports_external.string().optional().describe('Exported symbol name. Restricts consumers on action="importers"; required for action="callers"/"context_pack".'),top_n:exports_external.number().int().min(1).max(100).optional().describe('For action="key_files"/"package_boundaries": entries to return (default 10). For action="dead_exports": max candidates (default 100). For action="context_pack": max spans returned (default ~40 via token budget).'),max_depth:exports_external.number().int().min(1).max(10).optional().describe('For action="blast_radius": max BFS depth (default 3). For action="context_pack": traversal depth (default 2).')},async execute(args2,directory,_ctx){let a=args2??{},action=String(a.action??"");if(!VALID_ACTIONS.includes(action))return err(action||"(none)",`unknown action; expected one of: ${VALID_ACTIONS.join(", ")}`);if(action==="build")try{let start=Date.now(),graph2=await buildWorkspaceGraphAsync(directory);await saveGraph(directory,graph2);let elapsedMs=Date.now()-start,fileCount=Object.keys(graph2.nodes).length,edgeCount=graph2.edges.length,ontologyFileCount=Object.values(graph2.nodes).filter((node)=>node.ontology!==void 0).length;return ok(action,{fileCount,edgeCount,ontologyFileCount,buildTimestamp:graph2.metadata.generatedAt,elapsedMs,path:".swarm/repo-graph.json"})}catch(e){let message=e instanceof Error?e.message:String(e);return err(action,`build failed: ${message}`)}if(action==="graph_health")try{let graph2=await loadGraph(directory);return ok(action,{...getGraphHealth(graph2,directory)})}catch(e){let message=e instanceof Error?e.message:String(e);return err(action,`failed to load repo graph: ${message}`)}let loaded=await loadOrError(directory,action);if(!loaded.ok)return loaded.response;let graph=loaded.graph,stale=!isGraphFresh(graph);if(action==="key_files"){let topN=a.top_n??10,reverseCounts=getKeyFiles(graph,topN).map((n)=>({file:n.moduleName,language:n.language,exports:n.exports.length,roles:n.ontology?.roles??[],findings:n.ontology?.findings.length??0,inDegree:getImporters(graph,n.moduleName).length}));return ok(action,{count:reverseCounts.length,files:reverseCounts,stale})}if(action==="package_boundaries"){let topN=a.top_n??10,boundaries=getPackageBoundaries(graph,topN);return ok(action,{count:boundaries.length,boundaries,stale})}if(action==="dead_exports"){let result=getDeadExports(graph,{maxCandidates:a.top_n??100});return ok(action,{...result,stale})}if(action==="preflight_packet"){let inputs=a.files&&a.files.length>0?a.files:a.file?[a.file]:[];for(let f of inputs){let v=validateFile(f);if(v)return err(action,`invalid file: ${v}`)}let targets=inputs.map((f)=>toRelativeGraphPath(f,directory));return ok(action,{packet:buildOntologyPreflightPacket(graph,targets,{maxFiles:a.top_n??12,maxBoundaries:10}),stale})}if(action==="blast_radius"){let inputs=a.files&&a.files.length>0?a.files:a.file?[a.file]:null;if(!inputs)return err(action,"blast_radius requires `file` or `files`");for(let f of inputs){let v=validateFile(f);if(v)return err(action,`invalid file: ${v}`)}let targets=inputs.map((f)=>toRelativeGraphPath(f,directory)),result=getBlastRadius(graph,targets,a.max_depth??3);return ok(action,{...result,stale})}if(!a.file)return err(action,`${action} requires \`file\``);let fileErr=validateFile(a.file);if(fileErr)return err(action,`invalid file: ${fileErr}`);let target=toRelativeGraphPath(a.file,directory);if(action==="importers"){if(a.symbol!==void 0){let sErr=validateSymbol(a.symbol);if(sErr)return err(action,`invalid symbol: ${sErr}`);let consumers=getSymbolConsumers(graph,target,a.symbol);return ok(action,{target,symbol:a.symbol,count:consumers.length,consumers,stale})}let importers=getImporters(graph,target);return ok(action,{target,count:importers.length,importers,stale})}if(action==="callers"){if(a.symbol===void 0)return err(action,"callers requires `symbol` (the exported name)");let sErr=validateSymbol(a.symbol);if(sErr)return err(action,`invalid symbol: ${sErr}`);let callers=getCallers(graph,target,a.symbol);return ok(action,{target,symbol:a.symbol,count:callers.length,callers,stale})}if(action==="context_pack"){if(a.symbol===void 0)return err(action,"context_pack requires `symbol` (the exported name)");let sErr=validateSymbol(a.symbol);if(sErr)return err(action,`invalid symbol: ${sErr}`);let raw=getContextPack(graph,target,a.symbol,{maxDepth:a.max_depth??2,maxTokens:4000}),toRel=(p)=>{if(!path216.isAbsolute(p))return p.replace(/\\/g,"/");try{return path216.relative(directory,p).replace(/\\/g,"/")}catch{return p}},normalizedTarget={...raw.target,file:toRel(raw.target.file)},normalizedSpans=raw.spans.map((s)=>({...s,file:toRel(s.file)})).filter((s)=>s.file.length>0),truncated=raw.truncated||a.top_n!==void 0&&normalizedSpans.length>a.top_n,cappedSpans=a.top_n!==void 0?normalizedSpans.slice(0,a.top_n):normalizedSpans;return ok(action,{target:normalizedTarget,spans:cappedSpans,truncated,estimatedTokens:raw.estimatedTokens,stale,schemaSupported:raw.schemaSupported,...raw.note?{note:raw.note}:{}})}if(action==="dependencies"){let deps=getDependencies(graph,target);return ok(action,{target,count:deps.length,dependencies:deps,stale})}if(action==="localization"){let ctx=getLocalizationContext(graph,target,{maxDepth:a.max_depth});return ok(action,{...ctx,stale})}if(action==="ontology"){let ontology=getFileOntology(graph,target);if(!ontology)return err(action,`No ontology facts found for ${target}. Rebuild the graph if the file was recently added.`);return ok(action,{target,ontology,stale})}return err(action,"unhandled action")}});init_zod();init_effective_spec();init_create_tool();import*as fs137 from"node:fs";import*as path217 from"node:path";var EVIDENCE_DIR4=".swarm/evidence",OBLIGATION_KEYWORDS2=["MUST","SHOULD","SHALL"],MAX_FILE_SIZE_BYTES8=1048576;function extractRequirements(specContent){let requirements=[],lines=specContent.split(`
|
|
6002
|
-
`),frLineRegex=/^\s*[-*]?\s*(FR-\d{3})\s*[:.\-)]\s*(.+)/gi,frInlineRegex=/\b(FR-\d{3})\b[^.!?]*?(MUST|SHOULD|SHALL)[^.!?]*[.!?]?/gi;for(let line of lines){let lineMatchResults=[...line.matchAll(frLineRegex)];if(lineMatchResults.length>0){let lineMatch=lineMatchResults[0],id=lineMatch[1].toUpperCase(),restOfLine=lineMatch[2],extracted=extractObligationAndText(id,restOfLine);if(extracted)requirements.push(extracted);continue}for(let inlineMatch of line.matchAll(frInlineRegex)){let id=inlineMatch[1].toUpperCase(),matchedText=inlineMatch[0];if(!requirements.some((r)=>r.id===id)){let extracted=extractObligationAndText(id,matchedText);if(extracted)requirements.push(extracted)}}}return requirements}function extractObligationAndText(id,lineText){let obligation=null,text=lineText.trim();for(let keyword of OBLIGATION_KEYWORDS2)if(new RegExp(`\\b${keyword}\\b`,"i").test(text)){obligation=keyword;break}if(obligation){let obligationRegex=new RegExp(`\\b${obligation}\\b`,"i");text=text.replace(obligationRegex,"").replace(/\s+/g," ").trim()}if(text=text.replace(/^[:\-.)\s]+/,"").trim(),!text)return null;return{id,obligation,text}}var PHASE_TASK_ID_REGEX=/^\d+\.\d+(\.\d+)*$/;function readTouchedFiles(evidenceDir,phase,cwd){let touchedFiles=new Set;if(!fs137.existsSync(evidenceDir)||!fs137.statSync(evidenceDir).isDirectory())return[];let entries;try{entries=fs137.readdirSync(evidenceDir)}catch{return[]}for(let entry of entries){let entryPath=path217.join(evidenceDir,entry);try{if(!fs137.statSync(entryPath).isDirectory())continue}catch{continue}if(!PHASE_TASK_ID_REGEX.test(entry))continue;if(entry.split(".")[0]!==String(phase))continue;let evidenceFilePath=path217.join(entryPath,"evidence.json");try{let resolvedPath=path217.resolve(evidenceFilePath),evidenceDirResolved=path217.resolve(evidenceDir);if(!resolvedPath.startsWith(evidenceDirResolved+path217.sep))continue;let stat14=fs137.lstatSync(evidenceFilePath);if(!stat14.isFile())continue;if(stat14.size>MAX_FILE_SIZE_BYTES8)continue}catch{continue}let content;try{content=fs137.readFileSync(evidenceFilePath,"utf-8")}catch{continue}let parsed;try{parsed=JSON.parse(content)}catch{continue}if(parsed&&typeof parsed==="object"){let obj=parsed;if(Array.isArray(obj.entries)){for(let entryItem of obj.entries)if(entryItem&&typeof entryItem==="object"&&entryItem.type==="diff"){let diffEntry=entryItem;if(Array.isArray(diffEntry.files_changed)){for(let file3 of diffEntry.files_changed)if(typeof file3==="string")touchedFiles.add(path217.resolve(cwd,file3))}}}}}return Array.from(touchedFiles)}function searchFileForKeywords(filePath,keywords,cwd){try{let resolvedPath=path217.resolve(filePath),cwdResolved=path217.resolve(cwd);if(!resolvedPath.startsWith(cwdResolved))return!1;let content=fs137.readFileSync(resolvedPath,"utf-8");for(let keyword of keywords)if(new RegExp(`\\b${keyword}\\b`,"i").test(content))return!0;return!1}catch{return!1}}function analyzeRequirementCoverage(requirement,touchedFiles,cwd){let keywords=[],stopWords=new Set(["the","a","an","and","or","but","in","on","at","to","for","of","with","by","from","as","is","was","are","be","been","being","have","has","had","do","does","did","will","would","could","should","may","might","must","shall","can","need","that","this","these","those","it","its","they","them"]),wordRegex=/\b[a-zA-Z]{4,}\b/g,words=requirement.text.match(wordRegex)||[];for(let word of words){let lower=word.toLowerCase();if(!stopWords.has(lower))keywords.push(word)}let foundCount=0,searchedFiles=[];for(let file3 of touchedFiles){if(!file3.match(/\.(ts|js|tsx|jsx|py|go|rs|java|c|cpp|h|cs|rb|php)$/i))continue;if(searchedFiles.push(file3),searchFileForKeywords(file3,keywords,cwd))foundCount++}let status;if(foundCount>=1)status="covered";else status="missing";if(searchedFiles.length===0)status="missing";return{id:requirement.id,obligation:requirement.obligation,text:requirement.text,status,filesSearched:searchedFiles}}var req_coverage=createSwarmTool({description:"Analyze requirement coverage for FR requirements against touched files. Reads .swarm/spec.md for FR-### requirements and checks coverage against files touched during a phase via evidence files. Produces coverage report.",args:{phase:exports_external.number().int().min(1).describe("The phase number to analyze coverage for"),directory:exports_external.string().optional().describe("Working directory (defaults to plugin context directory)")},async execute(args2,directory){let phase,inputDirectory;try{if(args2&&typeof args2==="object"){let obj=args2;phase=typeof obj.phase==="number"?obj.phase:typeof obj.phase==="string"?Number(obj.phase):NaN,inputDirectory=typeof obj.directory==="string"?obj.directory:void 0}else phase=NaN}catch{phase=NaN}if(Number.isNaN(phase)||phase<1||!Number.isFinite(phase))return JSON.stringify({success:!1,phase:0,totalRequirements:0,coveredCount:0,missingCount:0,requirements:[],error:"Invalid phase number"},null,2);let cwd=inputDirectory||directory,spec=readEffectiveSpecSync(cwd);if(!spec)return JSON.stringify({success:!1,phase,totalRequirements:0,coveredCount:0,missingCount:0,requirements:[],error:"Failed to read effective spec: .swarm/spec.md is missing and no OpenSpec-compatible projection is available"},null,2);let specContent=spec.content,requirements=extractRequirements(specContent);if(requirements.length===0)return JSON.stringify({success:!0,phase,totalRequirements:0,coveredCount:0,missingCount:0,requirements:[],message:"No FR requirements found in spec.md"},null,2);let evidenceDir=path217.join(cwd,EVIDENCE_DIR4),touchedFiles=readTouchedFiles(evidenceDir,phase,cwd),analyzedRequirements=[],coveredCount=0,missingCount=0;for(let req of requirements){let analysis=analyzeRequirementCoverage(req,touchedFiles,cwd);switch(analyzedRequirements.push(analysis),analysis.status){case"covered":coveredCount++;break;case"missing":missingCount++;break}}let result={success:!0,phase,totalRequirements:requirements.length,coveredCount,missingCount,requirements:analyzedRequirements},reportFilename=`req-coverage-phase-${phase}.json`,reportPath=path217.join(evidenceDir,reportFilename);try{if(!fs137.existsSync(evidenceDir))fs137.mkdirSync(evidenceDir,{recursive:!0});fs137.writeFileSync(reportPath,JSON.stringify(result,null,2),"utf-8")}catch(writeError){
|
|
6001
|
+
`)){if(line.startsWith("+++ b/")){if(currentFile=line.slice(6).trim(),!result.has(currentFile))result.set(currentFile,new Set);continue}if(line.startsWith("@@")&¤tFile){let match=line.match(/^@@ [^+]*\+(\d+)(?:,(\d+))? @@/);if(match){let start=parseInt(match[1],10),count=match[2]!==void 0?parseInt(match[2],10):1,lines=result.get(currentFile);for(let i=start;i<start+count;i++)lines.add(i)}}}return result}async function getChangedLineRanges(directory){try{for(let baseBranch of["origin/main","origin/master","main","master"]){let mergeBaseProc=bunSpawn(["git","merge-base",baseBranch,"HEAD"],{cwd:directory,stdout:"pipe",stderr:"pipe"}),[mbExit,mbOut]=await Promise.all([mergeBaseProc.exited,mergeBaseProc.stdout.text()]);if(mbExit===0&&mbOut.trim()){let mergeBase=mbOut.trim(),diffOut=await runGitDiff(["-U0",`${mergeBase}..HEAD`],directory);if(diffOut)return parseDiffLineRanges(diffOut)}}let diffHead1=await runGitDiff(["-U0","HEAD~1"],directory);if(diffHead1)return parseDiffLineRanges(diffHead1);let diffHead=await runGitDiff(["-U0","HEAD"],directory);if(diffHead)return parseDiffLineRanges(diffHead);return null}catch{return null}}function classifySastFindings(findings,changedLineRanges,directory){if(!changedLineRanges||changedLineRanges.size===0)return{newFindings:findings,preexistingFindings:[]};let newFindings=[],preexistingFindings=[];for(let finding of findings){let filePath=finding.location.file,normalised=path215.relative(directory,filePath).replace(/\\/g,"/");if(changedLineRanges.get(normalised)?.has(finding.location.line))newFindings.push(finding);else preexistingFindings.push(finding)}return{newFindings,preexistingFindings}}async function runPreCheckBatch(input,workspaceDir,contextDir){let effectiveWorkspaceDir=workspaceDir||input.directory||contextDir,{files,directory,sast_threshold="medium",config:config3,phase}=input,dirError=validateDirectory2(directory,effectiveWorkspaceDir);if(dirError)return warn(`pre_check_batch: Invalid directory: ${dirError}`),{gates_passed:!1,lint:{ran:!1,error:dirError,duration_ms:0},secretscan:{ran:!1,error:dirError,duration_ms:0},sast_scan:{ran:!1,error:dirError,duration_ms:0},quality_budget:{ran:!1,error:dirError,duration_ms:0},total_duration_ms:0};if(!files||files.length===0)return warn("pre_check_batch: No files provided, skipping all tools (fail-closed)"),{gates_passed:!1,lint:{ran:!1,error:"No files provided",duration_ms:0},secretscan:{ran:!1,error:"No files provided",duration_ms:0},sast_scan:{ran:!1,error:"No files provided",duration_ms:0},quality_budget:{ran:!1,error:"No files provided",duration_ms:0},total_duration_ms:0};let changedFiles=[];for(let file3 of files){if(typeof file3!=="string"){warn(`pre_check_batch: Non-string file entry rejected: ${String(file3)}`);continue}if(validatePath(file3,directory,effectiveWorkspaceDir)){warn(`pre_check_batch: Invalid file path: ${file3}`);continue}changedFiles.push(path215.resolve(directory,file3))}if(changedFiles.length===0)return warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)"),{gates_passed:!1,lint:{ran:!1,error:"No files provided",duration_ms:0},secretscan:{ran:!1,error:"No files provided",duration_ms:0},sast_scan:{ran:!1,error:"No files provided",duration_ms:0},quality_budget:{ran:!1,error:"No files provided",duration_ms:0},total_duration_ms:0};if(changedFiles.length>MAX_FILES)throw Error(`Input exceeds maximum file count: ${changedFiles.length} > ${MAX_FILES}`);let limit=pLimit(MAX_CONCURRENT),[lintResult,secretscanResult,sastScanResult,qualityBudgetResult]=await Promise.all([limit(()=>runLintWrapped(changedFiles,directory,config3)),limit(()=>runSecretscanWrapped(changedFiles,directory,config3)),limit(()=>runSastScanWrapped(changedFiles,directory,sast_threshold,config3,phase)),limit(()=>runQualityBudgetWrapped(changedFiles,directory,config3))]),totalDuration=lintResult.duration_ms+secretscanResult.duration_ms+sastScanResult.duration_ms+qualityBudgetResult.duration_ms,gatesPassed=!0;if(lintResult.ran&&lintResult.result){let lintRes=lintResult.result;if("success"in lintRes&&lintRes.success===!1)warn("pre_check_batch: Lint found issues (informational only)")}else if(lintResult.error)warn(`pre_check_batch: Lint error (informational only): ${lintResult.error}`);if(secretscanResult.ran&&secretscanResult.result){let scanResult=secretscanResult.result;if("error"in scanResult&&scanResult.error)gatesPassed=!1,warn(`pre_check_batch: Secretscan error - GATE FAILED: ${scanResult.error}`);else if("findings"in scanResult&&scanResult.findings.length>0)gatesPassed=!1,warn("pre_check_batch: Secretscan found secrets - GATE FAILED");else if(files&&files.length>0&&(scanResult.files_scanned??0)===0)gatesPassed=!1,warn("pre_check_batch: Secretscan scanned 0 files despite requested file scope - GATE FAILED (possible vacuous pass)")}else if(secretscanResult.error)gatesPassed=!1,warn(`pre_check_batch: Secretscan error - GATE FAILED: ${secretscanResult.error}`);if(secretscanResult.ran&&secretscanResult.result)try{let scanResult=secretscanResult.result,secretscanEvidence={task_id:"secretscan",type:"secretscan",timestamp:new Date().toISOString(),agent:"pre_check_batch",verdict:scanResult.count>0?"fail":"pass",summary:`Secretscan: ${scanResult.count} finding(s), ${scanResult.files_scanned??0} files scanned, ${scanResult.skipped_files??0} skipped`,findings_count:scanResult.count,scan_directory:scanResult.scan_dir,files_scanned:scanResult.files_scanned,skipped_files:scanResult.skipped_files};await saveEvidence(directory,"secretscan",secretscanEvidence)}catch(e){warn(`Failed to persist secretscan evidence: ${e instanceof Error?e.message:String(e)}`)}let sastPreexistingFindings;if(sastScanResult.ran&&sastScanResult.result){let sastResult=sastScanResult.result;if(sastResult.baseline_used){if(sastResult.pre_existing_findings&&sastResult.pre_existing_findings.length>0){if(sastPreexistingFindings=sastResult.pre_existing_findings.filter((f)=>meetsThresholdForTriage(f.severity,sast_threshold)),sastPreexistingFindings.length>0)warn(`pre_check_batch: SAST baseline diff found ${sastPreexistingFindings.length} pre-existing finding(s) - passing to reviewer for triage`)}if(sastResult.verdict==="fail")gatesPassed=!1,warn("pre_check_batch: SAST scan found new findings above threshold - GATE FAILED")}else if(sastResult.verdict==="fail"){let gateFindings=sastResult.findings.filter((f)=>GATE_SEVERITIES.has(f.severity));if(gateFindings.length>0){let changedLineRanges=await getChangedLineRanges(directory),{newFindings,preexistingFindings}=classifySastFindings(gateFindings,changedLineRanges,directory);if(newFindings.length>0)gatesPassed=!1,warn(`pre_check_batch: SAST scan found ${newFindings.length} new HIGH/CRITICAL finding(s) on changed lines - GATE FAILED`);else if(preexistingFindings.length>0)sastPreexistingFindings=preexistingFindings,warn(`pre_check_batch: SAST scan found ${preexistingFindings.length} pre-existing HIGH/CRITICAL finding(s) on unchanged lines - passing to reviewer for triage`)}else gatesPassed=!1,warn("pre_check_batch: SAST scan found vulnerabilities - GATE FAILED")}}else if(sastScanResult.error)gatesPassed=!1,warn(`pre_check_batch: SAST scan error - GATE FAILED: ${sastScanResult.error}`);if(qualityBudgetResult.ran&&qualityBudgetResult.result){if(qualityBudgetResult.result.verdict==="fail")warn("pre_check_batch: Quality budget exceeded (informational only)")}else if(qualityBudgetResult.error)warn(`pre_check_batch: Quality budget error (informational only): ${qualityBudgetResult.error}`);let result={gates_passed:gatesPassed,lint:lintResult,secretscan:secretscanResult,sast_scan:sastScanResult,quality_budget:qualityBudgetResult,total_duration_ms:Math.round(totalDuration),...sastPreexistingFindings&&sastPreexistingFindings.length>0&&{sast_preexisting_findings:sastPreexistingFindings}},outputSize=JSON.stringify(result).length;if(outputSize>MAX_COMBINED_BYTES)warn(`pre_check_batch: Large output (${outputSize} bytes)`);return result}var pre_check_batch=createSwarmTool({description:"Run multiple verification tools in parallel: lint, secretscan, SAST scan, and quality budget. Returns unified result with gates_passed status. Security tools (secretscan, sast_scan) are HARD GATES - failures block merging.",args:{files:exports_external.array(exports_external.string()).optional().describe("Specific files to check (optional, scans directory if not provided)"),directory:exports_external.string().describe("Project root directory — must be the workspace root, subdirectories are rejected"),sast_threshold:exports_external.enum(["low","medium","high","critical"]).optional().describe("Minimum severity for SAST findings to cause failure (default: medium)"),phase:exports_external.number().int().min(1).optional().describe("Current phase number (positive integer >= 1). When provided, enables SAST baseline diffing: only findings absent from the phase-scoped baseline fail the gate.")},async execute(args2,directory){if(!args2||typeof args2!=="object")return JSON.stringify({gates_passed:!1,lint:{ran:!1,error:"Invalid arguments",duration_ms:0},secretscan:{ran:!1,error:"Invalid arguments",duration_ms:0},sast_scan:{ran:!1,error:"Invalid arguments",duration_ms:0},quality_budget:{ran:!1,error:"Invalid arguments",duration_ms:0},total_duration_ms:0},null,2);if(!directory||typeof directory!=="string"||directory.trim()==="")return JSON.stringify({gates_passed:!1,lint:{ran:!1,error:"project directory is required but was not provided",duration_ms:0},secretscan:{ran:!1,error:"project directory is required but was not provided",duration_ms:0},sast_scan:{ran:!1,error:"project directory is required but was not provided",duration_ms:0},quality_budget:{ran:!1,error:"project directory is required but was not provided",duration_ms:0},total_duration_ms:0},null,2);let typedArgs=args2;if(!typedArgs.directory)return JSON.stringify({gates_passed:!1,lint:{ran:!1,error:"directory is required",duration_ms:0},secretscan:{ran:!1,error:"directory is required",duration_ms:0},sast_scan:{ran:!1,error:"directory is required",duration_ms:0},quality_budget:{ran:!1,error:"directory is required",duration_ms:0},total_duration_ms:0},null,2);let resolvedDirectory=path215.resolve(typedArgs.directory),workspaceAnchor=path215.resolve(directory);if(resolvedDirectory!==workspaceAnchor&&resolvedDirectory.startsWith(workspaceAnchor+path215.sep)){let subDirError=`directory "${typedArgs.directory}" is a subdirectory of the project root — pre_check_batch requires the project root directory "${workspaceAnchor}"`;return JSON.stringify({gates_passed:!1,lint:{ran:!1,error:subDirError,duration_ms:0},secretscan:{ran:!1,error:subDirError,duration_ms:0},sast_scan:{ran:!1,error:subDirError,duration_ms:0},quality_budget:{ran:!1,error:subDirError,duration_ms:0},total_duration_ms:0},null,2)}let dirError=validateDirectory2(resolvedDirectory,workspaceAnchor);if(dirError)return JSON.stringify({gates_passed:!1,lint:{ran:!1,error:dirError,duration_ms:0},secretscan:{ran:!1,error:dirError,duration_ms:0},sast_scan:{ran:!1,error:dirError,duration_ms:0},quality_budget:{ran:!1,error:dirError,duration_ms:0},total_duration_ms:0},null,2);try{let rawPhase=typedArgs.phase,safePhase=typeof rawPhase==="number"&&Number.isInteger(rawPhase)&&rawPhase>=1?rawPhase:void 0,result=await runPreCheckBatch({files:typedArgs.files,directory:resolvedDirectory,sast_threshold:typedArgs.sast_threshold,config:typedArgs.config,phase:safePhase},workspaceAnchor,directory);return JSON.stringify(result,null,2)}catch(error93){let errorMessage3=error93 instanceof Error?error93.message:"Unknown error";return JSON.stringify({gates_passed:!1,lint:{ran:!1,error:errorMessage3,duration_ms:0},secretscan:{ran:!1,error:errorMessage3,duration_ms:0},sast_scan:{ran:!1,error:errorMessage3,duration_ms:0},quality_budget:{ran:!1,error:errorMessage3,duration_ms:0},total_duration_ms:0},null,2)}}});init_zod();init_path_security();init_create_tool();import*as path216 from"node:path";var VALID_ACTIONS=["build","importers","dependencies","blast_radius","localization","key_files","ontology","package_boundaries","preflight_packet","callers","dead_exports","context_pack","graph_health"],MAX_FILE_PATH_LENGTH3=500,MAX_SYMBOL_LENGTH2=256;function validateFile(p){if(!p||typeof p!=="string")return"file is required";if(p.length===0)return"file is empty";if(p.length>MAX_FILE_PATH_LENGTH3)return`file exceeds maximum length of ${MAX_FILE_PATH_LENGTH3}`;if(containsControlChars(p))return"file contains control characters";if(containsPathTraversal(p))return"file contains path traversal";if(path216.isAbsolute(p)||/^[a-zA-Z]:[\\/]/.test(p))return"file must be a workspace-relative path, not absolute";return null}function validateSymbol(s){if(s.length===0)return"symbol is empty";if(s.length>MAX_SYMBOL_LENGTH2)return`symbol exceeds maximum length of ${MAX_SYMBOL_LENGTH2}`;if(containsControlChars(s))return"symbol contains control characters";return null}function err(action,message){return JSON.stringify({success:!1,action,error:message},null,2)}function ok(action,payload){return JSON.stringify({success:!0,action,...payload},null,2)}function toRelativeGraphPath(input,workspaceRoot){let normalized=input.replace(/\\/g,"/");if(path216.isAbsolute(normalized)){let rel=path216.relative(workspaceRoot,normalized).replace(/\\/g,"/");return normalizeGraphPath(rel)}return normalizeGraphPath(normalized)}async function loadOrError(directory,action){try{let graph=await loadGraph(directory);if(!graph)return{ok:!1,response:err(action,'No repo graph found at .swarm/repo-graph.json. Run repo_map with action="build" first.')};return{ok:!0,graph}}catch(error93){let message=error93 instanceof Error?error93.message:String(error93);return{ok:!1,response:err(action,`failed to load repo graph: ${message}`)}}}var repo_map=createSwarmTool({description:'Query the repository code graph for structural awareness before editing. Actions: "build" (build/refresh .swarm/repo-graph.json), "importers" (who imports a file), "dependencies" (what a file imports), "blast_radius" (transitive dependents + risk), "localization" (compact context block for a target file), "key_files" (top-N most-imported files), "ontology" (file roles/routes/data/security/findings), "package_boundaries" (inferred package/layer boundaries), "preflight_packet" (bounded ontology packet for planning), "callers" (files that reference an exported symbol, call-site granularity; needs file+symbol), "dead_exports" (advisory: exported symbols with no detected in-repo reference; results are review candidates, not delete directives), '+'"context_pack" (token-budgeted slice of source spans for a target symbol — definition + transitive callers/callees; advisory/conservative; needs file+symbol; uses max_depth for traversal depth, top_n for span cap), '+'"graph_health" (freshness and bounded extraction diagnostics; no file required). Use this before refactoring shared modules to avoid breaking unseen consumers. Note: "callers"/"dead_exports"/"context_pack" use conservative regex analysis (TS/JS/Python) and cannot see dynamic dispatch or namespace/barrel re-export usage; "dead_exports" results are review candidates, not delete directives.',args:{action:exports_external.enum(["build","importers","dependencies","blast_radius","localization","key_files","ontology","package_boundaries","preflight_packet","callers","dead_exports","context_pack","graph_health"]).describe('Query action: "build" | "importers" | "dependencies" | "blast_radius" | "localization" | "key_files" | "ontology" | "package_boundaries" | "preflight_packet" | "callers" | "dead_exports" | "context_pack" | "graph_health"'),file:exports_external.string().optional().describe("Target file (workspace-relative or absolute). Required for importers/dependencies/localization/ontology. Optional for preflight_packet."),files:exports_external.array(exports_external.string()).optional().describe("Multiple target files for blast_radius/preflight_packet. If omitted, falls back to `file`."),symbol:exports_external.string().optional().describe('Exported symbol name. Restricts consumers on action="importers"; required for action="callers"/"context_pack".'),top_n:exports_external.number().int().min(1).max(100).optional().describe('For action="key_files"/"package_boundaries": entries to return (default 10). For action="dead_exports": max candidates (default 100). For action="context_pack": max spans returned (default ~40 via token budget).'),max_depth:exports_external.number().int().min(1).max(10).optional().describe('For action="blast_radius": max BFS depth (default 3). For action="context_pack": traversal depth (default 2).')},async execute(args2,directory,_ctx){let a=args2??{},action=String(a.action??"");if(!VALID_ACTIONS.includes(action))return err(action||"(none)",`unknown action; expected one of: ${VALID_ACTIONS.join(", ")}`);if(action==="build")try{let start=Date.now(),graph2=await buildWorkspaceGraphAsync(directory);await saveGraph(directory,graph2);let elapsedMs=Date.now()-start,fileCount=Object.keys(graph2.nodes).length,edgeCount=graph2.edges.length,ontologyFileCount=Object.values(graph2.nodes).filter((node)=>node.ontology!==void 0).length;return ok(action,{fileCount,edgeCount,ontologyFileCount,buildTimestamp:graph2.metadata.generatedAt,elapsedMs,path:".swarm/repo-graph.json"})}catch(e){let message=e instanceof Error?e.message:String(e);return err(action,`build failed: ${message}`)}if(action==="graph_health")try{let graph2=await loadGraph(directory);return ok(action,{...getGraphHealth(graph2,directory)})}catch(e){let message=e instanceof Error?e.message:String(e);return err(action,`failed to load repo graph: ${message}`)}let loaded=await loadOrError(directory,action);if(!loaded.ok)return loaded.response;let graph=loaded.graph,stale=!isGraphFresh(graph);if(action==="key_files"){let topN=a.top_n??10,reverseCounts=getKeyFiles(graph,topN).map((n)=>({file:n.moduleName,language:n.language,exports:n.exports.length,roles:n.ontology?.roles??[],findings:n.ontology?.findings.length??0,inDegree:getImporters(graph,n.moduleName).length}));return ok(action,{count:reverseCounts.length,files:reverseCounts,stale})}if(action==="package_boundaries"){let topN=a.top_n??10,boundaries=getPackageBoundaries(graph,topN);return ok(action,{count:boundaries.length,boundaries,stale})}if(action==="dead_exports"){let result=getDeadExports(graph,{maxCandidates:a.top_n??100});return ok(action,{...result,stale})}if(action==="preflight_packet"){let inputs=a.files&&a.files.length>0?a.files:a.file?[a.file]:[];for(let f of inputs){let v=validateFile(f);if(v)return err(action,`invalid file: ${v}`)}let targets=inputs.map((f)=>toRelativeGraphPath(f,directory));return ok(action,{packet:buildOntologyPreflightPacket(graph,targets,{maxFiles:a.top_n??12,maxBoundaries:10}),stale})}if(action==="blast_radius"){let inputs=a.files&&a.files.length>0?a.files:a.file?[a.file]:null;if(!inputs)return err(action,"blast_radius requires `file` or `files`");for(let f of inputs){let v=validateFile(f);if(v)return err(action,`invalid file: ${v}`)}let targets=inputs.map((f)=>toRelativeGraphPath(f,directory)),result=getBlastRadius(graph,targets,a.max_depth??3);return ok(action,{...result,stale})}if(!a.file)return err(action,`${action} requires \`file\``);let fileErr=validateFile(a.file);if(fileErr)return err(action,`invalid file: ${fileErr}`);let target=toRelativeGraphPath(a.file,directory);if(action==="importers"){if(a.symbol!==void 0){let sErr=validateSymbol(a.symbol);if(sErr)return err(action,`invalid symbol: ${sErr}`);let consumers=getSymbolConsumers(graph,target,a.symbol);return ok(action,{target,symbol:a.symbol,count:consumers.length,consumers,stale})}let importers=getImporters(graph,target);return ok(action,{target,count:importers.length,importers,stale})}if(action==="callers"){if(a.symbol===void 0)return err(action,"callers requires `symbol` (the exported name)");let sErr=validateSymbol(a.symbol);if(sErr)return err(action,`invalid symbol: ${sErr}`);let callers=getCallers(graph,target,a.symbol);return ok(action,{target,symbol:a.symbol,count:callers.length,callers,stale})}if(action==="context_pack"){if(a.symbol===void 0)return err(action,"context_pack requires `symbol` (the exported name)");let sErr=validateSymbol(a.symbol);if(sErr)return err(action,`invalid symbol: ${sErr}`);let raw=getContextPack(graph,target,a.symbol,{maxDepth:a.max_depth??2,maxTokens:4000}),toRel=(p)=>{if(!path216.isAbsolute(p))return p.replace(/\\/g,"/");try{return path216.relative(directory,p).replace(/\\/g,"/")}catch{return p}},normalizedTarget={...raw.target,file:toRel(raw.target.file)},normalizedSpans=raw.spans.map((s)=>({...s,file:toRel(s.file)})).filter((s)=>s.file.length>0),truncated=raw.truncated||a.top_n!==void 0&&normalizedSpans.length>a.top_n,cappedSpans=a.top_n!==void 0?normalizedSpans.slice(0,a.top_n):normalizedSpans;return ok(action,{target:normalizedTarget,spans:cappedSpans,truncated,estimatedTokens:raw.estimatedTokens,stale,schemaSupported:raw.schemaSupported,...raw.note?{note:raw.note}:{}})}if(action==="dependencies"){let deps=getDependencies(graph,target);return ok(action,{target,count:deps.length,dependencies:deps,stale})}if(action==="localization"){let ctx=getLocalizationContext(graph,target,{maxDepth:a.max_depth});return ok(action,{...ctx,stale})}if(action==="ontology"){let ontology=getFileOntology(graph,target);if(!ontology)return err(action,`No ontology facts found for ${target}. Rebuild the graph if the file was recently added.`);return ok(action,{target,ontology,stale})}return err(action,"unhandled action")}});init_zod();init_effective_spec();init_logger();init_create_tool();import*as fs137 from"node:fs";import*as path217 from"node:path";var EVIDENCE_DIR4=".swarm/evidence",OBLIGATION_KEYWORDS2=["MUST","SHOULD","SHALL"],MAX_FILE_SIZE_BYTES8=1048576;function extractRequirements(specContent){let requirements=[],lines=specContent.split(`
|
|
6002
|
+
`),frLineRegex=/^\s*[-*]?\s*(FR-\d{3})\s*[:.\-)]\s*(.+)/gi,frInlineRegex=/\b(FR-\d{3})\b[^.!?]*?(MUST|SHOULD|SHALL)[^.!?]*[.!?]?/gi;for(let line of lines){let lineMatchResults=[...line.matchAll(frLineRegex)];if(lineMatchResults.length>0){let lineMatch=lineMatchResults[0],id=lineMatch[1].toUpperCase(),restOfLine=lineMatch[2],extracted=extractObligationAndText(id,restOfLine);if(extracted)requirements.push(extracted);continue}for(let inlineMatch of line.matchAll(frInlineRegex)){let id=inlineMatch[1].toUpperCase(),matchedText=inlineMatch[0];if(!requirements.some((r)=>r.id===id)){let extracted=extractObligationAndText(id,matchedText);if(extracted)requirements.push(extracted)}}}return requirements}function extractObligationAndText(id,lineText){let obligation=null,text=lineText.trim();for(let keyword of OBLIGATION_KEYWORDS2)if(new RegExp(`\\b${keyword}\\b`,"i").test(text)){obligation=keyword;break}if(obligation){let obligationRegex=new RegExp(`\\b${obligation}\\b`,"i");text=text.replace(obligationRegex,"").replace(/\s+/g," ").trim()}if(text=text.replace(/^[:\-.)\s]+/,"").trim(),!text)return null;return{id,obligation,text}}var PHASE_TASK_ID_REGEX=/^\d+\.\d+(\.\d+)*$/;function readTouchedFiles(evidenceDir,phase,cwd){let touchedFiles=new Set;if(!fs137.existsSync(evidenceDir)||!fs137.statSync(evidenceDir).isDirectory())return[];let entries;try{entries=fs137.readdirSync(evidenceDir)}catch{return[]}for(let entry of entries){let entryPath=path217.join(evidenceDir,entry);try{if(!fs137.statSync(entryPath).isDirectory())continue}catch{continue}if(!PHASE_TASK_ID_REGEX.test(entry))continue;if(entry.split(".")[0]!==String(phase))continue;let evidenceFilePath=path217.join(entryPath,"evidence.json");try{let resolvedPath=path217.resolve(evidenceFilePath),evidenceDirResolved=path217.resolve(evidenceDir);if(!resolvedPath.startsWith(evidenceDirResolved+path217.sep))continue;let stat14=fs137.lstatSync(evidenceFilePath);if(!stat14.isFile())continue;if(stat14.size>MAX_FILE_SIZE_BYTES8)continue}catch{continue}let content;try{content=fs137.readFileSync(evidenceFilePath,"utf-8")}catch{continue}let parsed;try{parsed=JSON.parse(content)}catch{continue}if(parsed&&typeof parsed==="object"){let obj=parsed;if(Array.isArray(obj.entries)){for(let entryItem of obj.entries)if(entryItem&&typeof entryItem==="object"&&entryItem.type==="diff"){let diffEntry=entryItem;if(Array.isArray(diffEntry.files_changed)){for(let file3 of diffEntry.files_changed)if(typeof file3==="string")touchedFiles.add(path217.resolve(cwd,file3))}}}}}return Array.from(touchedFiles)}function searchFileForKeywords(filePath,keywords,cwd){try{let resolvedPath=path217.resolve(filePath),cwdResolved=path217.resolve(cwd);if(!resolvedPath.startsWith(cwdResolved))return!1;let content=fs137.readFileSync(resolvedPath,"utf-8");for(let keyword of keywords)if(new RegExp(`\\b${keyword}\\b`,"i").test(content))return!0;return!1}catch{return!1}}function analyzeRequirementCoverage(requirement,touchedFiles,cwd){let keywords=[],stopWords=new Set(["the","a","an","and","or","but","in","on","at","to","for","of","with","by","from","as","is","was","are","be","been","being","have","has","had","do","does","did","will","would","could","should","may","might","must","shall","can","need","that","this","these","those","it","its","they","them"]),wordRegex=/\b[a-zA-Z]{4,}\b/g,words=requirement.text.match(wordRegex)||[];for(let word of words){let lower=word.toLowerCase();if(!stopWords.has(lower))keywords.push(word)}let foundCount=0,searchedFiles=[];for(let file3 of touchedFiles){if(!file3.match(/\.(ts|js|tsx|jsx|py|go|rs|java|c|cpp|h|cs|rb|php)$/i))continue;if(searchedFiles.push(file3),searchFileForKeywords(file3,keywords,cwd))foundCount++}let status;if(foundCount>=1)status="covered";else status="missing";if(searchedFiles.length===0)status="missing";return{id:requirement.id,obligation:requirement.obligation,text:requirement.text,status,filesSearched:searchedFiles}}var req_coverage=createSwarmTool({description:"Analyze requirement coverage for FR requirements against touched files. Reads .swarm/spec.md for FR-### requirements and checks coverage against files touched during a phase via evidence files. Produces coverage report.",args:{phase:exports_external.number().int().min(1).describe("The phase number to analyze coverage for"),directory:exports_external.string().optional().describe("Working directory (defaults to plugin context directory)")},async execute(args2,directory){let phase,inputDirectory;try{if(args2&&typeof args2==="object"){let obj=args2;phase=typeof obj.phase==="number"?obj.phase:typeof obj.phase==="string"?Number(obj.phase):NaN,inputDirectory=typeof obj.directory==="string"?obj.directory:void 0}else phase=NaN}catch{phase=NaN}if(Number.isNaN(phase)||phase<1||!Number.isFinite(phase))return JSON.stringify({success:!1,phase:0,totalRequirements:0,coveredCount:0,missingCount:0,requirements:[],error:"Invalid phase number"},null,2);let cwd=inputDirectory||directory,spec=readEffectiveSpecSync(cwd);if(!spec)return JSON.stringify({success:!1,phase,totalRequirements:0,coveredCount:0,missingCount:0,requirements:[],error:"Failed to read effective spec: .swarm/spec.md is missing and no OpenSpec-compatible projection is available"},null,2);let specContent=spec.content,requirements=extractRequirements(specContent);if(requirements.length===0)return JSON.stringify({success:!0,phase,totalRequirements:0,coveredCount:0,missingCount:0,requirements:[],message:"No FR requirements found in spec.md"},null,2);let evidenceDir=path217.join(cwd,EVIDENCE_DIR4),touchedFiles=readTouchedFiles(evidenceDir,phase,cwd),analyzedRequirements=[],coveredCount=0,missingCount=0;for(let req of requirements){let analysis=analyzeRequirementCoverage(req,touchedFiles,cwd);switch(analyzedRequirements.push(analysis),analysis.status){case"covered":coveredCount++;break;case"missing":missingCount++;break}}let result={success:!0,phase,totalRequirements:requirements.length,coveredCount,missingCount,requirements:analyzedRequirements},reportFilename=`req-coverage-phase-${phase}.json`,reportPath=path217.join(evidenceDir,reportFilename);try{if(!fs137.existsSync(evidenceDir))fs137.mkdirSync(evidenceDir,{recursive:!0});fs137.writeFileSync(reportPath,JSON.stringify(result,null,2),"utf-8")}catch(writeError){log(`Failed to write coverage report: ${writeError instanceof Error?writeError.message:String(writeError)}`)}return JSON.stringify(result,null,2)}});init_zod();init_create_tool();var RetrieveLaneOutputArgsSchema=exports_external.object({ref:exports_external.string().min(1).describe("Opaque lane output ref returned as output_ref by dispatch tools."),offset:exports_external.number().int().min(0).default(0).describe("Line offset to start from."),limit:exports_external.number().int().min(1).max(500).default(100).describe("Number of lines to return, max 500.")}),retrieve_lane_output=createSwarmTool({description:"Retrieve paged full output for a dispatch_lanes or collect_lane_results lane by output_ref. Use when a lane preview is truncated, degraded, or needs candidate routing from full text.",args:{ref:RetrieveLaneOutputArgsSchema.shape.ref,offset:RetrieveLaneOutputArgsSchema.shape.offset,limit:RetrieveLaneOutputArgsSchema.shape.limit},async execute(args2,directory){let parsed=RetrieveLaneOutputArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,failure_class:"invalid_args",message:"Invalid retrieve_lane_output arguments",errors:parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`)},null,2);let loaded;try{loaded=readLaneOutput(directory,parsed.data.ref)}catch{loaded=null}if(!loaded)return JSON.stringify({success:!1,failure_class:"not_found",message:`No lane output artifact found for ${parsed.data.ref}`},null,2);let page=paginateLaneOutput(loaded.artifact.text,parsed.data.offset,Math.min(parsed.data.limit,500));if(page.exhausted)return`--- Lane output ${loaded.artifact.ref} offset beyond range ---
|
|
6003
6003
|
Lane: ${loaded.artifact.laneId} (${loaded.artifact.agent})
|
|
6004
6004
|
Digest: ${loaded.artifact.digest}
|
|
6005
6005
|
Content has ${page.totalLines} line${page.totalLines===1?"":"s"}.`;let response=`${`--- Lane output ${loaded.artifact.ref} lines ${page.startLine+1}-${page.endLine} of ${page.totalLines} ---
|
|
@@ -6033,7 +6033,7 @@ ${task.acceptance??""}`;if(idPattern.test(taskText))mappedTaskIds.push(task.id)}
|
|
|
6033
6033
|
`);for(let line of lines){let trimmed=line.trim();if(!trimmed||trimmed.startsWith("#")||trimmed.startsWith("metadata:"))continue;let match=trimmed.match(depRegex);if(match){let groupId=match[1],artifactId=match[2],version5=match[3];if(version5&&version5!=="unspecified")components.push({name:artifactId,version:version5,type:"library",purl:generatePurl("maven",artifactId,version5,groupId)})}}return components}var javaDetectors=[{name:"Java pom.xml",patterns:["pom.xml"],detect:(_filePath,content)=>{return parsePomXml(content)}},{name:"Java gradle.lockfile",patterns:["gradle.lockfile"],detect:(_filePath,content)=>{return parseGradleLockfile(content)}}];function parsePackageJson(content){let components=[];try{let pkg=JSON.parse(content),deps={...pkg.dependencies,...pkg.devDependencies};for(let[name,version5]of Object.entries(deps)){let cleanVersion=String(version5).replace(/^[\^~>=<]+/,"");components.push({name,version:cleanVersion||"unknown",type:"library",purl:generatePurl("npm",name,cleanVersion||"unknown")})}}catch{}return components}function parsePackageLock(content){let components=[];try{let lock=JSON.parse(content),packages=lock.packages||lock.dependencies||{};for(let[pkgPath,pkgData]of Object.entries(packages)){if(pkgPath==="")continue;let pkg=pkgData,version5=pkg.version||"",name=pkg.name||pkgPath.replace(/^node_modules\//,"").replace(/@.*$/,"");if(name&&version5)components.push({name,version:version5,type:"library",purl:generatePurl("npm",name,version5),license:pkg.license})}}catch{}return components}function parseYarnLock(content){let components=[],blocks=content.split(/^(?=@?[\w-]+@)/m);for(let block of blocks){let pkgMatch=block.match(/^(@?[\w-]+)@(\d+\.\d+\.\d+(?:-[\w.]+)?)/m);if(!pkgMatch)continue;let name=pkgMatch[1],version5=pkgMatch[2];if(name&&version5)components.push({name,version:version5,type:"library",purl:generatePurl("npm",name,version5)})}return components}function parsePnpmLockYaml(content){let components=[];try{let lines=content.split(`
|
|
6034
6034
|
`);for(let line of lines){let packageMatch=line.match(/^\s*\/(@?[\w-]+)@([\d.]+):?/);if(packageMatch)components.push({name:packageMatch[1],version:packageMatch[2],type:"library",purl:generatePurl("npm",packageMatch[1],packageMatch[2])})}}catch{}return components}var nodejsDetectors=[{name:"Node.js package-lock.json",patterns:["package-lock.json"],detect:(_filePath,content)=>{return parsePackageLock(content)}},{name:"Node.js yarn.lock",patterns:["yarn.lock"],detect:(_filePath,content)=>{return parseYarnLock(content)}},{name:"Node.js pnpm-lock.yaml",patterns:["pnpm-lock.yaml"],detect:(_filePath,content)=>{return parsePnpmLockYaml(content)}},{name:"Node.js package.json",patterns:["package.json"],detect:(_filePath,content)=>{return parsePackageJson(content)}}];function parseRequirementsTxt(content){let components=[],lines=content.split(`
|
|
6035
6035
|
`);for(let line of lines){let trimmed=line.trim();if(!trimmed||trimmed.startsWith("#"))continue;if(trimmed.startsWith("-"))continue;let match=trimmed.match(/^([a-zA-Z0-9_-]+)(?:[=<>~!]+)?([\d.]+)?/);if(match){let name=match[1],version5=match[2]||"unknown";if(name)components.push({name,version:version5,type:"library",purl:generatePurl("pypi",name,version5)})}}return components}function parsePoetryLock(content){let components=[],packageBlocks=content.split(/\[\[package\]\]/);for(let block of packageBlocks){if(block.trim()==="")continue;let nameMatch=block.match(/name\s*=\s*"([^"]+)"/),versionMatch=block.match(/version\s*=\s*"([^"]+)"/);if(nameMatch&&versionMatch){let name=nameMatch[1],version5=versionMatch[1],licenseMatch=block.match(/license\s*=\s*"([^"]+)"/);components.push({name,version:version5,type:"library",purl:generatePurl("pypi",name,version5),license:licenseMatch?.[1]})}}return components}function parsePipfileLock(content){let components=[];try{let lock=JSON.parse(content),sections=[lock.default,lock.dev].filter(Boolean);for(let section of sections){if(!section)continue;for(let[name,pkgData]of Object.entries(section)){let version5=pkgData.version||"unknown";if(version5=version5.replace(/^[=<>~!]+/,""),version5&&version5!=="*")components.push({name,version:version5,type:"library",purl:generatePurl("pypi",name,version5)})}}}catch{}return components}var pythonDetectors=[{name:"Python poetry.lock",patterns:["poetry.lock"],detect:(_filePath,content)=>{return parsePoetryLock(content)}},{name:"Python Pipfile.lock",patterns:["Pipfile.lock"],detect:(_filePath,content)=>{return parsePipfileLock(content)}},{name:"Python requirements.txt",patterns:["requirements.txt"],detect:(_filePath,content)=>{return parseRequirementsTxt(content)}}];function parseCargoToml(content){let components=[],lines=content.split(`
|
|
6036
|
-
`),inDependencies=!1,inDevDependencies=!1;for(let line of lines){let trimmed=line.trim();if(trimmed==="[dependencies]"||trimmed.startsWith("[dependencies]")){inDependencies=!0,inDevDependencies=!1;continue}if(trimmed==="[dev-dependencies]"||trimmed.startsWith("[dev-dependencies]")){inDependencies=!1,inDevDependencies=!0;continue}if(trimmed.startsWith("[")&&trimmed.endsWith("]")){inDependencies=!1,inDevDependencies=!1;continue}if(!inDependencies&&!inDevDependencies)continue;if(!trimmed||trimmed.startsWith("#"))continue;let match=trimmed.match(/^([a-zA-Z0-9_-]+)\s*=/);if(match){let name=match[1],version5="unknown",simpleMatch=trimmed.match(/"([\d.]+)"/);if(simpleMatch)version5=simpleMatch[1];else{let versionFieldMatch=trimmed.match(/version\s*=\s*"([\d.]+)"/);if(versionFieldMatch)version5=versionFieldMatch[1]}if(name&&version5!=="unknown")components.push({name,version:version5,type:"library",purl:generatePurl("cargo",name,version5)})}}return components}function parseCargoLock(content){let components=[],packageBlocks=content.split(/\[\[package\]\]/);for(let block of packageBlocks){if(block.trim()==="")continue;let nameMatch=block.match(/name\s*=\s*"([^"]+)"/),versionMatch=block.match(/version\s*=\s*"([^"]+)"/);if(nameMatch&&versionMatch){let name=nameMatch[1],version5=versionMatch[1];components.push({name,version:version5,type:"library",purl:generatePurl("cargo",name,version5)})}}return components}var rustDetectors=[{name:"Rust Cargo.lock",patterns:["Cargo.lock"],detect:(_filePath,content)=>{return parseCargoLock(content)}},{name:"Rust Cargo.toml",patterns:["Cargo.toml"],detect:(_filePath,content)=>{return parseCargoToml(content)}}];function parsePackageResolved(content){let components=[];try{let pins=JSON.parse(content).pins||[];for(let pin of pins){let identity=pin.identity||pin.package||"",state=pin.state||{},version5=state.version||state.revision||"",org="",orgMatch=(pin.location||"").match(/github\.com\/([^/]+)\//);if(orgMatch)org=orgMatch[1];if(identity&&version5)components.push({name:identity,version:version5,type:"library",purl:generatePurl("swift",identity,version5,org||void 0)})}}catch{}return components}var swiftDetectors=[{name:"Swift Package.resolved",patterns:["Package.resolved"],detect:(_filePath,content)=>{return parsePackageResolved(content)}}];function generatePurl(ecosystem,name,version5,namespace){let encodedName=encodeURIComponent(name),encodedVersion=encodeURIComponent(version5);switch(ecosystem){case"npm":return`pkg:npm/${encodedName}@${encodedVersion}`;case"pypi":return`pkg:pypi/${encodedName}@${encodedVersion}`;case"cargo":return`pkg:cargo/${encodedName}@${encodedVersion}`;case"golang":if(namespace)return`pkg:golang/${namespace}/${encodedName}@${encodedVersion}`;return`pkg:golang/${encodedName}@${encodedVersion}`;case"maven":return`pkg:maven/${encodeURIComponent(namespace||"unknown")}/${encodedName}@${encodedVersion}`;case"nuget":return`pkg:nuget/${encodedName}@${encodedVersion}`;case"swift":if(namespace)return`pkg:swift/${encodeURIComponent(namespace)}/${encodedName}@${encodedVersion}`;return`pkg:swift/${encodedName}@${encodedVersion}`;case"pub":return`pkg:pub/${encodedName}@${encodedVersion}`;default:return`pkg:unknown/${encodedName}@${encodedVersion}`}}var allDetectors=[...nodejsDetectors,...pythonDetectors,...rustDetectors,...goDetectors,...javaDetectors,...dotnetDetectors,...swiftDetectors,...dartDetectors];function findDetectorsForFile(filePath){let fileName=filePath.split(/[/\\]/).pop()||"";return allDetectors.filter((detector)=>detector.patterns.some((pattern)=>simpleGlobToRegex(pattern).test(fileName)))}function detectComponents(filePath,content){let detectors=findDetectorsForFile(filePath);for(let detector of detectors)try{let components=detector.detect(filePath,content);if(components.length>0)return components}catch(error93){console.warn(`[sbom] Detector failed for ${filePath}:`,error93 instanceof Error?error93.message:String(error93))}return[]}var DEFAULT_TOOL_VENDOR="opencode-swarm",DEFAULT_TOOL_NAME="sbom_generate",DEFAULT_TOOL_VERSION="6.9.0";function toCycloneDXComponent(component){let cyclonedxComponent={type:component.type,name:component.name,version:component.version};if(component.purl)cyclonedxComponent.purl=component.purl;if(component.license){let isSpdxId=/^[A-Za-z][A-Za-z0-9.*+-]*$/.test(component.license);cyclonedxComponent.licenses=[{license:isSpdxId?{id:component.license}:{name:component.license}}]}return cyclonedxComponent}function generateCycloneDX(components,options){let toolName=options?.toolName??DEFAULT_TOOL_NAME,toolVersion=options?.toolVersion??DEFAULT_TOOL_VERSION,bomVersion=options?.bomVersion??1,timestamp=new Date().toISOString(),cyclonedxComponents=components.map(toCycloneDXComponent);return{bomFormat:"CycloneDX",specVersion:"1.5",version:bomVersion,metadata:{timestamp,tools:[{vendor:DEFAULT_TOOL_VENDOR,name:toolName,version:toolVersion}]},components:cyclonedxComponents}}function serializeCycloneDX(bom){return JSON.stringify(bom,null,2)}init_utils();init_create_tool();var DEFAULT_OUTPUT_DIR=".swarm/evidence/sbom";function findManifestFiles(rootDir){let manifestFiles=[],patterns=[...new Set(allDetectors.flatMap((d)=>d.patterns))];function searchDir(dir){try{let entries=fs139.readdirSync(dir,{withFileTypes:!0});for(let entry of entries){let fullPath=path219.join(dir,entry.name);if(entry.name.startsWith(".")||entry.name==="node_modules"||entry.name==="dist"||entry.name==="build"||entry.name==="target")continue;if(entry.isDirectory())searchDir(fullPath);else if(entry.isFile()){for(let pattern of patterns)if(simpleGlobToRegex(pattern).test(entry.name)){manifestFiles.push(path219.relative(rootDir,fullPath));break}}}}catch{}}return searchDir(rootDir),manifestFiles}function findManifestFilesInDirs(directories,workingDir){let found=[],patterns=[...new Set(allDetectors.flatMap((d)=>d.patterns))];for(let dir of directories)try{let entries=fs139.readdirSync(dir,{withFileTypes:!0});for(let entry of entries){let fullPath=path219.join(dir,entry.name);if(entry.isFile()){for(let pattern of patterns)if(simpleGlobToRegex(pattern).test(entry.name)){found.push(path219.relative(workingDir,fullPath));break}}}}catch{}return found}function getDirectoriesFromChangedFiles(changedFiles,workingDir){let dirs=new Set;for(let file3 of changedFiles){let currentDir=path219.dirname(file3);while(!0)if(currentDir&¤tDir!=="."&¤tDir!==path219.sep){dirs.add(path219.join(workingDir,currentDir));let parent=path219.dirname(currentDir);if(parent===currentDir)break;currentDir=parent}else{dirs.add(workingDir);break}}return[...dirs]}function ensureOutputDir(outputDir){try{fs139.mkdirSync(outputDir,{recursive:!0})}catch(error93){if(!error93||error93.code!=="EEXIST")throw error93}}function generateSbomFilename(){let now=new Date,year=now.getFullYear(),month=String(now.getMonth()+1).padStart(2,"0"),day=String(now.getDate()).padStart(2,"0"),hours=String(now.getHours()).padStart(2,"0"),minutes=String(now.getMinutes()).padStart(2,"0"),seconds=String(now.getSeconds()).padStart(2,"0");return`sbom-${year}${month}${day}-${hours}${minutes}${seconds}.json`}function validateArgs4(args2){if(typeof args2!=="object"||args2===null)return!1;let obj=args2;if(typeof obj.scope!=="string"||!["changed","all"].includes(obj.scope))return!1;if(obj.scope==="changed"){if(!Array.isArray(obj.changed_files)||obj.changed_files.length===0)return!1}if(obj.output_dir!==void 0&&typeof obj.output_dir!=="string")return!1;if(obj.changed_files!==void 0){if(!Array.isArray(obj.changed_files))return!1;for(let f of obj.changed_files)if(typeof f!=="string")return!1}return!0}var sbom_generate=createSwarmTool({description:"Generate Software Bill of Materials (SBOM) by scanning project for dependency manifests. Uses CycloneDX format. Supports scanning entire project or only changed files.",args:{scope:exports_external.enum(["changed","all"]).describe('Scan scope: "changed" for modified files only, "all" for entire project'),changed_files:exports_external.array(exports_external.string()).optional().describe('List of changed files (required if scope="changed")'),output_dir:exports_external.string().optional().describe("Output directory for SBOM (default: .swarm/evidence/sbom/)")},async execute(args2,directory){if(!validateArgs4(args2))return JSON.stringify({...{verdict:"skip",files:[],components_count:0,output_path:""},error:'Invalid arguments: scope is required ("changed" or "all"), and changed_files is required when scope="changed"'},null,2);let obj=args2,scope=obj.scope,changedFiles=obj.changed_files,relativeOutputDir=obj.output_dir||DEFAULT_OUTPUT_DIR,workingDir=directory,outputDir=path219.isAbsolute(relativeOutputDir)?relativeOutputDir:path219.join(workingDir,relativeOutputDir),manifestFiles=[];if(scope==="all")manifestFiles=findManifestFiles(workingDir);else if(scope==="changed"&&changedFiles&&changedFiles.length>0){let changedDirs=getDirectoriesFromChangedFiles(changedFiles,workingDir);if(changedDirs.length>0)manifestFiles=findManifestFilesInDirs(changedDirs,workingDir)}if(manifestFiles.length===0)return JSON.stringify({verdict:"skip",files:[],components_count:0,output_path:""},null,2);let allComponents=[],processedFiles=[];for(let manifestFile of manifestFiles)try{let fullPath=path219.isAbsolute(manifestFile)?manifestFile:path219.join(workingDir,manifestFile);if(!fs139.existsSync(fullPath))continue;let content=fs139.readFileSync(fullPath,"utf-8"),components=detectComponents(manifestFile,content);if(processedFiles.push(manifestFile),components.length>0)allComponents.push(...components)}catch{}if(processedFiles.length===0&&manifestFiles.length>0);ensureOutputDir(outputDir);let bom=generateCycloneDX(allComponents),bomJson=serializeCycloneDX(bom),filename=generateSbomFilename(),outputPath=path219.join(outputDir,filename);fs139.writeFileSync(outputPath,bomJson,"utf-8");let verdict=processedFiles.length>0?"pass":"pass";try{let timestamp=new Date().toISOString();await saveEvidence(workingDir,"sbom_generate",{task_id:"sbom_generate",type:"sbom",timestamp,agent:"sbom_generate",verdict,summary:`Generated SBOM with ${allComponents.length} component(s) from ${processedFiles.length} manifest file(s)`,components:allComponents.map((c)=>({name:c.name,version:c.version,type:c.type,purl:c.purl,license:c.license})),metadata:{timestamp,tool:"sbom_generate",tool_version:"6.9.0"},files:processedFiles,components_count:allComponents.length,output_path:outputPath})}catch(error93){console.warn(`Warning: Failed to save SBOM evidence: ${error93 instanceof Error?error93.message:String(error93)}`)}let result={verdict,files:processedFiles,components_count:allComponents.length,output_path:outputPath};return JSON.stringify(result,null,2)}});init_zod();init_create_tool();import*as fs140 from"node:fs";import*as path220 from"node:path";var SPEC_CANDIDATES=["openapi.json","openapi.yaml","openapi.yml","swagger.json","swagger.yaml","swagger.yml","api/openapi.json","api/openapi.yaml","docs/openapi.json","docs/openapi.yaml","spec/openapi.json","spec/openapi.yaml"],SKIP_DIRS=["node_modules","dist","build",".git",".swarm","coverage","__tests__"],SKIP_EXTENSIONS=[".test.",".spec."],MAX_SPEC_SIZE=10485760,ALLOWED_EXTENSIONS=[".json",".yaml",".yml"];function normalizeApiPath(p){return p.replace(/\/$/,"").replace(/\{[^}]+\}/g,":param").replace(/:[a-zA-Z_][a-zA-Z0-9_]*/g,":param")}function discoverSpecFile(cwd,specFileArg){if(specFileArg){let resolvedPath=path220.resolve(cwd,specFileArg),normalizedCwd=cwd.endsWith(path220.sep)?cwd:cwd+path220.sep;if(!resolvedPath.startsWith(normalizedCwd)&&resolvedPath!==cwd)throw Error("Invalid spec_file: path traversal detected");let ext=path220.extname(resolvedPath).toLowerCase();if(!ALLOWED_EXTENSIONS.includes(ext))throw Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);if(fs140.statSync(resolvedPath).size>MAX_SPEC_SIZE)throw Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE/1024/1024}MB limit`);if(!fs140.existsSync(resolvedPath))throw Error(`Spec file not found: ${resolvedPath}`);return resolvedPath}for(let candidate of SPEC_CANDIDATES){let candidatePath=path220.resolve(cwd,candidate);if(fs140.existsSync(candidatePath)){if(fs140.statSync(candidatePath).size<=MAX_SPEC_SIZE)return candidatePath}}return null}function parseSpec(specFile){let content=fs140.readFileSync(specFile,"utf-8");if(path220.extname(specFile).toLowerCase()===".json")return parseJsonSpec(content);return parseYamlSpec(content)}function parseJsonSpec(content){let spec;try{spec=JSON.parse(content)}catch{return[]}let paths=[];if(!spec.paths)return paths;for(let[pathKey,pathValue]of Object.entries(spec.paths)){let methods=[];if(typeof pathValue==="object"&&pathValue!==null){for(let method of["get","post","put","patch","delete","options","head"])if(method in pathValue)methods.push(method)}if(methods.length>0)paths.push({path:pathKey,methods})}return paths}function parseYamlSpec(content){let paths=[];if(!content.match(/^paths:\s*$/m))return paths;let pathRegex=/^\s{2}(\/[^\s:]+):/gm;for(let match=pathRegex.exec(content);match!==null;match=pathRegex.exec(content)){let pathKey=match[1],methodRegex=/^\s{4}(get|post|put|patch|delete|options|head):/gm,methods=[],pathStart=match.index,nextPathMatch=content.substring(pathStart+1).match(/^\s{2}\//m),pathEnd=nextPathMatch&&nextPathMatch.index!==void 0?pathStart+1+nextPathMatch.index:content.length,pathSection=content.substring(pathStart,pathEnd),methodMatch=methodRegex.exec(pathSection);while(methodMatch!==null)methods.push(methodMatch[1]),methodMatch=methodRegex.exec(pathSection);if(methods.length>0)paths.push({path:pathKey,methods})}return paths}function extractRoutes2(cwd){let routes=[];function walkDir2(dir){let entries;try{entries=fs140.readdirSync(dir,{withFileTypes:!0})}catch{return}for(let entry of entries){let fullPath=path220.join(dir,entry.name);if(entry.isSymbolicLink())continue;if(entry.isDirectory()){if(SKIP_DIRS.includes(entry.name))continue;walkDir2(fullPath)}else if(entry.isFile()){let ext=path220.extname(entry.name).toLowerCase(),baseName=entry.name.toLowerCase();if(![".ts",".js",".mjs"].includes(ext))continue;if(SKIP_EXTENSIONS.some((skip)=>baseName.includes(skip)))continue;let fileRoutes=extractRoutesFromFile(fullPath);routes.push(...fileRoutes)}}}return walkDir2(cwd),routes}function extractRoutesFromFile(filePath){let routes=[],lines=fs140.readFileSync(filePath,"utf-8").split(/\r?\n/),expressRegex=/(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g,flaskRegex=/@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;for(let lineNum=0;lineNum<lines.length;lineNum++){let line=lines[lineNum],match=expressRegex.exec(line);expressRegex.lastIndex=0,flaskRegex.lastIndex=0;while(match!==null){let method=match[1].toLowerCase(),routePath=match[2];routes.push({path:routePath,method,file:filePath,line:lineNum+1}),match=expressRegex.exec(line)}match=flaskRegex.exec(line);while(match!==null){let routePath=match[1];routes.push({path:routePath,method:"get",file:filePath,line:lineNum+1}),match=flaskRegex.exec(line)}}return routes}function findDrift(specPaths,codeRoutes){let specPathMap=new Map;for(let sp of specPaths){let normalized=normalizeApiPath(sp.path);if(!specPathMap.has(normalized))specPathMap.set(normalized,[]);specPathMap.get(normalized).push(...sp.methods)}let codeRouteMap=new Map;for(let cr of codeRoutes){let normalized=normalizeApiPath(cr.path);if(!codeRouteMap.has(normalized))codeRouteMap.set(normalized,[]);codeRouteMap.get(normalized).push(cr)}let undocumented=[];for(let[normalized,routes]of codeRouteMap)if(!specPathMap.has(normalized))for(let route of routes)undocumented.push({path:route.path,method:route.method,file:route.file,line:route.line});let phantom=[];for(let[normalized,methods]of specPathMap)if(!codeRouteMap.has(normalized))phantom.push({path:specPaths.find((sp)=>normalizeApiPath(sp.path)===normalized).path,methods});return{undocumented,phantom}}var schema_drift=createSwarmTool({description:"Compare OpenAPI spec against actual route implementations to find drift. Detects undocumented routes in code and phantom routes in spec.",args:{spec_file:exports_external.string().optional().describe("Path to OpenAPI spec file. Auto-detected if omitted. Checks: openapi.json/yaml/yml, swagger.json/yaml/yml, api/openapi.json/yaml, docs/openapi.json/yaml, spec/openapi.json/yaml")},async execute(args2,directory){let cwd=directory;if(args2!==null&&typeof args2!=="object")return JSON.stringify({...{specFile:"",specPathCount:0,codeRouteCount:0,undocumented:[],phantom:[],undocumentedCount:0,phantomCount:0,consistent:!1},error:"Invalid arguments"},null,2);let argsObj=args2;try{let specFile=discoverSpecFile(cwd,argsObj.spec_file);if(!specFile)return JSON.stringify({...{specFile:"",specPathCount:0,codeRouteCount:0,undocumented:[],phantom:[],undocumentedCount:0,phantomCount:0,consistent:!1},error:"No OpenAPI spec file found. Provide spec_file or place spec in one of: openapi.json/yaml/yml, swagger.json/yaml/yml, api/openapi.json/yaml, docs/openapi.json/yaml, spec/openapi.json/yaml"},null,2);let specPaths=parseSpec(specFile),codeRoutes=extractRoutes2(cwd),{undocumented,phantom}=findDrift(specPaths,codeRoutes),result={specFile,specPathCount:specPaths.length,codeRouteCount:codeRoutes.length,undocumented,phantom,undocumentedCount:undocumented.length,phantomCount:phantom.length,consistent:undocumented.length===0&&phantom.length===0};return JSON.stringify(result,null,2)}catch(error93){let errorMessage3=error93 instanceof Error?error93.message:"Unknown error";return JSON.stringify({...{specFile:"",specPathCount:0,codeRouteCount:0,undocumented:[],phantom:[],undocumentedCount:0,phantomCount:0,consistent:!1},error:errorMessage3},null,2)}}});init_zod();init_external_tool_runner();init_path_security();init_create_tool();import*as fs141 from"node:fs";import{createRequire as createRequire6}from"node:module";import*as path221 from"node:path";var require2=createRequire6(import.meta.url),DEFAULT_MAX_RESULTS4=100,DEFAULT_MAX_LINES=200,REGEX_TIMEOUT_MS=5000,MAX_FILE_SIZE_BYTES9=1048576,HARD_CAP_RESULTS4=1e4,HARD_CAP_LINES=1e4,MAX_QUERY_LENGTH=20000,MAX_RG_STDOUT_BYTES=8388608,MAX_RG_STDERR_BYTES=65536,FALLBACK_MAX_FILES=20000,FALLBACK_MAX_DIRS=5000,FALLBACK_MAX_DEPTH=40,FALLBACK_MAX_TOTAL_BYTES=67108864,DEFAULT_SKIP_DIRS=new Set([".git",".swarm","node_modules","dist","build","out","coverage",".next",".turbo",".cache"]);function globMatch(pattern,filePath){let normalizedPattern=pattern.replace(/\\/g,"/"),normalizedPath=filePath.replace(/\\/g,"/"),regexPattern=normalizedPattern.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*\*/g,"{{DOUBLESTAR}}").replace(/\*/g,"[^/]*").replace(/\?/g,".").replace(/\{\{DOUBLESTAR\}\}/g,".*");try{return new RegExp(`^${regexPattern}$`).test(normalizedPath)}catch{return!1}}function matchesGlobs(filePath,globs){if(globs.length===0)return!0;return globs.some((glob)=>globMatch(glob,filePath))}var WINDOWS_RESERVED_NAMES5=/^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;function containsWindowsAttacks4(str){if(/:[^\\/]/.test(str))return!0;let parts=str.split(/[/\\]/);for(let part of parts)if(WINDOWS_RESERVED_NAMES5.test(part))return!0;return!1}function isPathInWorkspace3(filePath,workspace){try{let resolvedPath=path221.resolve(workspace,filePath),realWorkspace=fs141.realpathSync(workspace),realResolvedPath=fs141.realpathSync(resolvedPath),relativePath=path221.relative(realWorkspace,realResolvedPath);if(relativePath.startsWith("..")||path221.isAbsolute(relativePath))return!1;return!0}catch{return!1}}function validatePathForRead2(filePath,workspace){return isPathInWorkspace3(filePath,workspace)}function splitGlobPatterns2(value){return value?value.split(",").map((p)=>p.trim()).filter(Boolean):[]}function toWorkspaceRelativePath2(filePath,workspace){try{let resolved=path221.resolve(workspace,filePath),realWorkspace=fs141.realpathSync(workspace),realResolved=fs141.realpathSync(resolved),relative49=path221.relative(realWorkspace,realResolved);if(!relative49||relative49.startsWith("..")||path221.isAbsolute(relative49))return null;return relative49.split(path221.sep).join("/")}catch{return null}}function truncateLine(line,maxLines){let trimmed=line.trimEnd();if(trimmed.length>maxLines)return`${trimmed.substring(0,maxLines)}...`;return trimmed}function resolvePackagedRipgrep(){try{let mod=require2("@vscode/ripgrep");return typeof mod.rgPath==="string"&&mod.rgPath?mod.rgPath:null}catch{return null}}function resolveRipgrepBinary(){return _internals139.resolvePackagedRipgrep()??_internals139.resolveExecutableFromPath(["rg"])}async function ripgrepSearch(opts){let rgPath=_internals139.resolveRipgrepBinary();if(!rgPath)return{error:!0,type:"rg-not-found",message:"ripgrep (rg) not found; using fallback search was not possible"};let args2=["--json","--no-config","-n"];for(let pattern of splitGlobPatterns2(opts.include))args2.push("--glob",pattern);for(let pattern of splitGlobPatterns2(opts.exclude))args2.push("--glob",`!${pattern}`);if(opts.mode!=="regex")args2.push("--fixed-strings");args2.push("--",opts.query,".");let run=await _internals139.runExternalTool({executable:rgPath,args:args2,cwd:opts.workspace,timeoutMs:REGEX_TIMEOUT_MS,maxStdoutBytes:MAX_RG_STDOUT_BYTES,maxStderrBytes:MAX_RG_STDERR_BYTES});try{if(run.status==="timeout")return{error:!0,type:"regex-timeout",message:`Search timed out after ${REGEX_TIMEOUT_MS}ms`};if(run.status==="spawn-error")return{error:!0,type:"unknown",message:run.message??"ripgrep failed to start"};if(run.exitCode!==0&&run.stderr){if(run.stderr.includes("Invalid regex")||run.stderr.includes("regex parse error")||run.stderr.includes("SyntaxError"))return{error:!0,type:"invalid-query",message:`Invalid query: ${run.stderr.split(`
|
|
6036
|
+
`),inDependencies=!1,inDevDependencies=!1;for(let line of lines){let trimmed=line.trim();if(trimmed==="[dependencies]"||trimmed.startsWith("[dependencies]")){inDependencies=!0,inDevDependencies=!1;continue}if(trimmed==="[dev-dependencies]"||trimmed.startsWith("[dev-dependencies]")){inDependencies=!1,inDevDependencies=!0;continue}if(trimmed.startsWith("[")&&trimmed.endsWith("]")){inDependencies=!1,inDevDependencies=!1;continue}if(!inDependencies&&!inDevDependencies)continue;if(!trimmed||trimmed.startsWith("#"))continue;let match=trimmed.match(/^([a-zA-Z0-9_-]+)\s*=/);if(match){let name=match[1],version5="unknown",simpleMatch=trimmed.match(/"([\d.]+)"/);if(simpleMatch)version5=simpleMatch[1];else{let versionFieldMatch=trimmed.match(/version\s*=\s*"([\d.]+)"/);if(versionFieldMatch)version5=versionFieldMatch[1]}if(name&&version5!=="unknown")components.push({name,version:version5,type:"library",purl:generatePurl("cargo",name,version5)})}}return components}function parseCargoLock(content){let components=[],packageBlocks=content.split(/\[\[package\]\]/);for(let block of packageBlocks){if(block.trim()==="")continue;let nameMatch=block.match(/name\s*=\s*"([^"]+)"/),versionMatch=block.match(/version\s*=\s*"([^"]+)"/);if(nameMatch&&versionMatch){let name=nameMatch[1],version5=versionMatch[1];components.push({name,version:version5,type:"library",purl:generatePurl("cargo",name,version5)})}}return components}var rustDetectors=[{name:"Rust Cargo.lock",patterns:["Cargo.lock"],detect:(_filePath,content)=>{return parseCargoLock(content)}},{name:"Rust Cargo.toml",patterns:["Cargo.toml"],detect:(_filePath,content)=>{return parseCargoToml(content)}}];function parsePackageResolved(content){let components=[];try{let pins=JSON.parse(content).pins||[];for(let pin of pins){let identity=pin.identity||pin.package||"",state=pin.state||{},version5=state.version||state.revision||"",org="",orgMatch=(pin.location||"").match(/github\.com\/([^/]+)\//);if(orgMatch)org=orgMatch[1];if(identity&&version5)components.push({name:identity,version:version5,type:"library",purl:generatePurl("swift",identity,version5,org||void 0)})}}catch{}return components}var swiftDetectors=[{name:"Swift Package.resolved",patterns:["Package.resolved"],detect:(_filePath,content)=>{return parsePackageResolved(content)}}];function generatePurl(ecosystem,name,version5,namespace){let encodedName=encodeURIComponent(name),encodedVersion=encodeURIComponent(version5);switch(ecosystem){case"npm":return`pkg:npm/${encodedName}@${encodedVersion}`;case"pypi":return`pkg:pypi/${encodedName}@${encodedVersion}`;case"cargo":return`pkg:cargo/${encodedName}@${encodedVersion}`;case"golang":if(namespace)return`pkg:golang/${namespace}/${encodedName}@${encodedVersion}`;return`pkg:golang/${encodedName}@${encodedVersion}`;case"maven":return`pkg:maven/${encodeURIComponent(namespace||"unknown")}/${encodedName}@${encodedVersion}`;case"nuget":return`pkg:nuget/${encodedName}@${encodedVersion}`;case"swift":if(namespace)return`pkg:swift/${encodeURIComponent(namespace)}/${encodedName}@${encodedVersion}`;return`pkg:swift/${encodedName}@${encodedVersion}`;case"pub":return`pkg:pub/${encodedName}@${encodedVersion}`;default:return`pkg:unknown/${encodedName}@${encodedVersion}`}}var allDetectors=[...nodejsDetectors,...pythonDetectors,...rustDetectors,...goDetectors,...javaDetectors,...dotnetDetectors,...swiftDetectors,...dartDetectors];function findDetectorsForFile(filePath){let fileName=filePath.split(/[/\\]/).pop()||"";return allDetectors.filter((detector)=>detector.patterns.some((pattern)=>simpleGlobToRegex(pattern).test(fileName)))}function detectComponents(filePath,content){let detectors=findDetectorsForFile(filePath);for(let detector of detectors)try{let components=detector.detect(filePath,content);if(components.length>0)return components}catch(error93){console.warn(`[sbom] Detector failed for ${filePath}:`,error93 instanceof Error?error93.message:String(error93))}return[]}var DEFAULT_TOOL_VENDOR="opencode-swarm",DEFAULT_TOOL_NAME="sbom_generate",DEFAULT_TOOL_VERSION="6.9.0";function toCycloneDXComponent(component){let cyclonedxComponent={type:component.type,name:component.name,version:component.version};if(component.purl)cyclonedxComponent.purl=component.purl;if(component.license){let isSpdxId=/^[A-Za-z][A-Za-z0-9.*+-]*$/.test(component.license);cyclonedxComponent.licenses=[{license:isSpdxId?{id:component.license}:{name:component.license}}]}return cyclonedxComponent}function generateCycloneDX(components,options){let toolName=options?.toolName??DEFAULT_TOOL_NAME,toolVersion=options?.toolVersion??DEFAULT_TOOL_VERSION,bomVersion=options?.bomVersion??1,timestamp=new Date().toISOString(),cyclonedxComponents=components.map(toCycloneDXComponent);return{bomFormat:"CycloneDX",specVersion:"1.5",version:bomVersion,metadata:{timestamp,tools:[{vendor:DEFAULT_TOOL_VENDOR,name:toolName,version:toolVersion}]},components:cyclonedxComponents}}function serializeCycloneDX(bom){return JSON.stringify(bom,null,2)}init_utils();init_logger();init_create_tool();var DEFAULT_OUTPUT_DIR=".swarm/evidence/sbom";function findManifestFiles(rootDir){let manifestFiles=[],patterns=[...new Set(allDetectors.flatMap((d)=>d.patterns))];function searchDir(dir){try{let entries=fs139.readdirSync(dir,{withFileTypes:!0});for(let entry of entries){let fullPath=path219.join(dir,entry.name);if(entry.name.startsWith(".")||entry.name==="node_modules"||entry.name==="dist"||entry.name==="build"||entry.name==="target")continue;if(entry.isDirectory())searchDir(fullPath);else if(entry.isFile()){for(let pattern of patterns)if(simpleGlobToRegex(pattern).test(entry.name)){manifestFiles.push(path219.relative(rootDir,fullPath));break}}}}catch{}}return searchDir(rootDir),manifestFiles}function findManifestFilesInDirs(directories,workingDir){let found=[],patterns=[...new Set(allDetectors.flatMap((d)=>d.patterns))];for(let dir of directories)try{let entries=fs139.readdirSync(dir,{withFileTypes:!0});for(let entry of entries){let fullPath=path219.join(dir,entry.name);if(entry.isFile()){for(let pattern of patterns)if(simpleGlobToRegex(pattern).test(entry.name)){found.push(path219.relative(workingDir,fullPath));break}}}}catch{}return found}function getDirectoriesFromChangedFiles(changedFiles,workingDir){let dirs=new Set;for(let file3 of changedFiles){let currentDir=path219.dirname(file3);while(!0)if(currentDir&¤tDir!=="."&¤tDir!==path219.sep){dirs.add(path219.join(workingDir,currentDir));let parent=path219.dirname(currentDir);if(parent===currentDir)break;currentDir=parent}else{dirs.add(workingDir);break}}return[...dirs]}function ensureOutputDir(outputDir){try{fs139.mkdirSync(outputDir,{recursive:!0})}catch(error93){if(!error93||error93.code!=="EEXIST")throw error93}}function generateSbomFilename(){let now=new Date,year=now.getFullYear(),month=String(now.getMonth()+1).padStart(2,"0"),day=String(now.getDate()).padStart(2,"0"),hours=String(now.getHours()).padStart(2,"0"),minutes=String(now.getMinutes()).padStart(2,"0"),seconds=String(now.getSeconds()).padStart(2,"0");return`sbom-${year}${month}${day}-${hours}${minutes}${seconds}.json`}function validateArgs4(args2){if(typeof args2!=="object"||args2===null)return!1;let obj=args2;if(typeof obj.scope!=="string"||!["changed","all"].includes(obj.scope))return!1;if(obj.scope==="changed"){if(!Array.isArray(obj.changed_files)||obj.changed_files.length===0)return!1}if(obj.output_dir!==void 0&&typeof obj.output_dir!=="string")return!1;if(obj.changed_files!==void 0){if(!Array.isArray(obj.changed_files))return!1;for(let f of obj.changed_files)if(typeof f!=="string")return!1}return!0}var sbom_generate=createSwarmTool({description:"Generate Software Bill of Materials (SBOM) by scanning project for dependency manifests. Uses CycloneDX format. Supports scanning entire project or only changed files.",args:{scope:exports_external.enum(["changed","all"]).describe('Scan scope: "changed" for modified files only, "all" for entire project'),changed_files:exports_external.array(exports_external.string()).optional().describe('List of changed files (required if scope="changed")'),output_dir:exports_external.string().optional().describe("Output directory for SBOM (default: .swarm/evidence/sbom/)")},async execute(args2,directory){if(!validateArgs4(args2))return JSON.stringify({...{verdict:"skip",files:[],components_count:0,output_path:""},error:'Invalid arguments: scope is required ("changed" or "all"), and changed_files is required when scope="changed"'},null,2);let obj=args2,scope=obj.scope,changedFiles=obj.changed_files,relativeOutputDir=obj.output_dir||DEFAULT_OUTPUT_DIR,workingDir=directory,outputDir=path219.isAbsolute(relativeOutputDir)?relativeOutputDir:path219.join(workingDir,relativeOutputDir),manifestFiles=[];if(scope==="all")manifestFiles=findManifestFiles(workingDir);else if(scope==="changed"&&changedFiles&&changedFiles.length>0){let changedDirs=getDirectoriesFromChangedFiles(changedFiles,workingDir);if(changedDirs.length>0)manifestFiles=findManifestFilesInDirs(changedDirs,workingDir)}if(manifestFiles.length===0)return JSON.stringify({verdict:"skip",files:[],components_count:0,output_path:""},null,2);let allComponents=[],processedFiles=[];for(let manifestFile of manifestFiles)try{let fullPath=path219.isAbsolute(manifestFile)?manifestFile:path219.join(workingDir,manifestFile);if(!fs139.existsSync(fullPath))continue;let content=fs139.readFileSync(fullPath,"utf-8"),components=detectComponents(manifestFile,content);if(processedFiles.push(manifestFile),components.length>0)allComponents.push(...components)}catch{}if(processedFiles.length===0&&manifestFiles.length>0);ensureOutputDir(outputDir);let bom=generateCycloneDX(allComponents),bomJson=serializeCycloneDX(bom),filename=generateSbomFilename(),outputPath=path219.join(outputDir,filename);fs139.writeFileSync(outputPath,bomJson,"utf-8");let verdict=processedFiles.length>0?"pass":"pass";try{let timestamp=new Date().toISOString();await saveEvidence(workingDir,"sbom_generate",{task_id:"sbom_generate",type:"sbom",timestamp,agent:"sbom_generate",verdict,summary:`Generated SBOM with ${allComponents.length} component(s) from ${processedFiles.length} manifest file(s)`,components:allComponents.map((c)=>({name:c.name,version:c.version,type:c.type,purl:c.purl,license:c.license})),metadata:{timestamp,tool:"sbom_generate",tool_version:"6.9.0"},files:processedFiles,components_count:allComponents.length,output_path:outputPath})}catch(error93){log(`Warning: Failed to save SBOM evidence: ${error93 instanceof Error?error93.message:String(error93)}`)}let result={verdict,files:processedFiles,components_count:allComponents.length,output_path:outputPath};return JSON.stringify(result,null,2)}});init_zod();init_create_tool();import*as fs140 from"node:fs";import*as path220 from"node:path";var SPEC_CANDIDATES=["openapi.json","openapi.yaml","openapi.yml","swagger.json","swagger.yaml","swagger.yml","api/openapi.json","api/openapi.yaml","docs/openapi.json","docs/openapi.yaml","spec/openapi.json","spec/openapi.yaml"],SKIP_DIRS=["node_modules","dist","build",".git",".swarm","coverage","__tests__"],SKIP_EXTENSIONS=[".test.",".spec."],MAX_SPEC_SIZE=10485760,ALLOWED_EXTENSIONS=[".json",".yaml",".yml"];function normalizeApiPath(p){return p.replace(/\/$/,"").replace(/\{[^}]+\}/g,":param").replace(/:[a-zA-Z_][a-zA-Z0-9_]*/g,":param")}function discoverSpecFile(cwd,specFileArg){if(specFileArg){let resolvedPath=path220.resolve(cwd,specFileArg),normalizedCwd=cwd.endsWith(path220.sep)?cwd:cwd+path220.sep;if(!resolvedPath.startsWith(normalizedCwd)&&resolvedPath!==cwd)throw Error("Invalid spec_file: path traversal detected");let ext=path220.extname(resolvedPath).toLowerCase();if(!ALLOWED_EXTENSIONS.includes(ext))throw Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);if(fs140.statSync(resolvedPath).size>MAX_SPEC_SIZE)throw Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE/1024/1024}MB limit`);if(!fs140.existsSync(resolvedPath))throw Error(`Spec file not found: ${resolvedPath}`);return resolvedPath}for(let candidate of SPEC_CANDIDATES){let candidatePath=path220.resolve(cwd,candidate);if(fs140.existsSync(candidatePath)){if(fs140.statSync(candidatePath).size<=MAX_SPEC_SIZE)return candidatePath}}return null}function parseSpec(specFile){let content=fs140.readFileSync(specFile,"utf-8");if(path220.extname(specFile).toLowerCase()===".json")return parseJsonSpec(content);return parseYamlSpec(content)}function parseJsonSpec(content){let spec;try{spec=JSON.parse(content)}catch{return[]}let paths=[];if(!spec.paths)return paths;for(let[pathKey,pathValue]of Object.entries(spec.paths)){let methods=[];if(typeof pathValue==="object"&&pathValue!==null){for(let method of["get","post","put","patch","delete","options","head"])if(method in pathValue)methods.push(method)}if(methods.length>0)paths.push({path:pathKey,methods})}return paths}function parseYamlSpec(content){let paths=[];if(!content.match(/^paths:\s*$/m))return paths;let pathRegex=/^\s{2}(\/[^\s:]+):/gm;for(let match=pathRegex.exec(content);match!==null;match=pathRegex.exec(content)){let pathKey=match[1],methodRegex=/^\s{4}(get|post|put|patch|delete|options|head):/gm,methods=[],pathStart=match.index,nextPathMatch=content.substring(pathStart+1).match(/^\s{2}\//m),pathEnd=nextPathMatch&&nextPathMatch.index!==void 0?pathStart+1+nextPathMatch.index:content.length,pathSection=content.substring(pathStart,pathEnd),methodMatch=methodRegex.exec(pathSection);while(methodMatch!==null)methods.push(methodMatch[1]),methodMatch=methodRegex.exec(pathSection);if(methods.length>0)paths.push({path:pathKey,methods})}return paths}function extractRoutes2(cwd){let routes=[];function walkDir2(dir){let entries;try{entries=fs140.readdirSync(dir,{withFileTypes:!0})}catch{return}for(let entry of entries){let fullPath=path220.join(dir,entry.name);if(entry.isSymbolicLink())continue;if(entry.isDirectory()){if(SKIP_DIRS.includes(entry.name))continue;walkDir2(fullPath)}else if(entry.isFile()){let ext=path220.extname(entry.name).toLowerCase(),baseName=entry.name.toLowerCase();if(![".ts",".js",".mjs"].includes(ext))continue;if(SKIP_EXTENSIONS.some((skip)=>baseName.includes(skip)))continue;let fileRoutes=extractRoutesFromFile(fullPath);routes.push(...fileRoutes)}}}return walkDir2(cwd),routes}function extractRoutesFromFile(filePath){let routes=[],lines=fs140.readFileSync(filePath,"utf-8").split(/\r?\n/),expressRegex=/(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g,flaskRegex=/@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;for(let lineNum=0;lineNum<lines.length;lineNum++){let line=lines[lineNum],match=expressRegex.exec(line);expressRegex.lastIndex=0,flaskRegex.lastIndex=0;while(match!==null){let method=match[1].toLowerCase(),routePath=match[2];routes.push({path:routePath,method,file:filePath,line:lineNum+1}),match=expressRegex.exec(line)}match=flaskRegex.exec(line);while(match!==null){let routePath=match[1];routes.push({path:routePath,method:"get",file:filePath,line:lineNum+1}),match=flaskRegex.exec(line)}}return routes}function findDrift(specPaths,codeRoutes){let specPathMap=new Map;for(let sp of specPaths){let normalized=normalizeApiPath(sp.path);if(!specPathMap.has(normalized))specPathMap.set(normalized,[]);specPathMap.get(normalized).push(...sp.methods)}let codeRouteMap=new Map;for(let cr of codeRoutes){let normalized=normalizeApiPath(cr.path);if(!codeRouteMap.has(normalized))codeRouteMap.set(normalized,[]);codeRouteMap.get(normalized).push(cr)}let undocumented=[];for(let[normalized,routes]of codeRouteMap)if(!specPathMap.has(normalized))for(let route of routes)undocumented.push({path:route.path,method:route.method,file:route.file,line:route.line});let phantom=[];for(let[normalized,methods]of specPathMap)if(!codeRouteMap.has(normalized))phantom.push({path:specPaths.find((sp)=>normalizeApiPath(sp.path)===normalized).path,methods});return{undocumented,phantom}}var schema_drift=createSwarmTool({description:"Compare OpenAPI spec against actual route implementations to find drift. Detects undocumented routes in code and phantom routes in spec.",args:{spec_file:exports_external.string().optional().describe("Path to OpenAPI spec file. Auto-detected if omitted. Checks: openapi.json/yaml/yml, swagger.json/yaml/yml, api/openapi.json/yaml, docs/openapi.json/yaml, spec/openapi.json/yaml")},async execute(args2,directory){let cwd=directory;if(args2!==null&&typeof args2!=="object")return JSON.stringify({...{specFile:"",specPathCount:0,codeRouteCount:0,undocumented:[],phantom:[],undocumentedCount:0,phantomCount:0,consistent:!1},error:"Invalid arguments"},null,2);let argsObj=args2;try{let specFile=discoverSpecFile(cwd,argsObj.spec_file);if(!specFile)return JSON.stringify({...{specFile:"",specPathCount:0,codeRouteCount:0,undocumented:[],phantom:[],undocumentedCount:0,phantomCount:0,consistent:!1},error:"No OpenAPI spec file found. Provide spec_file or place spec in one of: openapi.json/yaml/yml, swagger.json/yaml/yml, api/openapi.json/yaml, docs/openapi.json/yaml, spec/openapi.json/yaml"},null,2);let specPaths=parseSpec(specFile),codeRoutes=extractRoutes2(cwd),{undocumented,phantom}=findDrift(specPaths,codeRoutes),result={specFile,specPathCount:specPaths.length,codeRouteCount:codeRoutes.length,undocumented,phantom,undocumentedCount:undocumented.length,phantomCount:phantom.length,consistent:undocumented.length===0&&phantom.length===0};return JSON.stringify(result,null,2)}catch(error93){let errorMessage3=error93 instanceof Error?error93.message:"Unknown error";return JSON.stringify({...{specFile:"",specPathCount:0,codeRouteCount:0,undocumented:[],phantom:[],undocumentedCount:0,phantomCount:0,consistent:!1},error:errorMessage3},null,2)}}});init_zod();init_external_tool_runner();init_path_security();init_create_tool();import*as fs141 from"node:fs";import{createRequire as createRequire6}from"node:module";import*as path221 from"node:path";var require2=createRequire6(import.meta.url),DEFAULT_MAX_RESULTS4=100,DEFAULT_MAX_LINES=200,REGEX_TIMEOUT_MS=5000,MAX_FILE_SIZE_BYTES9=1048576,HARD_CAP_RESULTS4=1e4,HARD_CAP_LINES=1e4,MAX_QUERY_LENGTH=20000,MAX_RG_STDOUT_BYTES=8388608,MAX_RG_STDERR_BYTES=65536,FALLBACK_MAX_FILES=20000,FALLBACK_MAX_DIRS=5000,FALLBACK_MAX_DEPTH=40,FALLBACK_MAX_TOTAL_BYTES=67108864,DEFAULT_SKIP_DIRS=new Set([".git",".swarm","node_modules","dist","build","out","coverage",".next",".turbo",".cache"]);function globMatch(pattern,filePath){let normalizedPattern=pattern.replace(/\\/g,"/"),normalizedPath=filePath.replace(/\\/g,"/"),regexPattern=normalizedPattern.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*\*/g,"{{DOUBLESTAR}}").replace(/\*/g,"[^/]*").replace(/\?/g,".").replace(/\{\{DOUBLESTAR\}\}/g,".*");try{return new RegExp(`^${regexPattern}$`).test(normalizedPath)}catch{return!1}}function matchesGlobs(filePath,globs){if(globs.length===0)return!0;return globs.some((glob)=>globMatch(glob,filePath))}var WINDOWS_RESERVED_NAMES5=/^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;function containsWindowsAttacks4(str){if(/:[^\\/]/.test(str))return!0;let parts=str.split(/[/\\]/);for(let part of parts)if(WINDOWS_RESERVED_NAMES5.test(part))return!0;return!1}function isPathInWorkspace3(filePath,workspace){try{let resolvedPath=path221.resolve(workspace,filePath),realWorkspace=fs141.realpathSync(workspace),realResolvedPath=fs141.realpathSync(resolvedPath),relativePath=path221.relative(realWorkspace,realResolvedPath);if(relativePath.startsWith("..")||path221.isAbsolute(relativePath))return!1;return!0}catch{return!1}}function validatePathForRead2(filePath,workspace){return isPathInWorkspace3(filePath,workspace)}function splitGlobPatterns2(value){return value?value.split(",").map((p)=>p.trim()).filter(Boolean):[]}function toWorkspaceRelativePath2(filePath,workspace){try{let resolved=path221.resolve(workspace,filePath),realWorkspace=fs141.realpathSync(workspace),realResolved=fs141.realpathSync(resolved),relative49=path221.relative(realWorkspace,realResolved);if(!relative49||relative49.startsWith("..")||path221.isAbsolute(relative49))return null;return relative49.split(path221.sep).join("/")}catch{return null}}function truncateLine(line,maxLines){let trimmed=line.trimEnd();if(trimmed.length>maxLines)return`${trimmed.substring(0,maxLines)}...`;return trimmed}function resolvePackagedRipgrep(){try{let mod=require2("@vscode/ripgrep");return typeof mod.rgPath==="string"&&mod.rgPath?mod.rgPath:null}catch{return null}}function resolveRipgrepBinary(){return _internals139.resolvePackagedRipgrep()??_internals139.resolveExecutableFromPath(["rg"])}async function ripgrepSearch(opts){let rgPath=_internals139.resolveRipgrepBinary();if(!rgPath)return{error:!0,type:"rg-not-found",message:"ripgrep (rg) not found; using fallback search was not possible"};let args2=["--json","--no-config","-n"];for(let pattern of splitGlobPatterns2(opts.include))args2.push("--glob",pattern);for(let pattern of splitGlobPatterns2(opts.exclude))args2.push("--glob",`!${pattern}`);if(opts.mode!=="regex")args2.push("--fixed-strings");args2.push("--",opts.query,".");let run=await _internals139.runExternalTool({executable:rgPath,args:args2,cwd:opts.workspace,timeoutMs:REGEX_TIMEOUT_MS,maxStdoutBytes:MAX_RG_STDOUT_BYTES,maxStderrBytes:MAX_RG_STDERR_BYTES});try{if(run.status==="timeout")return{error:!0,type:"regex-timeout",message:`Search timed out after ${REGEX_TIMEOUT_MS}ms`};if(run.status==="spawn-error")return{error:!0,type:"unknown",message:run.message??"ripgrep failed to start"};if(run.exitCode!==0&&run.stderr){if(run.stderr.includes("Invalid regex")||run.stderr.includes("regex parse error")||run.stderr.includes("SyntaxError"))return{error:!0,type:"invalid-query",message:`Invalid query: ${run.stderr.split(`
|
|
6037
6037
|
`)[0]}`}}let matches=[],total=0;for(let line of run.stdout.split(`
|
|
6038
6038
|
`)){if(!line.trim())continue;try{let entry=JSON.parse(line);if(entry.type==="match"){let rawPath=entry.data?.path?.text??entry.data?.path,relativePath=typeof rawPath==="string"?toWorkspaceRelativePath2(rawPath,opts.workspace):null;if(!relativePath)continue;if(total++,matches.length<opts.maxResults){let match={file:relativePath,lineNumber:entry.data.line_number,lineText:truncateLine(entry.data.lines.text,opts.maxLines)};matches.push(match)}}}catch{}}return{matches,truncated:total>opts.maxResults||run.stdoutTruncated||run.stderrTruncated,total,query:opts.query,mode:opts.mode,maxResults:opts.maxResults,engine:"ripgrep",outputTruncated:run.stdoutTruncated||run.stderrTruncated}}catch(err2){return{error:!0,type:"unknown",message:err2 instanceof Error?err2.message:String(err2)}}}function escapeRegex4(str){return str.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function collectFiles(dir,workspace,includeGlobs,excludeGlobs,state,depth=0){if(depth>FALLBACK_MAX_DEPTH||state.files.length>=FALLBACK_MAX_FILES||state.dirCount>=FALLBACK_MAX_DIRS)return state.truncated=!0,state.files;try{let realDir=fs141.realpathSync(dir);if(state.seenRealPaths.has(realDir))return state.files;state.seenRealPaths.add(realDir),state.dirCount++}catch{return state.files}if(!validatePathForRead2(dir,workspace))return state.files;try{let entries=fs141.readdirSync(dir,{withFileTypes:!0});for(let entry of entries){if(state.files.length>=FALLBACK_MAX_FILES||state.dirCount>=FALLBACK_MAX_DIRS){state.truncated=!0;break}let fullPath=path221.join(dir,entry.name),relativePath=path221.relative(workspace,fullPath);if(!validatePathForRead2(fullPath,workspace))continue;if(entry.isDirectory()){if(DEFAULT_SKIP_DIRS.has(entry.name))continue;collectFiles(fullPath,workspace,includeGlobs,excludeGlobs,state,depth+1)}else if(entry.isFile()){if(includeGlobs.length>0&&!matchesGlobs(relativePath,includeGlobs))continue;if(excludeGlobs.length>0&&matchesGlobs(relativePath,excludeGlobs))continue;let normalized=toWorkspaceRelativePath2(fullPath,workspace);if(!normalized)continue;state.files.push(normalized)}}}catch{}return state.files}async function fallbackSearch(opts){let includeGlobs=opts.include?opts.include.split(",").map((p)=>p.trim()).filter(Boolean):[],excludeGlobs=opts.exclude?opts.exclude.split(",").map((p)=>p.trim()).filter(Boolean):[],collectState={files:[],seenRealPaths:new Set,dirCount:0,truncated:!1},files=collectFiles(opts.workspace,opts.workspace,includeGlobs,excludeGlobs,collectState),regex;try{if(opts.mode==="regex")regex=new RegExp(opts.query);else regex=new RegExp(escapeRegex4(opts.query))}catch(err2){return{error:!0,type:"invalid-query",message:err2 instanceof Error?err2.message:"Invalid regex pattern"}}let matches=[],total=0,totalBytesRead=0,truncated=collectState.truncated;for(let file3 of files){let fullPath=path221.join(opts.workspace,file3);if(!validatePathForRead2(fullPath,opts.workspace))continue;let stats2;try{if(stats2=fs141.statSync(fullPath),stats2.size>MAX_FILE_SIZE_BYTES9)continue;if(totalBytesRead+stats2.size>FALLBACK_MAX_TOTAL_BYTES){truncated=!0;break}totalBytesRead+=stats2.size}catch{continue}let content;try{content=fs141.readFileSync(fullPath,"utf-8")}catch{continue}let lines=content.split(`
|
|
6039
6039
|
`);for(let i=0;i<lines.length;i++){let line=lines[i];if(regex.test(line)){if(total++,matches.length<opts.maxResults)matches.push({file:file3,lineNumber:i+1,lineText:truncateLine(line,opts.maxLines)});regex.lastIndex=0}}}return{matches,truncated:truncated||total>opts.maxResults,total,query:opts.query,mode:opts.mode,maxResults:opts.maxResults,engine:"fallback",warning:"Fallback search uses bounded filesystem traversal and does not fully emulate ripgrep gitignore behavior."}}var search=createSwarmTool({description:"Search for text within workspace files using ripgrep-style interface. Supports literal and regex search modes with glob include/exclude filtering. Returns structured JSON output with file paths, line numbers, and line content.",args:{query:exports_external.string().describe("Search query string (literal or regex depending on mode)"),mode:exports_external.enum(["literal","regex"]).default("literal").describe("Search mode: literal for exact string match, regex for regular expression"),include:exports_external.string().optional().describe('Glob pattern for files to include (e.g., "*.ts", "src/**/*.js")'),exclude:exports_external.string().optional().describe('Glob pattern for files to exclude (e.g., "node_modules/**", "*.test.ts")'),max_results:exports_external.number().default(DEFAULT_MAX_RESULTS4).describe("Maximum number of matches to return"),max_lines:exports_external.number().default(DEFAULT_MAX_LINES).describe("Maximum characters per line in results")},execute:async(args2,directory)=>{let query,mode="literal",include,exclude,maxResults=DEFAULT_MAX_RESULTS4,maxLines=DEFAULT_MAX_LINES;try{let obj=args2;query=String(obj.query??""),mode=obj.mode==="regex"?"regex":"literal",include=typeof obj.include==="string"?obj.include:void 0,exclude=typeof obj.exclude==="string"?obj.exclude:void 0;let rawMaxResults=typeof obj.max_results==="number"?obj.max_results:DEFAULT_MAX_RESULTS4,sanitizedMaxResults=Number.isNaN(rawMaxResults)?DEFAULT_MAX_RESULTS4:rawMaxResults;maxResults=Math.min(Math.max(0,sanitizedMaxResults),HARD_CAP_RESULTS4);let rawMaxLines=typeof obj.max_lines==="number"?obj.max_lines:DEFAULT_MAX_LINES,sanitizedMaxLines=Number.isNaN(rawMaxLines)?DEFAULT_MAX_LINES:rawMaxLines;maxLines=Math.min(Math.max(0,sanitizedMaxLines),HARD_CAP_LINES)}catch{return JSON.stringify({error:!0,type:"invalid-query",message:"Could not parse search arguments"},null,2)}if(!query||query.trim()==="")return JSON.stringify({error:!0,type:"invalid-query",message:"Query cannot be empty"},null,2);if(query.length>MAX_QUERY_LENGTH)return JSON.stringify({error:!0,type:"invalid-query",message:`Query exceeds maximum length of ${MAX_QUERY_LENGTH} characters`},null,2);if(containsControlChars(query))return JSON.stringify({error:!0,type:"invalid-query",message:"Query contains invalid control characters"},null,2);if(include&&containsPathTraversal(include))return JSON.stringify({error:!0,type:"path-escape",message:"Include pattern contains path traversal sequence"},null,2);if(exclude&&containsPathTraversal(exclude))return JSON.stringify({error:!0,type:"path-escape",message:"Exclude pattern contains path traversal sequence"},null,2);if(include&&containsWindowsAttacks4(include))return JSON.stringify({error:!0,type:"path-escape",message:"Include pattern contains invalid Windows-specific sequence"},null,2);if(exclude&&containsWindowsAttacks4(exclude))return JSON.stringify({error:!0,type:"path-escape",message:"Exclude pattern contains invalid Windows-specific sequence"},null,2);if(!fs141.existsSync(directory))return JSON.stringify({error:!0,type:"unknown",message:"Workspace directory does not exist"},null,2);let result;if(_internals139.resolveRipgrepBinary())result=await ripgrepSearch({query,mode,include,exclude,maxResults,maxLines,workspace:directory});else result=await fallbackSearch({query,mode,include,exclude,maxResults,maxLines,workspace:directory});if("error"in result&&result.error)return JSON.stringify(result,null,2);return JSON.stringify(result,null,2)}}),_internals139={resolvePackagedRipgrep,resolveExecutableFromPath,resolveRipgrepBinary,runExternalTool,fallbackSearch};init_secretscan();init_zod();init_qa_gate_profile();init_manager();init_utils3();init_create_tool();async function executeSetQaGates(args2,directory){let plan=await loadPlanJsonOnly(directory);if(!plan)return{success:!1,reason:"plan_json_unavailable",message:"Cannot configure QA gates: plan.json is missing or invalid. Create a plan first (e.g. via /swarm specify or save_plan)."};let planId=derivePlanId(plan);getOrCreateProfile(directory,planId,args2.project_type);let partial3={};for(let key of["reviewer","test_engineer","council_mode","sme_enabled","critic_pre_plan","hallucination_guard","sast_enabled","mutation_test","phase_council","drift_check","final_council"])if(args2[key]!==void 0)partial3[key]=args2[key];try{let updated=setGates(directory,planId,partial3);return{success:!0,plan_id:planId,message:`QA gates updated for plan_id=${planId}`,profile:{plan_id:updated.plan_id,gates:{...updated.gates},locked_at:updated.locked_at,locked_by_snapshot_seq:updated.locked_by_snapshot_seq,profile_hash:computeProfileHash(updated)}}}catch(err2){let msg=err2 instanceof Error?err2.message:String(err2),lower=msg.toLowerCase(),reason="set_gates_failed";if(lower.includes("locked"))reason="profile_locked";else if(lower.includes("ratchet"))reason="ratchet_violation";return{success:!1,reason,message:msg,plan_id:planId}}}var set_qa_gates=createSwarmTool({description:"Configure the QA gate profile for the current plan. Architect-only. Ratchet-tighter: can enable additional gates but cannot disable gates that are already enabled. Rejects all writes once the profile is locked (after critic approval). Creates the profile with defaults if none exists. plan_id is derived automatically from plan.json.",args:{reviewer:exports_external.boolean().optional().describe("Enable the reviewer gate (true) — cannot be disabled."),test_engineer:exports_external.boolean().optional().describe("Enable the test_engineer gate (true) — cannot be disabled once on."),council_mode:exports_external.boolean().optional().describe("Enable council mode — replaces per-task Stage B (reviewer + test_engineer) with the full 5-member council (critic, reviewer, sme, test_engineer, explorer) per task."),sme_enabled:exports_external.boolean().optional().describe("Enable SME consultation."),critic_pre_plan:exports_external.boolean().optional().describe("Enable critic_pre_plan review before plan approval."),hallucination_guard:exports_external.boolean().optional().describe("Enable hallucination_guard checks on plan and implementation claims."),sast_enabled:exports_external.boolean().optional().describe("Enable SAST scanning as a required QA gate."),mutation_test:exports_external.boolean().optional().describe("Enable the mutation-testing gate (default: off). Requires mutation tests to achieve a passing kill rate before phase completion; WARN verdict allows advancement, FAIL blocks."),phase_council:exports_external.boolean().optional().describe("Enable the phase_council gate (default: off). When on, a full 5-member council (critic, reviewer, sme, test_engineer, explorer) reviews all work completed in a phase holistically at phase_complete time. Requires council.enabled: true in config."),drift_check:exports_external.boolean().optional().describe("Enable drift verification gate (default: on). Blocks phase_complete until drift-verifier.json has an approved verdict. When disabled, drift verification is skipped entirely."),final_council:exports_external.boolean().optional().describe("Enable the final_council gate (default: off). When on, after all phases complete the architect dispatches critic, reviewer, sme, test_engineer, and explorer with project-scoped context, collects their CouncilMemberVerdict objects, and calls write_final_council_evidence. This is not General Council mode and does not require council.general.enabled."),project_type:exports_external.string().optional().describe('Project type label (e.g. "ts", "python"). Only applied when the profile is being created for the first time.')},execute:async(args2,directory)=>{return JSON.stringify(await executeSetQaGates(args2??{},directory),null,2)}});init_zod();init_skill_generator();init_create_tool();var skill_apply=createSwarmTool({description:"Activate a draft skill proposal (.swarm/skills/proposals/<slug>.md) into .opencode/skills/generated/<slug>/SKILL.md.",args:{slug:exports_external.string().min(1).describe("Slug of the proposal to activate."),force:exports_external.boolean().optional().default(!1).describe("Overwrite an existing active SKILL.md even if it lacks the generator stamp. Default false."),evaluate:exports_external.boolean().optional().default(!1).describe("Validate the proposal against .swarm/skills/evals/<slug> before activation. Default false."),confirm_unevaluated:exports_external.boolean().optional().default(!1).describe('Allow activation when evaluateSkillChange returns status "unevaluated" (no eval set exists). Default false — the activation is blocked with a surfaced reason so the caller can confirm. Generated skills auto-derive an eval stub from their source directives, so this only applies to non-directive skills with no stub.')},execute:async(args2,directory)=>{let a=args2??{};if(!a.slug||typeof a.slug!=="string")return JSON.stringify({activated:!1,reason:"slug required"});let result=await activateProposal(directory,a.slug,a.force??!1,{evaluate:a.evaluate??!1,confirmUnevaluated:a.confirm_unevaluated??!1});return JSON.stringify(result,null,2)}});init_zod();init_skill_generator();init_create_tool();var skill_generate=createSwarmTool({description:'Compile mature knowledge entries into a SKILL.md. mode="draft" writes a proposal under .swarm/skills/proposals; mode="active" writes the live skill under .opencode/skills/generated and stamps source entries.',args:{source_knowledge_ids:exports_external.array(exports_external.string()).optional().describe("Optional explicit knowledge ids to compile. If omitted, all mature candidates are clustered and emitted."),slug:exports_external.string().optional().describe("Optional slug for the FIRST cluster. Sanitized; rejected if invalid."),mode:exports_external.enum(["draft","active"]).default("draft"),force:exports_external.boolean().optional().default(!1),evaluate:exports_external.boolean().optional().default(!1).describe("Validate generated skill content against .swarm/skills/evals/<slug> before writing. Default false."),min_confidence:exports_external.number().min(0).max(1).optional(),min_confirmations:exports_external.number().int().min(1).max(50).optional()},execute:async(args2,directory)=>{let a=args2??{},result=await generateSkills({directory,mode:a.mode??"draft",slug:a.slug,sourceKnowledgeIds:a.source_knowledge_ids,force:a.force??!1,evaluate:a.evaluate??!1,minConfidence:a.min_confidence,minConfirmations:a.min_confirmations});return JSON.stringify(result,null,2)}});init_zod();init_config();init_schema();init_skill_improver();init_create_tool();var skill_improve=createSwarmTool({description:'Run the skill_improver capability under daily quota. Writes a proposal under .swarm/skill-improver/proposals/<timestamp>.md. With mode="draft_skills" it also drafts SKILL.md proposals for mature clusters. Quota is enforced via .swarm/skill-improver-quota.json.',args:{targets:exports_external.array(exports_external.enum(["skills","spec","architect_prompt","knowledge"])).optional(),mode:exports_external.enum(["proposal","draft_skills"]).optional(),max_calls:exports_external.number().int().min(1).max(100).optional().describe("Override the per-run reservation count (capped by daily max)."),evaluate:exports_external.boolean().optional().default(!1).describe('When mode="draft_skills", validate generated draft skills before writing proposals. Default false.')},execute:async(args2,directory,ctx)=>{let a=args2??{},{config:config3}=loadPluginConfigWithMeta(directory),parsed=SkillImproverConfigSchema.parse(config3.skill_improver??{}),enrichmentConfig=KnowledgeConfigSchema.parse(config3.knowledge??{}).enrichment??{max_calls_per_day:30,quota_window:"utc"};if(!parsed.enabled)return JSON.stringify({ran:!1,reason:'skill_improver is disabled. Set "skill_improver.enabled": true in opencode-swarm config to use this tool.'},null,2);let result=await runSkillImprover({directory,config:parsed,targets:a.targets,mode:a.mode,maxCalls:a.max_calls,sessionId:ctx?.sessionID,enrichmentQuota:{maxCalls:enrichmentConfig.max_calls_per_day,window:enrichmentConfig.quota_window},evaluateDrafts:a.evaluate??!1});return JSON.stringify(result,null,2)}});init_zod();init_skill_generator();init_create_tool();var skill_inspect=createSwarmTool({description:"Read a generated skill (active or draft) and return its full markdown body and metadata.",args:{slug:exports_external.string().min(1).describe("Slug of the skill to inspect."),prefer:exports_external.enum(["auto","proposal","active"]).optional().default("auto")},execute:async(args2,directory)=>{let a=args2??{};if(!a.slug||typeof a.slug!=="string")return JSON.stringify({found:!1,reason:"slug required"});let result=await inspectSkill(directory,a.slug,a.prefer??"auto");return JSON.stringify(result,null,2)}});init_skill_generator();init_create_tool();var skill_list=createSwarmTool({description:"List generated skill drafts (under .swarm/skills/proposals) and active generated skills (under .opencode/skills/generated).",args:{},execute:async(_args,directory)=>{let result=await listSkills(directory);return JSON.stringify(result,null,2)}});init_zod();init_skill_generator();init_create_tool();var skill_regenerate=createSwarmTool({description:"Regenerate an active skill by re-clustering its source knowledge entries and updating the SKILL.md in place.",args:{slug:exports_external.string().min(1).describe("Slug of the active skill to regenerate."),evaluate:exports_external.boolean().optional().default(!1).describe("Validate regenerated content against .swarm/skills/evals/<slug> before writing. Default false.")},execute:async(args2,directory)=>{let a=args2??{};if(!a.slug||typeof a.slug!=="string")return JSON.stringify({regenerated:!1,reason:"slug required"});let result=await regenerateSkill(directory,a.slug,{evaluate:a.evaluate??!1});return JSON.stringify(result,null,2)}});init_zod();init_skill_generator();init_create_tool();var skill_retire=createSwarmTool({description:"Retire a generated skill by adding a retired.marker file. Retired skills are excluded from scoring and injection.",args:{slug:exports_external.string().min(1).describe("Slug of the active skill to retire."),reason:exports_external.string().optional().describe("Optional reason for retirement.")},execute:async(args2,directory)=>{let a=args2??{};if(!a.slug||typeof a.slug!=="string")return JSON.stringify({retired:!1,reason:"slug required"});let result=await retireSkill(directory,a.slug,a.reason);return JSON.stringify(result,null,2)}});init_zod();init_config();init_schema();init_create_tool();import{mkdir as mkdir37,rename as rename15,writeFile as writeFile25}from"node:fs/promises";import*as path222 from"node:path";var MAX_SPEC_BYTES2=262144,spec_write=createSwarmTool({description:"Write the canonical project spec to .swarm/spec.md. Atomic write, size-bounded (256 KiB), heading-required. Honors spec_writer.allow_spec_write.",args:{content:exports_external.string().min(20).max(MAX_SPEC_BYTES2),mode:exports_external.enum(["replace","append"]).optional().default("replace")},execute:async(args2,directory)=>{let a=args2??{},content=a.content,mode=a.mode??"replace";if(typeof content!=="string"||content.length<20)return JSON.stringify({written:!1,reason:"content must be a string >=20 chars"});if(content.length>MAX_SPEC_BYTES2)return JSON.stringify({written:!1,reason:`content exceeds ${MAX_SPEC_BYTES2} bytes`});let{config:config3}=loadPluginConfigWithMeta(directory);if(!SpecWriterConfigSchema.parse(config3.spec_writer??{}).allow_spec_write)return JSON.stringify({written:!1,reason:"spec_writer.allow_spec_write is false"},null,2);if(content.indexOf("\x00")!==-1)return JSON.stringify({written:!1,reason:"content contains null byte"},null,2);if(!/^#\s+/m.test(content))return JSON.stringify({written:!1,reason:'spec must contain at least one top-level "# Heading"'},null,2);let target=path222.join(directory,".swarm","spec.md");await mkdir37(path222.dirname(target),{recursive:!0});let tmp=`${target}.tmp-${process.pid}-${Date.now()}`,finalContent=content;if(mode==="append")try{if(finalContent=`${(await(await import("node:fs/promises")).readFile(target,"utf-8")).replace(/\s+$/,"")}
|
|
@@ -6068,9 +6068,9 @@ Ignoring will not affect already-tracked files. To stop tracking them, run:
|
|
|
6068
6068
|
echo ".swarm/" >> .gitignore
|
|
6069
6069
|
git commit -m "Stop tracking opencode-swarm runtime state"`)}catch{}}var _internals144={bunSpawn};function getDeclaredScope(taskId,directory){try{let planPath=path228.join(directory,".swarm","plan.json");if(!fs146.existsSync(planPath))return null;let raw=fs146.readFileSync(planPath,"utf-8"),plan=JSON.parse(raw);for(let phase of plan.phases??[])for(let task of phase.tasks??[]){if(task.id!==taskId)continue;let ft=task.files_touched;if(Array.isArray(ft)&&ft.length>0)return ft;if(typeof ft==="string"&&ft.length>0)return[ft];return null}return null}catch{return null}}var GIT_DIFF_SPAWN_OPTIONS={timeout:ENSURE_SWARM_GIT_EXCLUDED_PER_CALL_TIMEOUT_MS,stdin:"ignore",stdout:"pipe",stderr:"pipe"};async function getChangedFiles2(directory){try{let proc=_internals144.bunSpawn(["git","diff","--name-only","HEAD~1"],{cwd:directory,...GIT_DIFF_SPAWN_OPTIONS}),exitCode,stdout;try{[exitCode,stdout]=await Promise.all([proc.exited,proc.stdout.text()])}finally{try{proc.kill()}catch{}}if(exitCode===0)return stdout.trim().split(`
|
|
6070
6070
|
`).map((f)=>f.trim()).filter((f)=>f.length>0);let proc2=_internals144.bunSpawn(["git","diff","--name-only","HEAD"],{cwd:directory,...GIT_DIFF_SPAWN_OPTIONS}),exitCode2,stdout2;try{[exitCode2,stdout2]=await Promise.all([proc2.exited,proc2.stdout.text()])}finally{try{proc2.kill()}catch{}}if(exitCode2===0)return stdout2.trim().split(`
|
|
6071
|
-
`).map((f)=>f.trim()).filter((f)=>f.length>0);return null}catch{return null}}async function validateDiffScope(taskId,directory){try{let declaredScope=getDeclaredScope(taskId,directory);if(!declaredScope)return null;let changedFiles=await getChangedFiles2(directory);if(!changedFiles)return null;let nonSwarmFiles=changedFiles.filter((f)=>!f.replace(/\\/g,"/").replace(/^\.\//,"").startsWith(".swarm/")),normalise=(p)=>p.replace(/\\/g,"/").replace(/^\.\//,""),normScope=new Set(declaredScope.map(normalise)),undeclared=nonSwarmFiles.map(normalise).filter((f)=>!normScope.has(f));if(undeclared.length===0)return null;let scopeStr=declaredScope.join(", "),undeclaredStr=undeclared.slice(0,5).join(", "),extra=undeclared.length>5?` (+${undeclared.length-5} more)`:"";return`SCOPE WARNING: Task ${taskId} declared scope [${scopeStr}] but also modified [${undeclaredStr}${extra}]. Reviewer should verify these changes are intentional.`}catch{return null}}init_file_locks();init_manager();init_utils3();init_state2();init_telemetry();init_file_locks();import*as fs147 from"node:fs";import*as path229 from"node:path";var _internals145={listActiveLocks,verifyLeanTurboTaskCompletion},TIER_3_PATTERNS=[/^architect.*\.ts$/i,/^delegation.*\.ts$/i,/^guardrails.*\.ts$/i,/^adversarial.*\.ts$/i,/^sanitiz.*\.ts$/i,/^auth.*$/i,/^permission.*$/i,/^crypto.*$/i,/^secret.*$/i,/^security.*\.ts$/i];function matchesTier3Pattern(files){for(let file3 of files){let fileName=path229.basename(file3);for(let pattern of TIER_3_PATTERNS)if(pattern.test(fileName))return!0}return!1}function verifyLeanTurboTaskCompletion(directory,taskId,sessionID){let persisted=null;try{let statePath=path229.join(directory,".swarm","turbo-state.json");if(!fs147.existsSync(statePath))return{ok:!1,reason:"Lean Turbo state file not found"};let raw=fs147.readFileSync(statePath,"utf-8");persisted=JSON.parse(raw)}catch{return{ok:!1,reason:"Lean Turbo state file unreadable or malformed"}}if(typeof persisted!=="object"||persisted===null||typeof persisted.sessions!=="object"||persisted.sessions===null||Array.isArray(persisted.sessions))return{ok:!1,reason:"Lean Turbo state malformed: missing expected fields"};let runState=null;for(let sessionState of Object.values(persisted.sessions))if(typeof sessionState==="object"&&sessionState!==null&&sessionState.strategy==="lean"&&sessionState.status==="running"){if(sessionID!==void 0&&sessionState.sessionID!==sessionID)continue;runState=sessionState;break}if(!runState)return{ok:!1,reason:"No active Lean Turbo run state found"};if(!Array.isArray(runState.lanes)||!Array.isArray(runState.degradedTasks))return{ok:!1,reason:"Lean Turbo state malformed: missing expected fields"};let lane=runState.lanes.find((l)=>typeof l==="object"&&l!==null&&Array.isArray(l.taskIds)&&typeof l.laneId==="string"&&l.taskIds.includes(taskId));if(!lane)return{ok:!1,reason:`Task ${taskId} not found in any Lean Turbo lane`,laneFound:!1};let degradedTask=runState.degradedTasks.find((dt)=>typeof dt==="object"&&dt!==null&&dt.taskId===taskId);if(degradedTask)return{ok:!1,reason:`Task ${taskId} is degraded: ${degradedTask.reason}`,laneFound:!0};if(lane.status!=="completed")return{ok:!1,reason:`Lane ${lane.laneId} is not completed (status: ${lane.status})`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};if(lane.laneId.length===0||lane.laneId.includes("/")||lane.laneId.includes("\\")||lane.laneId.includes(".."))return{ok:!1,reason:`Lane ID contains invalid characters: ${lane.laneId}`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};let phase=runState.phase??0,evidencePath=path229.join(directory,".swarm","evidence",String(phase),"lean-turbo",`${lane.laneId}.json`),expectedDir=path229.join(directory,".swarm","evidence",String(phase),"lean-turbo"),resolvedPath=path229.resolve(evidencePath),resolvedDir=path229.resolve(expectedDir);if(!resolvedPath.startsWith(resolvedDir+path229.sep)&&resolvedPath!==resolvedDir)return{ok:!1,reason:`Lane ID causes path traversal: ${lane.laneId}`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};if(!fs147.existsSync(evidencePath))return{ok:!1,reason:`Lane ${lane.laneId} evidence file not found: ${evidencePath}`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};let laneLocks=_internals145.listActiveLocks(directory).filter((lock)=>lock.laneId===lane.laneId);if(laneLocks.length>0)return{ok:!1,reason:`Active file locks exist for lane ${lane.laneId}: ${laneLocks.map((l)=>l.filePath).join(", ")}`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};let filesTouched=[];try{let planPath=path229.join(directory,".swarm","plan.json"),planRaw=fs147.readFileSync(planPath,"utf-8"),plan=JSON.parse(planRaw);for(let planPhase of plan.phases??[])for(let task of planPhase.tasks??[])if(task.id===taskId&&task.files_touched){filesTouched=task.files_touched;break}}catch{return{ok:!1,reason:`Cannot verify Tier-3 patterns for task ${taskId}: plan.json unreadable`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}}}if(filesTouched.length>0&&matchesTier3Pattern(filesTouched))return{ok:!1,reason:`Task ${taskId} touches Tier-3 security-sensitive files and cannot bypass Stage B`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};return{ok:!0,reason:`Task ${taskId} in completed lane ${lane.laneId}`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}}}init_task_id();init_create_tool();init_resolve_working_directory();var _internals146={tryAcquireLock,updateTaskStatus,resolveWorkingDirectory,loadPlan},VALID_STATUSES2=["pending","in_progress","completed","blocked"];function validateStatus(status){if(!VALID_STATUSES2.includes(status))return`Invalid status "${status}". Must be one of: ${VALID_STATUSES2.join(", ")}`;return}function validateTaskId(taskId){if(validateTaskIdFormat(taskId))return`Invalid task_id "${taskId}". Must match pattern N.M or N.M.P (e.g., "1.1", "1.2.3")`;return}var TIER_3_PATTERNS2=[/^architect.*\.ts$/i,/^delegation.*\.ts$/i,/^guardrails.*\.ts$/i,/^adversarial.*\.ts$/i,/^sanitiz.*\.ts$/i,/^auth.*$/i,/^permission.*$/i,/^crypto.*$/i,/^secret.*$/i,/^security.*\.ts$/i];function matchesTier3Pattern2(files){for(let file3 of files){let fileName=path230.basename(file3);for(let pattern of TIER_3_PATTERNS2)if(pattern.test(fileName))return!0}return!1}function hasPassedDurableGateEvidence(workingDirectory,taskId){let evidence=readTaskEvidenceRaw(workingDirectory,taskId);if(!evidence||!Array.isArray(evidence.required_gates)||evidence.required_gates.length===0)return!1;return evidence.required_gates.every((gate)=>evidence.gates?.[gate]!=null)}function checkReviewerGate(taskId,workingDirectory,stageBParallelEnabled=!1,sessionID,fallbackDir){try{let skipStandardTurboBypass=!1;if(hasActiveLeanTurbo()){let resolvedDir2=workingDirectory;try{let leanCheck=verifyLeanTurboTaskCompletion(resolvedDir2,taskId,sessionID);if(leanCheck.ok)return{blocked:!1,reason:`Lean Turbo bypass: ${leanCheck.reason}`};if(leanCheck.laneFound!==!1)skipStandardTurboBypass=!0}catch{skipStandardTurboBypass=!0}}if(!skipStandardTurboBypass&&hasActiveTurboMode()){let resolvedDir2=workingDirectory;try{let planPath=path230.join(resolvedDir2,".swarm","plan.json"),planRaw=fs148.readFileSync(planPath,"utf-8"),plan=JSON.parse(planRaw);for(let planPhase of plan.phases??[])for(let task of planPhase.tasks??[])if(task.id===taskId&&task.files_touched){if(!matchesTier3Pattern2(task.files_touched))return{blocked:!1,reason:"Turbo Mode bypass"};break}}catch{}}let resolvedDir;if(fallbackDir){let resolveResult=_internals146.resolveWorkingDirectory(workingDirectory,fallbackDir);if(resolveResult.success)resolvedDir=resolveResult.directory;else resolvedDir=fallbackDir}else if(workingDirectory)resolvedDir=workingDirectory;let evidenceIncompleteReason=null;try{if(!resolvedDir);else{let evidence=readTaskEvidenceRaw(resolvedDir,taskId);if(evidence===null);else if(evidence.required_gates&&Array.isArray(evidence.required_gates)&&evidence.gates){if(evidence.required_gates.length>0&&evidence.required_gates.every((gate)=>evidence.gates[gate]!=null))return{blocked:!1,reason:""};let missingGates=evidence.required_gates.filter((gate)=>evidence.gates[gate]==null);evidenceIncompleteReason=evidence.required_gates.length===0?`Task ${taskId} has an evidence file with no required gates. Delegate reviewer and test_engineer before marking task as completed.`:`Task ${taskId} is missing required gates: [${missingGates.join(", ")}]. Required: [${evidence.required_gates.join(", ")}]. Completed: [${Object.keys(evidence.gates).join(", ")}]. Delegate the missing gate agents before marking task as completed.`}}}catch(error93){return console.warn(`[gate-evidence] Evidence file for task ${taskId} is corrupt or unreadable:`,error93 instanceof Error?error93.message:String(error93)),telemetry.gateFailed("","qa_gate",taskId,"Evidence file corrupt or unreadable"),{blocked:!0,reason:`Evidence file for task ${taskId} is corrupt or unreadable. Fix the file at .swarm/evidence/${taskId}.json or delete it to fall through to session state.`}}if(swarmState.agentSessions.size===0&&!evidenceIncompleteReason)return{blocked:!1,reason:""};let validSessionCount=0;for(let[_sessionId,session]of swarmState.agentSessions){if(!(session.taskWorkflowStates instanceof Map))continue;validSessionCount++;let state=getTaskState(session,taskId);if(state==="tests_run"||state==="complete")return{blocked:!1,reason:""};if(stageBParallelEnabled&&hasBothStageBCompletions(session,taskId))return{blocked:!1,reason:""}}if(validSessionCount===0&&!evidenceIncompleteReason)return{blocked:!1,reason:""};let stateEntries=[];for(let[sessionId,session]of swarmState.agentSessions){if(!(session.taskWorkflowStates instanceof Map))continue;let state=getTaskState(session,taskId);stateEntries.push(`${sessionId}: ${state}`)}if(resolvedDir)try{let planPath=path230.join(resolvedDir,".swarm","plan.json"),planRaw=fs148.readFileSync(planPath,"utf-8"),plan=JSON.parse(planRaw);for(let planPhase of plan.phases??[])for(let task of planPhase.tasks??[])if(task.id===taskId&&task.status==="completed"&&hasPassedDurableGateEvidence(resolvedDir,taskId))return{blocked:!1,reason:""}}catch{}{let hasReviewer=!1,hasTestEngineer=!1;for(let[sessionId,chain]of swarmState.delegationChains){let session=swarmState.agentSessions.get(sessionId);if(session&&(session.currentTaskId===taskId||session.lastCoderDelegationTaskId===taskId))for(let delegation of chain){let target=stripKnownSwarmPrefix(delegation.to);if(target==="reviewer")hasReviewer=!0;if(target==="test_engineer")hasTestEngineer=!0}}if(hasReviewer&&hasTestEngineer)return{blocked:!1,reason:""};if(!evidenceIncompleteReason&&(!hasReviewer||!hasTestEngineer)){for(let[sessionId,chain]of swarmState.delegationChains){if(chain.some((d)=>stripKnownSwarmPrefix(d.to)==="coder"))continue;let chainSession=swarmState.agentSessions.get(sessionId);if(chainSession){let chainTaskId=chainSession.currentTaskId||chainSession.lastCoderDelegationTaskId;if(chainTaskId&&chainTaskId!==taskId)continue}for(let delegation of chain){let target=stripKnownSwarmPrefix(delegation.to);if(target==="reviewer")hasReviewer=!0;if(target==="test_engineer")hasTestEngineer=!0}}if(hasReviewer&&hasTestEngineer)return{blocked:!1,reason:""}}}let currentStateStr=stateEntries.length>0?stateEntries.join(", "):"no active sessions",chainEntries=[];for(let[sessionId,chain]of swarmState.delegationChains){let session=swarmState.agentSessions.get(sessionId);if(session&&(session.currentTaskId===taskId||session.lastCoderDelegationTaskId===taskId)){let targets=chain.map((d)=>stripKnownSwarmPrefix(d.to));chainEntries.push(`${sessionId}: [${targets.join(", ")}]`)}}let chainSummary=chainEntries.length>0?chainEntries.join("; "):"no chains for this task",rehydratedSessionCount=[...swarmState.agentSessions.values()].filter((s)=>s.sessionRehydratedAt>0).length,finalReason=[`Task ${taskId} has not passed QA gates.`,` Session states: [${currentStateStr}].`,` Delegation chains: [${chainSummary}].`,` Evidence: [${evidenceIncompleteReason??"no evidence file found"}].`,` Rehydrated sessions: ${rehydratedSessionCount}.`," Missing required state: tests_run or complete."].join(`
|
|
6071
|
+
`).map((f)=>f.trim()).filter((f)=>f.length>0);return null}catch{return null}}async function validateDiffScope(taskId,directory){try{let declaredScope=getDeclaredScope(taskId,directory);if(!declaredScope)return null;let changedFiles=await getChangedFiles2(directory);if(!changedFiles)return null;let nonSwarmFiles=changedFiles.filter((f)=>!f.replace(/\\/g,"/").replace(/^\.\//,"").startsWith(".swarm/")),normalise=(p)=>p.replace(/\\/g,"/").replace(/^\.\//,""),normScope=new Set(declaredScope.map(normalise)),undeclared=nonSwarmFiles.map(normalise).filter((f)=>!normScope.has(f));if(undeclared.length===0)return null;let scopeStr=declaredScope.join(", "),undeclaredStr=undeclared.slice(0,5).join(", "),extra=undeclared.length>5?` (+${undeclared.length-5} more)`:"";return`SCOPE WARNING: Task ${taskId} declared scope [${scopeStr}] but also modified [${undeclaredStr}${extra}]. Reviewer should verify these changes are intentional.`}catch{return null}}init_file_locks();init_manager();init_utils3();init_state2();init_telemetry();init_file_locks();import*as fs147 from"node:fs";import*as path229 from"node:path";var _internals145={listActiveLocks,verifyLeanTurboTaskCompletion},TIER_3_PATTERNS=[/^architect.*\.ts$/i,/^delegation.*\.ts$/i,/^guardrails.*\.ts$/i,/^adversarial.*\.ts$/i,/^sanitiz.*\.ts$/i,/^auth.*$/i,/^permission.*$/i,/^crypto.*$/i,/^secret.*$/i,/^security.*\.ts$/i];function matchesTier3Pattern(files){for(let file3 of files){let fileName=path229.basename(file3);for(let pattern of TIER_3_PATTERNS)if(pattern.test(fileName))return!0}return!1}function verifyLeanTurboTaskCompletion(directory,taskId,sessionID){let persisted=null;try{let statePath=path229.join(directory,".swarm","turbo-state.json");if(!fs147.existsSync(statePath))return{ok:!1,reason:"Lean Turbo state file not found"};let raw=fs147.readFileSync(statePath,"utf-8");persisted=JSON.parse(raw)}catch{return{ok:!1,reason:"Lean Turbo state file unreadable or malformed"}}if(typeof persisted!=="object"||persisted===null||typeof persisted.sessions!=="object"||persisted.sessions===null||Array.isArray(persisted.sessions))return{ok:!1,reason:"Lean Turbo state malformed: missing expected fields"};let runState=null;for(let sessionState of Object.values(persisted.sessions))if(typeof sessionState==="object"&&sessionState!==null&&sessionState.strategy==="lean"&&sessionState.status==="running"){if(sessionID!==void 0&&sessionState.sessionID!==sessionID)continue;runState=sessionState;break}if(!runState)return{ok:!1,reason:"No active Lean Turbo run state found"};if(!Array.isArray(runState.lanes)||!Array.isArray(runState.degradedTasks))return{ok:!1,reason:"Lean Turbo state malformed: missing expected fields"};let lane=runState.lanes.find((l)=>typeof l==="object"&&l!==null&&Array.isArray(l.taskIds)&&typeof l.laneId==="string"&&l.taskIds.includes(taskId));if(!lane)return{ok:!1,reason:`Task ${taskId} not found in any Lean Turbo lane`,laneFound:!1};let degradedTask=runState.degradedTasks.find((dt)=>typeof dt==="object"&&dt!==null&&dt.taskId===taskId);if(degradedTask)return{ok:!1,reason:`Task ${taskId} is degraded: ${degradedTask.reason}`,laneFound:!0};if(lane.status!=="completed")return{ok:!1,reason:`Lane ${lane.laneId} is not completed (status: ${lane.status})`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};if(lane.laneId.length===0||lane.laneId.includes("/")||lane.laneId.includes("\\")||lane.laneId.includes(".."))return{ok:!1,reason:`Lane ID contains invalid characters: ${lane.laneId}`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};let phase=runState.phase??0,evidencePath=path229.join(directory,".swarm","evidence",String(phase),"lean-turbo",`${lane.laneId}.json`),expectedDir=path229.join(directory,".swarm","evidence",String(phase),"lean-turbo"),resolvedPath=path229.resolve(evidencePath),resolvedDir=path229.resolve(expectedDir);if(!resolvedPath.startsWith(resolvedDir+path229.sep)&&resolvedPath!==resolvedDir)return{ok:!1,reason:`Lane ID causes path traversal: ${lane.laneId}`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};if(!fs147.existsSync(evidencePath))return{ok:!1,reason:`Lane ${lane.laneId} evidence file not found: ${evidencePath}`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};let laneLocks=_internals145.listActiveLocks(directory).filter((lock)=>lock.laneId===lane.laneId);if(laneLocks.length>0)return{ok:!1,reason:`Active file locks exist for lane ${lane.laneId}: ${laneLocks.map((l)=>l.filePath).join(", ")}`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};let filesTouched=[];try{let planPath=path229.join(directory,".swarm","plan.json"),planRaw=fs147.readFileSync(planPath,"utf-8"),plan=JSON.parse(planRaw);for(let planPhase of plan.phases??[])for(let task of planPhase.tasks??[])if(task.id===taskId&&task.files_touched){filesTouched=task.files_touched;break}}catch{return{ok:!1,reason:`Cannot verify Tier-3 patterns for task ${taskId}: plan.json unreadable`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}}}if(filesTouched.length>0&&matchesTier3Pattern(filesTouched))return{ok:!1,reason:`Task ${taskId} touches Tier-3 security-sensitive files and cannot bypass Stage B`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};return{ok:!0,reason:`Task ${taskId} in completed lane ${lane.laneId}`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}}}init_logger();init_task_id();init_create_tool();init_resolve_working_directory();var _internals146={tryAcquireLock,updateTaskStatus,resolveWorkingDirectory,loadPlan},VALID_STATUSES2=["pending","in_progress","completed","blocked"];function validateStatus(status){if(!VALID_STATUSES2.includes(status))return`Invalid status "${status}". Must be one of: ${VALID_STATUSES2.join(", ")}`;return}function validateTaskId(taskId){if(validateTaskIdFormat(taskId))return`Invalid task_id "${taskId}". Must match pattern N.M or N.M.P (e.g., "1.1", "1.2.3")`;return}var TIER_3_PATTERNS2=[/^architect.*\.ts$/i,/^delegation.*\.ts$/i,/^guardrails.*\.ts$/i,/^adversarial.*\.ts$/i,/^sanitiz.*\.ts$/i,/^auth.*$/i,/^permission.*$/i,/^crypto.*$/i,/^secret.*$/i,/^security.*\.ts$/i];function matchesTier3Pattern2(files){for(let file3 of files){let fileName=path230.basename(file3);for(let pattern of TIER_3_PATTERNS2)if(pattern.test(fileName))return!0}return!1}function hasPassedDurableGateEvidence(workingDirectory,taskId){let evidence=readTaskEvidenceRaw(workingDirectory,taskId);if(!evidence||!Array.isArray(evidence.required_gates)||evidence.required_gates.length===0)return!1;return evidence.required_gates.every((gate)=>evidence.gates?.[gate]!=null)}function checkReviewerGate(taskId,workingDirectory,stageBParallelEnabled=!1,sessionID,fallbackDir){try{let skipStandardTurboBypass=!1;if(hasActiveLeanTurbo()){let resolvedDir2=workingDirectory;try{let leanCheck=verifyLeanTurboTaskCompletion(resolvedDir2,taskId,sessionID);if(leanCheck.ok)return{blocked:!1,reason:`Lean Turbo bypass: ${leanCheck.reason}`};if(leanCheck.laneFound!==!1)skipStandardTurboBypass=!0}catch{skipStandardTurboBypass=!0}}if(!skipStandardTurboBypass&&hasActiveTurboMode()){let resolvedDir2=workingDirectory;try{let planPath=path230.join(resolvedDir2,".swarm","plan.json"),planRaw=fs148.readFileSync(planPath,"utf-8"),plan=JSON.parse(planRaw);for(let planPhase of plan.phases??[])for(let task of planPhase.tasks??[])if(task.id===taskId&&task.files_touched){if(!matchesTier3Pattern2(task.files_touched))return{blocked:!1,reason:"Turbo Mode bypass"};break}}catch{}}let resolvedDir;if(fallbackDir){let resolveResult=_internals146.resolveWorkingDirectory(workingDirectory,fallbackDir);if(resolveResult.success)resolvedDir=resolveResult.directory;else resolvedDir=fallbackDir}else if(workingDirectory)resolvedDir=workingDirectory;let evidenceIncompleteReason=null;try{if(!resolvedDir);else{let evidence=readTaskEvidenceRaw(resolvedDir,taskId);if(evidence===null);else if(evidence.required_gates&&Array.isArray(evidence.required_gates)&&evidence.gates){if(evidence.required_gates.length>0&&evidence.required_gates.every((gate)=>evidence.gates[gate]!=null))return{blocked:!1,reason:""};let missingGates=evidence.required_gates.filter((gate)=>evidence.gates[gate]==null);evidenceIncompleteReason=evidence.required_gates.length===0?`Task ${taskId} has an evidence file with no required gates. Delegate reviewer and test_engineer before marking task as completed.`:`Task ${taskId} is missing required gates: [${missingGates.join(", ")}]. Required: [${evidence.required_gates.join(", ")}]. Completed: [${Object.keys(evidence.gates).join(", ")}]. Delegate the missing gate agents before marking task as completed.`}}}catch(error93){return log(`[gate-evidence] Evidence file for task ${taskId} is corrupt or unreadable:`,error93 instanceof Error?error93.message:String(error93)),telemetry.gateFailed("","qa_gate",taskId,"Evidence file corrupt or unreadable"),{blocked:!0,reason:`Evidence file for task ${taskId} is corrupt or unreadable. Fix the file at .swarm/evidence/${taskId}.json or delete it to fall through to session state.`}}if(swarmState.agentSessions.size===0&&!evidenceIncompleteReason)return{blocked:!1,reason:""};let validSessionCount=0;for(let[_sessionId,session]of swarmState.agentSessions){if(!(session.taskWorkflowStates instanceof Map))continue;validSessionCount++;let state=getTaskState(session,taskId);if(state==="tests_run"||state==="complete")return{blocked:!1,reason:""};if(stageBParallelEnabled&&hasBothStageBCompletions(session,taskId))return{blocked:!1,reason:""}}if(validSessionCount===0&&!evidenceIncompleteReason)return{blocked:!1,reason:""};let stateEntries=[];for(let[sessionId,session]of swarmState.agentSessions){if(!(session.taskWorkflowStates instanceof Map))continue;let state=getTaskState(session,taskId);stateEntries.push(`${sessionId}: ${state}`)}if(resolvedDir)try{let planPath=path230.join(resolvedDir,".swarm","plan.json"),planRaw=fs148.readFileSync(planPath,"utf-8"),plan=JSON.parse(planRaw);for(let planPhase of plan.phases??[])for(let task of planPhase.tasks??[])if(task.id===taskId&&task.status==="completed"&&hasPassedDurableGateEvidence(resolvedDir,taskId))return{blocked:!1,reason:""}}catch{}{let hasReviewer=!1,hasTestEngineer=!1;for(let[sessionId,chain]of swarmState.delegationChains){let session=swarmState.agentSessions.get(sessionId);if(session&&(session.currentTaskId===taskId||session.lastCoderDelegationTaskId===taskId))for(let delegation of chain){let target=stripKnownSwarmPrefix(delegation.to);if(target==="reviewer")hasReviewer=!0;if(target==="test_engineer")hasTestEngineer=!0}}if(hasReviewer&&hasTestEngineer)return{blocked:!1,reason:""};if(!evidenceIncompleteReason&&(!hasReviewer||!hasTestEngineer)){for(let[sessionId,chain]of swarmState.delegationChains){if(chain.some((d)=>stripKnownSwarmPrefix(d.to)==="coder"))continue;let chainSession=swarmState.agentSessions.get(sessionId);if(chainSession){let chainTaskId=chainSession.currentTaskId||chainSession.lastCoderDelegationTaskId;if(chainTaskId&&chainTaskId!==taskId)continue}for(let delegation of chain){let target=stripKnownSwarmPrefix(delegation.to);if(target==="reviewer")hasReviewer=!0;if(target==="test_engineer")hasTestEngineer=!0}}if(hasReviewer&&hasTestEngineer)return{blocked:!1,reason:""}}}let currentStateStr=stateEntries.length>0?stateEntries.join(", "):"no active sessions",chainEntries=[];for(let[sessionId,chain]of swarmState.delegationChains){let session=swarmState.agentSessions.get(sessionId);if(session&&(session.currentTaskId===taskId||session.lastCoderDelegationTaskId===taskId)){let targets=chain.map((d)=>stripKnownSwarmPrefix(d.to));chainEntries.push(`${sessionId}: [${targets.join(", ")}]`)}}let chainSummary=chainEntries.length>0?chainEntries.join("; "):"no chains for this task",rehydratedSessionCount=[...swarmState.agentSessions.values()].filter((s)=>s.sessionRehydratedAt>0).length,finalReason=[`Task ${taskId} has not passed QA gates.`,` Session states: [${currentStateStr}].`,` Delegation chains: [${chainSummary}].`,` Evidence: [${evidenceIncompleteReason??"no evidence file found"}].`,` Rehydrated sessions: ${rehydratedSessionCount}.`," Missing required state: tests_run or complete."].join(`
|
|
6072
6072
|
`);return telemetry.gateFailed("","qa_gate",taskId,evidenceIncompleteReason?"Missing gates: evidence incomplete":"Missing state: tests_run or complete"),{blocked:!0,reason:finalReason}}catch{return{blocked:!1,reason:""}}}async function checkReviewerGateWithScope(taskId,workingDirectory,sessionID,fallbackDir){let result=checkReviewerGate(taskId,workingDirectory,!0,sessionID,fallbackDir),scopeWarning=await validateDiffScope(taskId,workingDirectory).catch(()=>null);if(!scopeWarning)return result;return{...result,reason:result.reason?`${result.reason}
|
|
6073
|
-
${scopeWarning}`:scopeWarning}}function recoverTaskStateFromDelegations(taskId,directory){let hasReviewer=!1,hasTestEngineer=!1;for(let[sessionId,chain]of swarmState.delegationChains){let session=swarmState.agentSessions.get(sessionId);if(session&&(session.currentTaskId===taskId||session.lastCoderDelegationTaskId===taskId))for(let delegation of chain){let target=stripKnownSwarmPrefix(delegation.to);if(target==="reviewer")hasReviewer=!0;if(target==="test_engineer")hasTestEngineer=!0}}let hasDurableIncompleteGates=!1;if(directory)try{let taskEvidence=readTaskEvidenceRaw(directory,taskId);if(taskEvidence?.gates&&Array.isArray(taskEvidence.required_gates)&&taskEvidence.required_gates.length>0){let gates=taskEvidence.gates;hasDurableIncompleteGates=taskEvidence.required_gates.some((g)=>gates[g]==null)}}catch{hasDurableIncompleteGates=!0}if(!hasDurableIncompleteGates&&(!hasReviewer||!hasTestEngineer))for(let[sessionId,chain]of swarmState.delegationChains){if(chain.some((d)=>stripKnownSwarmPrefix(d.to)==="coder"))continue;let chainSession=swarmState.agentSessions.get(sessionId);if(chainSession){let chainTaskId=chainSession.currentTaskId||chainSession.lastCoderDelegationTaskId;if(chainTaskId&&chainTaskId!==taskId)continue}for(let delegation of chain){let target=stripKnownSwarmPrefix(delegation.to);if(target==="reviewer")hasReviewer=!0;if(target==="test_engineer")hasTestEngineer=!0}}if((!hasReviewer||!hasTestEngineer)&&directory)try{let evidence=readTaskEvidenceRaw(directory,taskId);if(evidence?.gates&&Array.isArray(evidence.required_gates)){if(evidence.gates.reviewer!=null)hasReviewer=!0;if(evidence.gates.test_engineer!=null)hasTestEngineer=!0}}catch{}if(!hasReviewer&&!hasTestEngineer)return;if(swarmState.agentSessions.size===0)try{startAgentSession("recovery-session","architect")}catch{}for(let[,session]of swarmState.agentSessions){if(!(session.taskWorkflowStates instanceof Map))continue;let currentState=getTaskState(session,taskId);if(currentState==="tests_run"||currentState==="complete")continue;if(hasReviewer&¤tState==="idle")try{advanceTaskState(session,taskId,"coder_delegated")}catch{}if(hasReviewer)recordStageBCompletion(session,taskId,"reviewer");if(hasTestEngineer)recordStageBCompletion(session,taskId,"test_engineer");if(hasReviewer){let stateNow=getTaskState(session,taskId);if(stateNow==="coder_delegated"||stateNow==="pre_check_passed")try{advanceTaskState(session,taskId,"reviewer_run")}catch{}}if(hasTestEngineer){if(getTaskState(session,taskId)==="reviewer_run")try{advanceTaskState(session,taskId,"tests_run")}catch{}}}}function checkCouncilGate(workingDirectory,taskId){let councilEnabled=!1,effectiveMinimum=3;try{let config3=loadPluginConfig(workingDirectory);councilEnabled=config3.council?.enabled===!0,effectiveMinimum=config3.council?.requireAllMembers?5:config3.council?.minimumMembers??3}catch{return{blocked:!1,reason:"",active:!1}}if(!councilEnabled)return{blocked:!1,reason:"",active:!1};try{let planPath=path230.join(workingDirectory,".swarm","plan.json"),planRaw=fs148.readFileSync(planPath,"utf-8"),planObj=JSON.parse(planRaw);if(planObj.swarm&&planObj.title){let planId=derivePlanId(planObj),profile=getProfile(workingDirectory,planId);if(!profile||!profile.gates.council_mode)return{blocked:!1,reason:"",active:!1}}}catch{return{blocked:!1,reason:"",active:!1}}let evidence;try{evidence=readTaskEvidenceRaw(workingDirectory,taskId)}catch{return{blocked:!0,reason:"council gate required but not yet run — architect must call submit_council_verdicts before advancing this task",active:!0}}let councilGate=evidence?.gates?.council;if(!councilGate)return{blocked:!0,reason:"council gate required but not yet run — architect must call submit_council_verdicts before advancing this task",active:!0};if(councilGate.verdict==="REJECT")return{blocked:!0,reason:"council gate blocked advancement — resolve requiredFixes and re-run submit_council_verdicts",active:!0};let rawQuorumSize=councilGate.quorumSize,quorumSize=typeof rawQuorumSize==="number"&&Number.isFinite(rawQuorumSize)&&rawQuorumSize>=1?rawQuorumSize:1;if(quorumSize<effectiveMinimum)return{blocked:!0,reason:`council gate blocked advancement — recorded verdict has insufficient quorum (${quorumSize} of ${effectiveMinimum} required members). Re-run submit_council_verdicts with the missing council members.`,active:!0};return{blocked:!1,reason:"",active:!0}}async function executeUpdateTaskStatus(args2,fallbackDir,ctx){let statusError=validateStatus(args2.status);if(statusError)return{success:!1,message:"Validation failed",errors:[statusError]};let taskIdError=validateTaskId(args2.task_id);if(taskIdError)return{success:!1,message:"Validation failed",errors:[taskIdError]};let directory,resolveResult=_internals146.resolveWorkingDirectory(args2.working_directory,fallbackDir);if(!resolveResult.success)return{success:!1,message:resolveResult.message,errors:[resolveResult.message]};directory=resolveResult.directory;let planPath=path230.join(directory,".swarm","plan.json");if(!fs148.existsSync(planPath))return{success:!1,message:`Invalid working_directory: plan not found in "${directory}"`,errors:[`Invalid working_directory: plan not found in "${directory}"`]};if(fallbackDir&&directory!==fallbackDir){let canonicalDir=fs148.realpathSync(path230.resolve(directory)),canonicalRoot=fs148.realpathSync(path230.resolve(fallbackDir));if(canonicalDir.startsWith(canonicalRoot+path230.sep))return{success:!1,message:`Invalid working_directory: "${directory}" is a subdirectory of the project root "${fallbackDir}". Pass the project root path or omit working_directory entirely.`,errors:[`Subdirectory rejected: use project root "${fallbackDir}" instead`]}}let loadedPlan=null;try{loadedPlan=await _internals146.loadPlan(directory)}catch{loadedPlan=null}if(loadedPlan?._ledgerReplayStale===!0){let staleReason=loadedPlan._ledgerReplayStaleReason??"plan.json is stale relative to the authoritative ledger (.swarm/plan-ledger.jsonl)";return{success:!1,message:`Task status update refused: plan.json is stale relative to the ledger (ledger replay failed). ${staleReason}`,errors:[staleReason],recovery_guidance:"Plan state could not be reconciled with the authoritative ledger (.swarm/plan-ledger.jsonl). Restore from a critic-approved snapshot or re-run plan recovery to rebuild plan.json from the ledger, then retry update_task_status."}}if(args2.status==="in_progress"&&args2.force!==!0){let currentTask=loadedPlan?.phases.flatMap((p)=>p.tasks).find((t)=>t.id===args2.task_id);if(currentTask&¤tTask.status!=="pending"&¤tTask.status!=="in_progress")return{success:!1,message:`Task ${args2.task_id} is settled (${currentTask.status}); cannot re-open to in_progress. Use force:true only for manual repair.`,errors:[`Task ${args2.task_id} is settled (${currentTask.status}); cannot re-open to in_progress. Use force:true only for manual repair.`]}}if(args2.status==="in_progress"&&args2.force===!0)console.warn(`[update-task-status] Force-override: re-opening settled task ${args2.task_id} to in_progress`);if(args2.status==="in_progress")for(let[_sessionId,session]of swarmState.agentSessions){if(getTaskState(session,args2.task_id)==="idle")try{advanceTaskState(session,args2.task_id,"coder_delegated")}catch{}session.currentTaskId=args2.task_id}if(args2.status==="in_progress")try{let evidencePath=path230.join(directory,".swarm","evidence",`${args2.task_id}.json`);fs148.mkdirSync(path230.dirname(evidencePath),{recursive:!0});let fd=fs148.openSync(evidencePath,"wx"),writeOk=!1;try{fs148.writeSync(fd,JSON.stringify({taskId:args2.task_id,required_gates:[],gates:{}},null,2)),writeOk=!0}finally{if(fs148.closeSync(fd),!writeOk)try{fs148.unlinkSync(evidencePath)}catch{}}}catch{}if(args2.status==="completed"){recoverTaskStateFromDelegations(args2.task_id,directory);let phaseRequiresReviewer=!0;try{let planPath2=path230.join(directory,".swarm","plan.json"),planRaw=fs148.readFileSync(planPath2,"utf-8"),taskPhase=JSON.parse(planRaw).phases.find((p)=>p.tasks.some((t)=>t.id===args2.task_id));if(taskPhase?.required_agents&&!taskPhase.required_agents.includes("reviewer"))phaseRequiresReviewer=!1}catch{}let councilCheck=checkCouncilGate(directory,args2.task_id);if(councilCheck.blocked)return{success:!1,message:"Gate check failed: council gate not yet satisfied for task "+args2.task_id,errors:[councilCheck.reason]};if(phaseRequiresReviewer&&!councilCheck.active){let reviewerCheck=await checkReviewerGateWithScope(args2.task_id,directory,ctx?.sessionID,fallbackDir);if(reviewerCheck.blocked)return{success:!1,message:"Gate check failed: required QA gates not yet satisfied for task "+args2.task_id,errors:[reviewerCheck.reason]}}}let lockTaskId=`update-task-status-${args2.task_id}-${Date.now()}`,planFilePath="plan.json",agentName="update-task-status";for(let[,agent]of swarmState.activeAgent){agentName=agent;break}let lockResult;try{lockResult=await _internals146.tryAcquireLock(directory,planFilePath,agentName,lockTaskId)}catch(error93){return{success:!1,message:"Failed to acquire lock for task status update",errors:[error93 instanceof Error?error93.message:String(error93)]}}if(!lockResult.acquired)return{success:!1,message:`Task status write blocked: plan.json is locked by ${lockResult.existing?.agent??"another agent"} (task: ${lockResult.existing?.taskId??"unknown"})`,errors:["Concurrent plan write detected — retry after the current write completes"],recovery_guidance:"Wait a moment and retry update_task_status. The lock will expire automatically if the holding agent fails."};try{let updatedPlan=await _internals146.updateTaskStatus(directory,args2.task_id,args2.status,{force:args2.force});if(args2.status==="completed")for(let[_sessionId,session]of swarmState.agentSessions){if(!(session.taskWorkflowStates instanceof Map))continue;if(getTaskState(session,args2.task_id)==="tests_run")try{advanceTaskState(session,args2.task_id,"complete")}catch{}}return{success:!0,message:"Task status updated successfully",task_id:args2.task_id,new_status:args2.status,current_phase:updatedPlan.current_phase}}catch(error93){return{success:!1,message:"Failed to update task status",errors:[error93 instanceof Error?error93.message:String(error93)]}}finally{if(lockResult?.acquired&&lockResult.lock._release)try{await lockResult.lock._release()}catch(releaseError){console.error("[update-task-status] Lock release failed:",releaseError)}}}var update_task_status=createSwarmTool({description:"Update the status of a specific task in the implementation plan. Task status can be one of: pending, in_progress, completed, blocked.",args:{task_id:exports_external.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/,"Task ID must be in N.M or N.M.P format").describe('Task ID in N.M format, e.g. "1.1", "1.2.3"'),status:exports_external.enum(["pending","in_progress","completed","blocked"]).describe("New status for the task: pending, in_progress, completed, or blocked"),working_directory:exports_external.string().optional().describe("Working directory where the plan is located"),force:exports_external.boolean().optional().default(!1).describe("Force override to permit re-opening a settled task (completed/blocked/failed) to in_progress. Use only for manual repair.")},execute:async(args2,_directory,_ctx)=>{return JSON.stringify(await executeUpdateTaskStatus(args2,_directory,_ctx),null,2)}});init_zod();init_loader();import{lookup}from"node:dns/promises";import*as http from"node:http";import*as https from"node:https";import{isIP}from"node:net";import{Readable}from"node:stream";import*as zlib from"node:zlib";init_utils2();init_redaction();import{createHash as createHash27}from"node:crypto";import{appendFile as appendFile19,mkdir as mkdir38}from"node:fs/promises";import*as path231 from"node:path";var EVIDENCE_CACHE_FILE="evidence-cache/documents.jsonl",MAX_EVIDENCE_TEXT_LENGTH=4000;async function writeEvidenceDocuments(directory,inputs,now=()=>new Date){let filePath=validateSwarmPath(directory,EVIDENCE_CACHE_FILE),capturedAt=now().toISOString(),records=inputs.map((input)=>createEvidenceDocumentRecord(input,capturedAt)).filter((record3)=>record3!==null);if(records.length>0)await mkdir38(path231.dirname(filePath),{recursive:!0}),await appendFile19(filePath,`${records.map((record3)=>JSON.stringify(record3)).join(`
|
|
6073
|
+
${scopeWarning}`:scopeWarning}}function recoverTaskStateFromDelegations(taskId,directory){let hasReviewer=!1,hasTestEngineer=!1;for(let[sessionId,chain]of swarmState.delegationChains){let session=swarmState.agentSessions.get(sessionId);if(session&&(session.currentTaskId===taskId||session.lastCoderDelegationTaskId===taskId))for(let delegation of chain){let target=stripKnownSwarmPrefix(delegation.to);if(target==="reviewer")hasReviewer=!0;if(target==="test_engineer")hasTestEngineer=!0}}let hasDurableIncompleteGates=!1;if(directory)try{let taskEvidence=readTaskEvidenceRaw(directory,taskId);if(taskEvidence?.gates&&Array.isArray(taskEvidence.required_gates)&&taskEvidence.required_gates.length>0){let gates=taskEvidence.gates;hasDurableIncompleteGates=taskEvidence.required_gates.some((g)=>gates[g]==null)}}catch{hasDurableIncompleteGates=!0}if(!hasDurableIncompleteGates&&(!hasReviewer||!hasTestEngineer))for(let[sessionId,chain]of swarmState.delegationChains){if(chain.some((d)=>stripKnownSwarmPrefix(d.to)==="coder"))continue;let chainSession=swarmState.agentSessions.get(sessionId);if(chainSession){let chainTaskId=chainSession.currentTaskId||chainSession.lastCoderDelegationTaskId;if(chainTaskId&&chainTaskId!==taskId)continue}for(let delegation of chain){let target=stripKnownSwarmPrefix(delegation.to);if(target==="reviewer")hasReviewer=!0;if(target==="test_engineer")hasTestEngineer=!0}}if((!hasReviewer||!hasTestEngineer)&&directory)try{let evidence=readTaskEvidenceRaw(directory,taskId);if(evidence?.gates&&Array.isArray(evidence.required_gates)){if(evidence.gates.reviewer!=null)hasReviewer=!0;if(evidence.gates.test_engineer!=null)hasTestEngineer=!0}}catch{}if(!hasReviewer&&!hasTestEngineer)return;if(swarmState.agentSessions.size===0)try{startAgentSession("recovery-session","architect")}catch{}for(let[,session]of swarmState.agentSessions){if(!(session.taskWorkflowStates instanceof Map))continue;let currentState=getTaskState(session,taskId);if(currentState==="tests_run"||currentState==="complete")continue;if(hasReviewer&¤tState==="idle")try{advanceTaskState(session,taskId,"coder_delegated")}catch{}if(hasReviewer)recordStageBCompletion(session,taskId,"reviewer");if(hasTestEngineer)recordStageBCompletion(session,taskId,"test_engineer");if(hasReviewer){let stateNow=getTaskState(session,taskId);if(stateNow==="coder_delegated"||stateNow==="pre_check_passed")try{advanceTaskState(session,taskId,"reviewer_run")}catch{}}if(hasTestEngineer){if(getTaskState(session,taskId)==="reviewer_run")try{advanceTaskState(session,taskId,"tests_run")}catch{}}}}function checkCouncilGate(workingDirectory,taskId){let councilEnabled=!1,effectiveMinimum=3;try{let config3=loadPluginConfig(workingDirectory);councilEnabled=config3.council?.enabled===!0,effectiveMinimum=config3.council?.requireAllMembers?5:config3.council?.minimumMembers??3}catch{return{blocked:!1,reason:"",active:!1}}if(!councilEnabled)return{blocked:!1,reason:"",active:!1};try{let planPath=path230.join(workingDirectory,".swarm","plan.json"),planRaw=fs148.readFileSync(planPath,"utf-8"),planObj=JSON.parse(planRaw);if(planObj.swarm&&planObj.title){let planId=derivePlanId(planObj),profile=getProfile(workingDirectory,planId);if(!profile||!profile.gates.council_mode)return{blocked:!1,reason:"",active:!1}}}catch{return{blocked:!1,reason:"",active:!1}}let evidence;try{evidence=readTaskEvidenceRaw(workingDirectory,taskId)}catch{return{blocked:!0,reason:"council gate required but not yet run — architect must call submit_council_verdicts before advancing this task",active:!0}}let councilGate=evidence?.gates?.council;if(!councilGate)return{blocked:!0,reason:"council gate required but not yet run — architect must call submit_council_verdicts before advancing this task",active:!0};if(councilGate.verdict==="REJECT")return{blocked:!0,reason:"council gate blocked advancement — resolve requiredFixes and re-run submit_council_verdicts",active:!0};let rawQuorumSize=councilGate.quorumSize,quorumSize=typeof rawQuorumSize==="number"&&Number.isFinite(rawQuorumSize)&&rawQuorumSize>=1?rawQuorumSize:1;if(quorumSize<effectiveMinimum)return{blocked:!0,reason:`council gate blocked advancement — recorded verdict has insufficient quorum (${quorumSize} of ${effectiveMinimum} required members). Re-run submit_council_verdicts with the missing council members.`,active:!0};return{blocked:!1,reason:"",active:!0}}async function executeUpdateTaskStatus(args2,fallbackDir,ctx){let statusError=validateStatus(args2.status);if(statusError)return{success:!1,message:"Validation failed",errors:[statusError]};let taskIdError=validateTaskId(args2.task_id);if(taskIdError)return{success:!1,message:"Validation failed",errors:[taskIdError]};let directory,resolveResult=_internals146.resolveWorkingDirectory(args2.working_directory,fallbackDir);if(!resolveResult.success)return{success:!1,message:resolveResult.message,errors:[resolveResult.message]};directory=resolveResult.directory;let planPath=path230.join(directory,".swarm","plan.json");if(!fs148.existsSync(planPath))return{success:!1,message:`Invalid working_directory: plan not found in "${directory}"`,errors:[`Invalid working_directory: plan not found in "${directory}"`]};if(fallbackDir&&directory!==fallbackDir){let canonicalDir=fs148.realpathSync(path230.resolve(directory)),canonicalRoot=fs148.realpathSync(path230.resolve(fallbackDir));if(canonicalDir.startsWith(canonicalRoot+path230.sep))return{success:!1,message:`Invalid working_directory: "${directory}" is a subdirectory of the project root "${fallbackDir}". Pass the project root path or omit working_directory entirely.`,errors:[`Subdirectory rejected: use project root "${fallbackDir}" instead`]}}let loadedPlan=null;try{loadedPlan=await _internals146.loadPlan(directory)}catch{loadedPlan=null}if(loadedPlan?._ledgerReplayStale===!0){let staleReason=loadedPlan._ledgerReplayStaleReason??"plan.json is stale relative to the authoritative ledger (.swarm/plan-ledger.jsonl)";return{success:!1,message:`Task status update refused: plan.json is stale relative to the ledger (ledger replay failed). ${staleReason}`,errors:[staleReason],recovery_guidance:"Plan state could not be reconciled with the authoritative ledger (.swarm/plan-ledger.jsonl). Restore from a critic-approved snapshot or re-run plan recovery to rebuild plan.json from the ledger, then retry update_task_status."}}if(args2.status==="in_progress"&&args2.force!==!0){let currentTask=loadedPlan?.phases.flatMap((p)=>p.tasks).find((t)=>t.id===args2.task_id);if(currentTask&¤tTask.status!=="pending"&¤tTask.status!=="in_progress")return{success:!1,message:`Task ${args2.task_id} is settled (${currentTask.status}); cannot re-open to in_progress. Use force:true only for manual repair.`,errors:[`Task ${args2.task_id} is settled (${currentTask.status}); cannot re-open to in_progress. Use force:true only for manual repair.`]}}if(args2.status==="in_progress"&&args2.force===!0)log(`[update-task-status] Force-override: re-opening settled task ${args2.task_id} to in_progress`);if(args2.status==="in_progress")for(let[_sessionId,session]of swarmState.agentSessions){if(getTaskState(session,args2.task_id)==="idle")try{advanceTaskState(session,args2.task_id,"coder_delegated")}catch{}session.currentTaskId=args2.task_id}if(args2.status==="in_progress")try{let evidencePath=path230.join(directory,".swarm","evidence",`${args2.task_id}.json`);fs148.mkdirSync(path230.dirname(evidencePath),{recursive:!0});let fd=fs148.openSync(evidencePath,"wx"),writeOk=!1;try{fs148.writeSync(fd,JSON.stringify({taskId:args2.task_id,required_gates:[],gates:{}},null,2)),writeOk=!0}finally{if(fs148.closeSync(fd),!writeOk)try{fs148.unlinkSync(evidencePath)}catch{}}}catch{}if(args2.status==="completed"){recoverTaskStateFromDelegations(args2.task_id,directory);let phaseRequiresReviewer=!0;try{let planPath2=path230.join(directory,".swarm","plan.json"),planRaw=fs148.readFileSync(planPath2,"utf-8"),taskPhase=JSON.parse(planRaw).phases.find((p)=>p.tasks.some((t)=>t.id===args2.task_id));if(taskPhase?.required_agents&&!taskPhase.required_agents.includes("reviewer"))phaseRequiresReviewer=!1}catch{}let councilCheck=checkCouncilGate(directory,args2.task_id);if(councilCheck.blocked)return{success:!1,message:"Gate check failed: council gate not yet satisfied for task "+args2.task_id,errors:[councilCheck.reason]};if(phaseRequiresReviewer&&!councilCheck.active){let reviewerCheck=await checkReviewerGateWithScope(args2.task_id,directory,ctx?.sessionID,fallbackDir);if(reviewerCheck.blocked)return{success:!1,message:"Gate check failed: required QA gates not yet satisfied for task "+args2.task_id,errors:[reviewerCheck.reason]}}}let lockTaskId=`update-task-status-${args2.task_id}-${Date.now()}`,planFilePath="plan.json",agentName="update-task-status";for(let[,agent]of swarmState.activeAgent){agentName=agent;break}let lockResult;try{lockResult=await _internals146.tryAcquireLock(directory,planFilePath,agentName,lockTaskId)}catch(error93){return{success:!1,message:"Failed to acquire lock for task status update",errors:[error93 instanceof Error?error93.message:String(error93)]}}if(!lockResult.acquired)return{success:!1,message:`Task status write blocked: plan.json is locked by ${lockResult.existing?.agent??"another agent"} (task: ${lockResult.existing?.taskId??"unknown"})`,errors:["Concurrent plan write detected — retry after the current write completes"],recovery_guidance:"Wait a moment and retry update_task_status. The lock will expire automatically if the holding agent fails."};try{let updatedPlan=await _internals146.updateTaskStatus(directory,args2.task_id,args2.status,{force:args2.force});if(args2.status==="completed")for(let[_sessionId,session]of swarmState.agentSessions){if(!(session.taskWorkflowStates instanceof Map))continue;if(getTaskState(session,args2.task_id)==="tests_run")try{advanceTaskState(session,args2.task_id,"complete")}catch{}}return{success:!0,message:"Task status updated successfully",task_id:args2.task_id,new_status:args2.status,current_phase:updatedPlan.current_phase}}catch(error93){return{success:!1,message:"Failed to update task status",errors:[error93 instanceof Error?error93.message:String(error93)]}}finally{if(lockResult?.acquired&&lockResult.lock._release)try{await lockResult.lock._release()}catch(releaseError){log("[update-task-status] Lock release failed:",releaseError)}}}var update_task_status=createSwarmTool({description:"Update the status of a specific task in the implementation plan. Task status can be one of: pending, in_progress, completed, blocked.",args:{task_id:exports_external.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/,"Task ID must be in N.M or N.M.P format").describe('Task ID in N.M format, e.g. "1.1", "1.2.3"'),status:exports_external.enum(["pending","in_progress","completed","blocked"]).describe("New status for the task: pending, in_progress, completed, or blocked"),working_directory:exports_external.string().optional().describe("Working directory where the plan is located"),force:exports_external.boolean().optional().default(!1).describe("Force override to permit re-opening a settled task (completed/blocked/failed) to in_progress. Use only for manual repair.")},execute:async(args2,_directory,_ctx)=>{return JSON.stringify(await executeUpdateTaskStatus(args2,_directory,_ctx),null,2)}});init_zod();init_loader();import{lookup}from"node:dns/promises";import*as http from"node:http";import*as https from"node:https";import{isIP}from"node:net";import{Readable}from"node:stream";import*as zlib from"node:zlib";init_utils2();init_redaction();import{createHash as createHash27}from"node:crypto";import{appendFile as appendFile19,mkdir as mkdir38}from"node:fs/promises";import*as path231 from"node:path";var EVIDENCE_CACHE_FILE="evidence-cache/documents.jsonl",MAX_EVIDENCE_TEXT_LENGTH=4000;async function writeEvidenceDocuments(directory,inputs,now=()=>new Date){let filePath=validateSwarmPath(directory,EVIDENCE_CACHE_FILE),capturedAt=now().toISOString(),records=inputs.map((input)=>createEvidenceDocumentRecord(input,capturedAt)).filter((record3)=>record3!==null);if(records.length>0)await mkdir38(path231.dirname(filePath),{recursive:!0}),await appendFile19(filePath,`${records.map((record3)=>JSON.stringify(record3)).join(`
|
|
6074
6074
|
`)}
|
|
6075
6075
|
`,"utf-8");return{path:".swarm/evidence-cache/documents.jsonl",records,refs:records.map((record3)=>record3.ref)}}function createEvidenceDocumentRecord(input,defaultCapturedAt){let text=normalizeEvidenceText(input.text??input.snippet??"");if(!text)return null;let capturedAt=input.capturedAt??defaultCapturedAt,base={sourceType:input.sourceType,query:normalizeOptional(input.query),title:normalizeOptional(input.title),url:normalizeOptional(input.url),text},id=createEvidenceDocumentId(base);return{id,ref:`evidence-cache:${id}`,...base,capturedAt,createdBy:normalizeOptional(input.createdBy),metadata:input.metadata??{}}}function createEvidenceDocumentId(input){return`evd_${createHash27("sha256").update([input.sourceType,input.query??"",input.title??"",input.url??"",input.text].join(`
|
|
6076
6076
|
`)).digest("hex").slice(0,16)}`}function normalizeEvidenceText(text){let normalized=redactSecrets(text.replace(/\s+/g," ").trim());return truncateEvidenceText(normalized,MAX_EVIDENCE_TEXT_LENGTH)}function truncateEvidenceText(text,maxLength){if(text.length<=maxLength)return text;let truncated=text.slice(0,maxLength),lastPlaceholderStart=truncated.lastIndexOf("[REDACTED:"),lastPlaceholderEnd=truncated.lastIndexOf("]");if(lastPlaceholderStart>lastPlaceholderEnd)return truncated.slice(0,lastPlaceholderStart).trimEnd();return truncated}function normalizeOptional(value){let normalized=value?.replace(/\s+/g," ").trim();return normalized?redactSecrets(normalized):void 0}init_create_tool();init_resolve_working_directory();var DEFAULT_MAX_BYTES=1e6,MAX_BYTES_HARD_CAP=5000000,DEFAULT_TIMEOUT_MS5=15000,MAX_TIMEOUT_MS3=30000,MAX_REDIRECTS=5,MAX_TEXT_LENGTH2=50000,ArgsSchema6=exports_external.object({url:exports_external.string().min(1).max(2048),max_bytes:exports_external.number().int().min(1024).max(MAX_BYTES_HARD_CAP).optional(),timeout_ms:exports_external.number().int().min(1000).max(MAX_TIMEOUT_MS3).optional(),working_directory:exports_external.string().optional()});function isBlockedAddress(address){let family=isIP(address);if(family===4)return isBlockedIPv4(address);if(family===6)return isBlockedIPv6(address);return!0}function isBlockedIPv4(address){let parts=address.split(".");if(parts.length!==4)return!0;let octets=parts.map((p)=>Number(p));if(octets.some((o)=>!Number.isInteger(o)||o<0||o>255))return!0;let[a,b]=octets;if(a===0)return!0;if(a===10)return!0;if(a===127)return!0;if(a===169&&b===254)return!0;if(a===172&&b>=16&&b<=31)return!0;if(a===192&&b===168)return!0;if(a===100&&b>=64&&b<=127)return!0;if(a===198&&(b===18||b===19))return!0;if(a===192&&b===0&&octets[2]===0)return!0;if(a===192&&b===0&&octets[2]===2)return!0;if(a===198&&b===51&&octets[2]===100)return!0;if(a===203&&b===0&&octets[2]===113)return!0;if(a===192&&b===88&&octets[2]===99)return!0;if(a>=224)return!0;return!1}function expandIPv6(input){let s=input.toLowerCase().split("%")[0];if(!s)return null;if(s.includes(".")){let colon=s.lastIndexOf(":");if(colon===-1)return null;let v4=s.slice(colon+1).split(".");if(v4.length!==4)return null;let o=v4.map((p)=>Number(p));if(o.some((n)=>!Number.isInteger(n)||n<0||n>255))return null;let h1=(o[0]<<8|o[1]).toString(16),h2=(o[2]<<8|o[3]).toString(16);s=`${s.slice(0,colon+1)}${h1}:${h2}`}let halves=s.split("::");if(halves.length>2)return null;let parseGroups=(part)=>{if(part==="")return[];let groups=part.split(":"),out=[];for(let g of groups){if(!/^[0-9a-f]{1,4}$/.test(g))return null;out.push(Number.parseInt(g,16))}return out},head2=parseGroups(halves[0]);if(head2===null)return null;if(halves.length===2){let tail2=parseGroups(halves[1]);if(tail2===null)return null;let missing=8-head2.length-tail2.length;if(missing<1)return null;return[...head2,...Array(missing).fill(0),...tail2]}return head2.length===8?head2:null}function isBlockedIPv6(raw){let h=expandIPv6(raw);if(!h)return!0;if(h.every((x)=>x===0))return!0;if(h.slice(0,7).every((x)=>x===0)&&h[7]===1)return!0;let mappedV4=h.slice(0,5).every((x)=>x===0)&&h[5]===65535,compatV4=h.slice(0,6).every((x)=>x===0)&&!(h[6]===0&&h[7]<=1);if(mappedV4||compatV4){let v4=`${h[6]>>8}.${h[6]&255}.${h[7]>>8}.${h[7]&255}`;return isBlockedIPv4(v4)}let first=h[0];if(first>=64512&&first<=65023)return!0;if(first>=65152&&first<=65215)return!0;if(first>=65280)return!0;return!1}async function validateFetchUrl(candidate,dnsLookup){let url3;try{url3=new URL(candidate)}catch{return{ok:!1,reason:"invalid_url",message:`Not a valid URL: ${candidate}`}}if(url3.protocol!=="http:"&&url3.protocol!=="https:")return{ok:!1,reason:"blocked_scheme",message:`Only http and https URLs are allowed (got "${url3.protocol}").`};let host=url3.hostname.replace(/^\[|\]$/g,"");if(isIP(host)){if(isBlockedAddress(host))return{ok:!1,reason:"blocked_host",message:`Refusing to fetch a private, loopback, or reserved address: ${host}`};return{ok:!0,url:url3,address:host}}let resolved;try{resolved=await dnsLookup(host,{all:!0})}catch(err2){return{ok:!1,reason:"dns_failure",message:`Could not resolve host "${host}": ${err2 instanceof Error?err2.message:String(err2)}`}}if(resolved.length===0)return{ok:!1,reason:"dns_failure",message:`Host "${host}" resolved to no addresses.`};for(let{address}of resolved)if(isBlockedAddress(address))return{ok:!1,reason:"blocked_host",message:`Host "${host}" resolves to a private, loopback, or reserved address (${address}).`};return{ok:!0,url:url3,address:resolved[0].address}}function isAllowedContentType(contentType){if(!contentType)return!0;let type=contentType.split(";")[0].trim().toLowerCase();if(type.startsWith("text/"))return!0;if(type==="application/json"||type==="application/xml")return!0;if(type==="application/xhtml+xml"||type.endsWith("+json")||type.endsWith("+xml"))return!0;return!1}function extractTitle(html){let lower=html.toLowerCase(),start=lower.indexOf("<title");if(start===-1)return;let tagEnd=lower.indexOf(">",start);if(tagEnd===-1)return;let contentStart=tagEnd+1,end=lower.indexOf("</title",contentStart);if(end===-1)return;let content=html.slice(contentStart,end);return decodeEntities(content.replace(/\s+/g," ").trim())||void 0}var NAMED_ENTITIES={amp:"&",lt:"<",gt:">",quot:'"',apos:"'",nbsp:" ","#39":"'"};function decodeEntities(text){return text.replace(/&(#x?[0-9a-f]+|[a-z]+);/gi,(whole,body)=>{let key=body.toLowerCase();if(key in NAMED_ENTITIES)return NAMED_ENTITIES[key];if(body.startsWith("#x")||body.startsWith("#X")){let code=Number.parseInt(body.slice(2),16);return Number.isFinite(code)?safeFromCodePoint(code):whole}if(body.startsWith("#")){let code=Number.parseInt(body.slice(1),10);return Number.isFinite(code)?safeFromCodePoint(code):whole}return whole})}function safeFromCodePoint(code){try{return String.fromCodePoint(code)}catch{return""}}function stripSpans(input,open4,close){let lower=input.toLowerCase(),out="",i=0;while(i<input.length){let start=lower.indexOf(open4,i);if(start===-1){out+=input.slice(i);break}out+=input.slice(i,start);let end=lower.indexOf(close,start+open4.length);if(end===-1)break;i=end+close.length}return out}function htmlToText(html){let withoutScripts=stripSpans(html,"<script","</script>");withoutScripts=stripSpans(withoutScripts,"<style","</style>"),withoutScripts=stripSpans(withoutScripts,"<noscript","</noscript>"),withoutScripts=stripSpans(withoutScripts,"<!--","-->");let noTags=withoutScripts.replace(/<\/(p|div|li|h[1-6]|tr|section|article|header|footer)>/gi,`
|
|
@@ -6079,7 +6079,7 @@ ${scopeWarning}`:scopeWarning}}function recoverTaskStateFromDelegations(taskId,d
|
|
|
6079
6079
|
`).replace(/\n{3,}/g,`
|
|
6080
6080
|
|
|
6081
6081
|
`).trim()}function makeAbortError(){try{return new DOMException("The operation was aborted","AbortError")}catch{let err2=Error("The operation was aborted");return err2.name="AbortError",err2}}function performHttpRequest(args2){let{url:url3,pinnedAddress,signal,headers}=args2,isHttps=url3.protocol==="https:",port=url3.port?Number(url3.port):isHttps?443:80,hostNoBrackets=url3.hostname.replace(/^\[|\]$/g,""),useSni=isHttps&&isIP(hostNoBrackets)===0,options={host:pinnedAddress,port,path:`${url3.pathname}${url3.search}`,method:"GET",headers:{Host:url3.host,...headers}};if(useSni)options.servername=url3.hostname;return new Promise((resolve92,reject)=>{let req,onResponse=(res)=>{let normHeaders={};for(let[key,value]of Object.entries(res.headers))normHeaders[key]=Array.isArray(value)?value[0]:value;res.on("error",()=>{}),resolve92({status:res.statusCode??0,headers:normHeaders,body:res,cancel:()=>req.destroy()})};req=isHttps?https.request(options,onResponse):http.request(options,onResponse);let onAbort=()=>req.destroy(makeAbortError());if(signal.aborted)req.destroy(makeAbortError());else signal.addEventListener("abort",onAbort,{once:!0});req.on("error",reject),req.end()})}async function boundedFetch(start,maxBytes,timeoutMs,deps){let current=start,controller=new AbortController,timer=setTimeout(()=>controller.abort(),timeoutMs);try{for(let hop=0;hop<=MAX_REDIRECTS;hop++){let raw;try{raw=await deps.httpRequest({url:current.url,pinnedAddress:current.address,signal:controller.signal,headers:{Accept:"text/html,application/xhtml+xml,text/plain,application/json;q=0.9,*/*;q=0.5"}})}catch(err2){if(controller.signal.aborted)return{ok:!1,reason:"timeout",message:`Fetch exceeded ${timeoutMs}ms for ${current.url.toString()}`};return{ok:!1,reason:"network_error",message:err2 instanceof Error?err2.message:String(err2)}}if(raw.status>=300&&raw.status<400){let location=raw.headers.location;if(raw.cancel?.(),!location)return{ok:!1,reason:"bad_redirect",message:`Redirect ${raw.status} with no Location header.`};let next;try{next=new URL(location,current.url)}catch{return{ok:!1,reason:"bad_redirect",message:`Invalid redirect target: ${location}`}}let revalidated=await validateFetchUrl(next.toString(),deps.dnsLookup);if(!revalidated.ok)return revalidated;if(hop===MAX_REDIRECTS)return{ok:!1,reason:"too_many_redirects",message:`Exceeded ${MAX_REDIRECTS} redirect hops.`};current={url:revalidated.url,address:revalidated.address};continue}if(raw.status<200||raw.status>=300)return raw.cancel?.(),{ok:!1,reason:"http_error",message:`HTTP ${raw.status} for ${current.url.toString()}`};let contentType=raw.headers["content-type"]??null;if(!isAllowedContentType(contentType))return raw.cancel?.(),{ok:!1,reason:"unsupported_content_type",message:`Refusing to read non-text content type "${contentType}".`};let activeBody=raw.body;if(raw.body!==null&&raw.body instanceof Readable){let encoding=(raw.headers["content-encoding"]??"").toLowerCase(),decoder=null;if(encoding==="gzip"||encoding==="x-gzip")decoder=raw.body.pipe(zlib.createGunzip());else if(encoding==="deflate")decoder=raw.body.pipe(zlib.createInflate());else if(encoding==="br")decoder=raw.body.pipe(zlib.createBrotliDecompress());if(decoder)decoder.on("error",()=>{}),activeBody=decoder}let body;try{body=await readBounded(activeBody,maxBytes)}catch(err2){if(raw.cancel?.(),controller.signal.aborted)return{ok:!1,reason:"timeout",message:`Fetch exceeded ${timeoutMs}ms while reading the body of ${current.url.toString()}`};return{ok:!1,reason:"network_error",message:err2 instanceof Error?err2.message:String(err2)}}return raw.cancel?.(),{ok:!0,outcome:{status:raw.status,finalUrl:current.url.toString(),contentType,bytes:body.bytes,truncated:body.truncated}}}return{ok:!1,reason:"too_many_redirects",message:`Exceeded ${MAX_REDIRECTS} redirect hops.`}}finally{clearTimeout(timer)}}async function readBounded(body,maxBytes){if(!body)return{bytes:new Uint8Array(0),truncated:!1};let chunks=[],received=0,truncated=!1;for await(let value of body){if(!value||value.byteLength===0)continue;if(chunks.push(value),received+=value.byteLength,received>maxBytes){truncated=!0;break}}let merged=new Uint8Array(Math.min(received,maxBytes)),offset=0;for(let chunk of chunks){if(offset>=merged.length)break;let slice=chunk.subarray(0,merged.length-offset);merged.set(slice,offset),offset+=slice.byteLength}return{bytes:merged,truncated}}var web_fetch=createSwarmTool({description:"Fetch the readable text of a single http(s) URL for architect-driven deep research (MODE: DEEP_RESEARCH). Returns decoded page text (HTML stripped to plain text), the document title, the final URL after redirects, and an evidence reference stored alongside web_search results. Use it to read primary sources that web_search only surfaces as snippets. Config-gated on council.general.enabled; no search API key required. Blocks private/loopback/link-local/metadata addresses (re-validated across redirects), enforces a timeout, and caps the response body size.",args:{url:exports_external.string().min(1).max(2048).describe("Absolute http(s) URL to fetch (1–2048 chars)."),max_bytes:exports_external.number().int().min(1024).max(MAX_BYTES_HARD_CAP).optional().describe(`Max decoded response bytes to read (1024..${MAX_BYTES_HARD_CAP}, default ${DEFAULT_MAX_BYTES}).`),timeout_ms:exports_external.number().int().min(1000).max(MAX_TIMEOUT_MS3).optional().describe(`Request timeout in ms (1000..${MAX_TIMEOUT_MS3}, default ${DEFAULT_TIMEOUT_MS5}).`),working_directory:exports_external.string().optional().describe("Project root for config resolution and evidence storage. Optional.")},execute:async(args2,directory)=>{let parsed=ArgsSchema6.safeParse(args2);if(!parsed.success){let fail={success:!1,reason:"invalid_args",message:parsed.error.issues.map((i)=>`${i.path.join(".")}: ${i.message}`).join("; ")};return JSON.stringify(fail,null,2)}let dirResult=resolveWorkingDirectory(parsed.data.working_directory,directory);if(!dirResult.success){let fail={success:!1,reason:"invalid_working_directory",message:dirResult.message};return JSON.stringify(fail,null,2)}let generalConfig=_internals147.loadPluginConfig(dirResult.directory).council?.general;if(!generalConfig||generalConfig.enabled!==!0)return JSON.stringify({success:!1,reason:"council_general_disabled",message:"web_fetch is disabled - set council.general.enabled: true in the resolved config: global ~/.config/opencode/opencode-swarm.json or project .opencode/opencode-swarm.json."},null,2);let validated=await validateFetchUrl(parsed.data.url,_internals147.dnsLookup);if(!validated.ok){let fail={success:!1,reason:validated.reason,message:validated.message};return JSON.stringify(fail,null,2)}let maxBytes=parsed.data.max_bytes??DEFAULT_MAX_BYTES,timeoutMs=parsed.data.timeout_ms??DEFAULT_TIMEOUT_MS5,result=await boundedFetch({url:validated.url,address:validated.address},maxBytes,timeoutMs,_internals147);if(!result.ok){let fail={success:!1,reason:result.reason,message:result.message};return JSON.stringify(fail,null,2)}let{outcome}=result,raw=new TextDecoder("utf-8",{fatal:!1}).decode(outcome.bytes),isHtml=(outcome.contentType??"").toLowerCase().includes("html")||/<html|<!doctype html/i.test(raw),title=isHtml?extractTitle(raw):void 0,bodyText=isHtml?htmlToText(raw):raw.replace(/\s*\n\s*/g,`
|
|
6082
|
-
`).trim(),text=bodyText.length>MAX_TEXT_LENGTH2?`${bodyText.slice(0,MAX_TEXT_LENGTH2)}…`:bodyText,textTruncated=outcome.truncated||bodyText.length>MAX_TEXT_LENGTH2,evidence=await captureFetchEvidence(dirResult.directory,outcome.finalUrl,title,text),ok2={success:!0,url:parsed.data.url,finalUrl:outcome.finalUrl,status:outcome.status,contentType:outcome.contentType??void 0,title,text,truncated:textTruncated,bytesReturned:outcome.bytes.byteLength,evidence};return JSON.stringify(ok2,null,2)}});async function captureFetchEvidence(directory,url3,title,text){try{let written=await _internals147.writeEvidenceDocuments(directory,[{sourceType:"crawl",url:url3,title,text,createdBy:"web_fetch"}]);return{stored:written.records.length>0,ref:written.refs[0],path:written.path}}catch(err2){return{stored:!1,error:err2 instanceof Error?err2.message:String(err2)}}}var _internals147={httpRequest:performHttpRequest,dnsLookup:lookup,loadPluginConfig,writeEvidenceDocuments};init_zod();init_loader();var CURRENT_INTENT_RE=/\b(?:latest|current|currently|today|now|newest|recent|recently|up\s*-?\s*to\s*-?\s*date|this\s+(?:week|month|year)|as\s+of\s+(?:today|now))\b/i,HISTORICAL_INTENT_RE=/\b(?:history|historical|archive|archived|in\s+20\d{2}|during\s+20\d{2}|from\s+20\d{2}|for\s+20\d{2}|as\s+of\s+20\d{2})\b/i;function applySearchQueryPolicy(rawQuery,now=new Date){let originalQuery=rawQuery,query=rawQuery.trim().replace(/\s+/g," "),currentYear=now.getUTCFullYear(),temporalIntent=detectTemporalIntent(query),removedStaleYears=[];if(temporalIntent==="current")query=removeTrailingStaleCutoffYears(query,currentYear,removedStaleYears);return{originalQuery,query,temporalIntent,freshness:temporalIntent==="current"?chooseFreshness(query):void 0,removedStaleYears}}function detectTemporalIntent(query){if(CURRENT_INTENT_RE.test(query))return"current";if(HISTORICAL_INTENT_RE.test(query))return"historical";return"unspecified"}function chooseFreshness(query){if(/\b(?:today|now|as\s+of\s+(?:today|now))\b/i.test(query))return"day";if(/\bthis\s+week\b/i.test(query))return"week";if(/\b(?:recent|recently|this\s+month)\b/i.test(query))return"month";return"year"}function removeTrailingStaleCutoffYears(query,currentYear,removed){return query.replace(/\s+(?:as\s+of\s+)?(20\d{2})\s*$/i,(match,year)=>{if(Number(year)>=currentYear)return match;return removed.push(year),""}).replace(/\s+/g," ").trim()}class WebSearchError extends Error{cause;constructor(message,cause){super(message);this.cause=cause;this.name="WebSearchError"}}class WebSearchConfigError extends Error{constructor(message){super(message);this.name="WebSearchConfigError"}}class TavilyProvider{apiKey;constructor(apiKey){this.apiKey=apiKey}async search(query,maxResults,options={}){let requestBody={api_key:this.apiKey,query,max_results:maxResults,search_depth:"advanced"};if(options.freshness)requestBody.time_range=options.freshness;let response;try{response=await fetch("https://api.tavily.com/search",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(requestBody)})}catch(err2){throw new WebSearchError(`Tavily network error for query "${query}"`,err2)}if(!response.ok)throw new WebSearchError(`Tavily HTTP ${response.status} for query "${query}"`);let body;try{body=await response.json()}catch(err2){throw new WebSearchError("Tavily returned non-JSON response",err2)}let results=body?.results;if(!Array.isArray(results))return[];return results.filter((r)=>typeof r?.title==="string"&&typeof r?.url==="string"&&typeof r?.content==="string").map((r)=>({title:r.title,url:r.url,snippet:r.content,query}))}}class BraveProvider{apiKey;constructor(apiKey){this.apiKey=apiKey}async search(query,maxResults,options={}){let url3=new URL("https://api.search.brave.com/res/v1/web/search");url3.searchParams.set("q",query),url3.searchParams.set("count",String(maxResults));let freshness=toBraveFreshness(options.freshness);if(freshness)url3.searchParams.set("freshness",freshness);let response;try{response=await fetch(url3.toString(),{method:"GET",headers:{"X-Subscription-Token":this.apiKey,Accept:"application/json"}})}catch(err2){throw new WebSearchError(`Brave network error for query "${query}"`,err2)}if(!response.ok)throw new WebSearchError(`Brave HTTP ${response.status} for query "${query}"`);let body;try{body=await response.json()}catch(err2){throw new WebSearchError("Brave returned non-JSON response",err2)}let results=body?.web?.results;if(!Array.isArray(results))return[];return results.filter((r)=>typeof r?.title==="string"&&typeof r?.url==="string"&&typeof r?.description==="string").map((r)=>({title:r.title,url:r.url,snippet:r.description,query}))}}function toBraveFreshness(freshness){switch(freshness){case"day":return"pd";case"week":return"pw";case"month":return"pm";case"year":return"py";default:return}}function resolveApiKey(provider,configKey){if(configKey&&configKey.length>0)return configKey;let envName=provider==="tavily"?"TAVILY_API_KEY":"BRAVE_SEARCH_API_KEY",fromEnv=process.env[envName];return fromEnv&&fromEnv.length>0?fromEnv:void 0}function createWebSearchProvider(config3){let apiKey=resolveApiKey(config3.searchProvider,config3.searchApiKey);if(!apiKey){let envName=config3.searchProvider==="tavily"?"TAVILY_API_KEY":"BRAVE_SEARCH_API_KEY";throw new WebSearchConfigError(`No API key for search provider "${config3.searchProvider}". Set council.general.searchApiKey in the resolved config (global ~/.config/opencode/opencode-swarm.json, project .opencode/opencode-swarm.json override) or export ${envName}.`)}switch(config3.searchProvider){case"tavily":return new TavilyProvider(apiKey);case"brave":return new BraveProvider(apiKey)}}init_create_tool();init_resolve_working_directory();var MAX_RESULTS_HARD_CAP=10,ArgsSchema7=exports_external.object({query:exports_external.string().min(1).max(500),max_results:exports_external.number().int().min(1).max(20).optional(),freshness:exports_external.enum(["auto","none","day","week","month","year"]).default("auto"),working_directory:exports_external.string().optional()}),web_search=createSwarmTool({description:"External web search for architect-driven council research, SME domain research, and skill-improver research. Returns titled results with snippets and URLs. Used by the architect in MODE: COUNCIL to gather a RESEARCH CONTEXT before dispatching council agents and by SME to evaluate external skill/source candidates. Normalizes current-intent queries, strips trailing stale cutoff years, and applies provider freshness filters by default. Requires council.general.enabled and a configured search API key (Tavily or Brave) in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides. max_results is capped at 10 with default from council.general.maxSourcesPerMember.",args:{query:exports_external.string().min(1).max(500).describe("Search query string (1–500 characters)."),freshness:exports_external.enum(["auto","none","day","week","month","year"]).optional().describe('Optional freshness filter. Query normalization always runs; "auto" infers provider freshness from current/recency terms, while "none" disables provider freshness filtering.'),max_results:exports_external.number().int().min(1).max(20).optional().describe(`Number of results to request (1–20). Hard-capped at ${MAX_RESULTS_HARD_CAP}. Defaults to council.general.maxSourcesPerMember.`),working_directory:exports_external.string().optional().describe("Project root for config resolution. Optional.")},execute:async(args2,directory)=>{let parsed=ArgsSchema7.safeParse(args2);if(!parsed.success){let fail={success:!1,reason:"invalid_args",message:parsed.error.issues.map((i)=>`${i.path.join(".")}: ${i.message}`).join("; ")};return JSON.stringify(fail,null,2)}let dirResult=resolveWorkingDirectory(parsed.data.working_directory,directory);if(!dirResult.success){let fail={success:!1,reason:"invalid_working_directory",message:dirResult.message};return JSON.stringify(fail,null,2)}let generalConfig=loadPluginConfig(dirResult.directory).council?.general;if(!generalConfig||generalConfig.enabled!==!0)return JSON.stringify({success:!1,reason:"council_general_disabled",message:"web_search is disabled - set council.general.enabled: true in the resolved config: global ~/.config/opencode/opencode-swarm.json or project .opencode/opencode-swarm.json."},null,2);let requested=parsed.data.max_results??generalConfig.maxSourcesPerMember,maxResults=Math.min(requested,MAX_RESULTS_HARD_CAP),policy=applySearchQueryPolicy(parsed.data.query),requestedFreshness=parsed.data.freshness??"auto",freshness=requestedFreshness==="auto"?policy.freshness:requestedFreshness==="none"?void 0:requestedFreshness,provider;try{provider=createWebSearchProvider(generalConfig)}catch(err2){let fail={success:!1,reason:err2 instanceof WebSearchConfigError?"missing_api_key":"provider_init_failed",message:err2 instanceof Error?err2.message:String(err2)};return JSON.stringify(fail,null,2)}try{let results=await provider.search(policy.query,maxResults,{freshness}),evidence=await captureSearchEvidence(dirResult.directory,policy.query,results),scannedResults=results.map(({title,url:url3,snippet})=>{let titleScan=scanExternalContent(title,{trustLevel:"low"}),snippetScan=scanExternalContent(snippet,{trustLevel:"low"}),threatLevel=titleScan.threatLevel==="error"||snippetScan.threatLevel==="error"?"error":titleScan.threatLevel==="warning"||snippetScan.threatLevel==="warning"?"warning":"none";return{title:titleScan.clean?title:titleScan.neutralized,url:url3,snippet:snippetScan.clean?snippet:snippetScan.neutralized,evidenceRef:evidence.refByUrl.get(url3),threatLevel}}),ok2={success:!0,query:policy.query,originalQuery:policy.originalQuery,temporalIntent:policy.temporalIntent,freshness,removedStaleYears:policy.removedStaleYears,totalResults:results.length,results:scannedResults,evidence:{stored:evidence.stored,path:evidence.path,refs:evidence.refs,error:evidence.error}};return JSON.stringify(ok2,null,2)}catch(err2){let fail={success:!1,reason:err2 instanceof WebSearchError?"search_failed":"unknown",message:err2 instanceof Error?err2.message:String(err2)};return JSON.stringify(fail,null,2)}}});async function captureSearchEvidence(directory,query,results){try{let written=await _internals148.writeEvidenceDocuments(directory,results.map((result)=>({sourceType:"web_search",query,title:result.title,url:result.url,snippet:result.snippet,createdBy:"web_search"}))),refByUrl=new Map;for(let record3 of written.records)if(record3.url)refByUrl.set(record3.url,record3.ref);return{stored:written.records.length>0,path:written.path,refs:written.refs,refByUrl}}catch(err2){return{stored:!1,refs:[],refByUrl:new Map,error:err2 instanceof Error?err2.message:String(err2)}}}var _internals148={writeEvidenceDocuments};init_zod();init_loader();init_schema();init_curator_llm_factory();init_knowledge_curator();init_skill_generator();init_schema3();init_store();init_create_tool();init_resolve_working_directory();import*as path232 from"node:path";var FindingSchema2=exports_external.object({severity:exports_external.enum(["low","medium","high","critical"]),category:exports_external.string().min(1),agents:exports_external.array(exports_external.string().min(1)).default([]),tasks:exports_external.array(exports_external.string().min(1)).default([]),evidence_refs:exports_external.array(exports_external.string().min(1)).default([]),description:exports_external.string().min(1),recommendation:exports_external.string().default("")}),KnowledgeRecommendationSchema2=exports_external.object({lesson:exports_external.string().min(1),target_agents:exports_external.array(exports_external.string().min(1)).default([]),confidence:exports_external.number().min(0).max(1).default(0.5),evidence_refs:exports_external.array(exports_external.string().min(1)).default([])}),ArgsSchema8=exports_external.object({phase:exports_external.number().int().min(0).max(999),verdict:exports_external.enum(["APPROVE","CONCERNS","REJECT"]),findings:exports_external.array(FindingSchema2).default([]),knowledge_recommendations:exports_external.array(KnowledgeRecommendationSchema2).default([]),working_directory:exports_external.string().optional(),provenance_agent_name:exports_external.string().min(1).optional(),provenance_session_id:exports_external.string().min(1).optional()}),write_architecture_supervisor_evidence=createSwarmTool({description:"Persist the architecture supervisor verdict for a phase. PREREQUISITE: dispatch critic_architecture_supervisor as an Agent task with the phase + agent summaries, collect its strict-JSON verdict (verdict/findings/knowledge_recommendations), then call this tool with those values. Writes .swarm/evidence/{phase}/"+"architecture-supervisor.json. This tool persists only — it does not contact the "+"supervisor. Architect-only; config-gated via architectural_supervision.enabled.",args:{phase:exports_external.number().int().min(0).max(999).describe("Phase number being reviewed."),verdict:exports_external.enum(["APPROVE","CONCERNS","REJECT"]).describe("Supervisor verdict."),findings:exports_external.array(FindingSchema2).optional().describe("System-level findings from the supervisor."),knowledge_recommendations:exports_external.array(KnowledgeRecommendationSchema2).optional().describe("Durable lessons proposed by the supervisor."),working_directory:exports_external.string().optional(),provenance_agent_name:exports_external.string().min(1).optional().describe("Agent name that produced this evidence (optional provenance)."),provenance_session_id:exports_external.string().min(1).optional().describe("Session ID of the agent that produced this evidence (optional provenance).")},execute:async(rawArgs,directory)=>{let parsed=ArgsSchema8.safeParse(rawArgs);if(!parsed.success)return JSON.stringify({success:!1,reason:"invalid arguments",errors:parsed.error.issues.map((i)=>({path:i.path.join("."),message:i.message}))},null,2);let args2=parsed.data,dirResult=resolveWorkingDirectory(args2.working_directory,directory);if(!dirResult.success)return JSON.stringify({success:!1,reason:dirResult.message},null,2);let provenance=args2.provenance_agent_name||args2.provenance_session_id?{agent_name:args2.provenance_agent_name,session_id:args2.provenance_session_id,captured_at:new Date().toISOString()}:void 0,report={schema_version:SUMMARY_SCHEMA_VERSION,phase:args2.phase,verdict:args2.verdict,findings:args2.findings,knowledge_recommendations:args2.knowledge_recommendations,created_at:new Date().toISOString(),...provenance?{provenance}:{}},evidencePath=writeSupervisorReport(dirResult.directory,report),knowledgeProposed=0,knowledgeReinforced=0,knowledgeQuarantined=0;try{let config3=loadPluginConfig(dirResult.directory);if(config3.architectural_supervision?.persist_knowledge_recommendations&&args2.knowledge_recommendations.length>0){let knowledgeConfig=KnowledgeConfigSchema.parse(config3.knowledge??{}),lessons=args2.knowledge_recommendations.map((r)=>r.lesson),result=await curateAndStoreSwarm(lessons,path232.basename(dirResult.directory),{phase_number:args2.phase},dirResult.directory,knowledgeConfig,{skipAutoPromotion:!0,llmDelegate:createCuratorLLMDelegate(dirResult.directory,"phase"),enrichmentQuota:{maxCalls:knowledgeConfig.enrichment.max_calls_per_day,window:knowledgeConfig.enrichment.quota_window}});knowledgeProposed=result.stored,knowledgeReinforced=result.reinforced,knowledgeQuarantined=result.quarantined}}catch{}let skillsProposed=0;try{let config3=loadPluginConfig(dirResult.directory),hasFailureLoop=args2.findings.some((f)=>f.category==="failure_loop");if(config3.architectural_supervision?.persist_knowledge_recommendations&&hasFailureLoop)skillsProposed=(await generateSkills({directory:dirResult.directory,mode:"draft"})).written.length}catch{}return JSON.stringify({success:!0,phase:args2.phase,verdict:args2.verdict,findings_count:args2.findings.length,knowledge_proposed:knowledgeProposed,knowledge_reinforced:knowledgeReinforced,knowledge_quarantined:knowledgeQuarantined,skills_proposed:skillsProposed,evidence_path:evidencePath},null,2)}});init_zod();init_qa_gate_profile();import fs149 from"node:fs";import path233 from"node:path";function normalizeVerdict2(verdict){if(!LIVE_VERDICT_SET_2.includes(verdict))throw Error(`Invalid verdict: must be 'APPROVED' or 'NEEDS_REVISION', got '${verdict}'`);switch(verdict){case"APPROVED":return"approved";case"NEEDS_REVISION":return"rejected";default:return verdict.toLowerCase()}}function normalizeVerdict4(verdict){if(!LIVE_VERDICT_SET_4.includes(verdict))throw Error(`Invalid verdict: must be 'PASS', 'WARN', 'FAIL', or 'SKIP', got '${verdict}'`);switch(verdict){case"PASS":return"pass";case"WARN":return"warn";case"FAIL":return"fail";case"SKIP":return"skip";default:return verdict.toLowerCase()}}var LIVE_VERDICT_SET_2=["APPROVED","NEEDS_REVISION"],LIVE_VERDICT_SET_4=["PASS","WARN","FAIL","SKIP"],VERDICT_SET_2=LIVE_VERDICT_SET_2,VERDICT_SET_4=LIVE_VERDICT_SET_4;function isAcceptedVerdict2(v){return LIVE_VERDICT_SET_2.includes(v)}function isAcceptedVerdict4(v){return LIVE_VERDICT_SET_4.includes(v)}init_utils2();init_ledger();init_manager();init_utils3();init_create_tool();async function executeWriteDriftEvidence(args2,directory){let phase=args2.phase;if(!Number.isInteger(phase)||phase<1)return JSON.stringify({success:!1,phase,message:"Invalid phase: must be a positive integer"},null,2);if(!isAcceptedVerdict2(args2.verdict))return JSON.stringify({success:!1,phase,message:"Invalid verdict: must be 'APPROVED' or 'NEEDS_REVISION'"},null,2);let summary=args2.summary;if(typeof summary!=="string"||summary.trim().length===0)return JSON.stringify({success:!1,phase,message:"Invalid summary: must be a non-empty string"},null,2);let normalizedVerdict=_internals149.normalizeVerdict2(args2.verdict),provenance=args2.provenanceAgentName||args2.provenanceSessionId?{agent_name:args2.provenanceAgentName,session_id:args2.provenanceSessionId,captured_at:new Date().toISOString()}:void 0,evidenceContent={entries:[{type:"drift-verification",verdict:normalizedVerdict,summary:summary.trim(),timestamp:new Date().toISOString(),requirementCoverage:args2.requirementCoverage,...provenance?{provenance}:{}}]},filename="drift-verifier.json",relativePath=path233.join("evidence",String(phase),filename),validatedPath;try{validatedPath=validateSwarmPath(directory,relativePath)}catch(error93){return JSON.stringify({success:!1,phase,message:error93 instanceof Error?error93.message:"Failed to validate path"},null,2)}let evidenceDir=path233.dirname(validatedPath);try{await fs149.promises.mkdir(evidenceDir,{recursive:!0});let tempPath=path233.join(evidenceDir,`.${filename}.tmp`);await fs149.promises.writeFile(tempPath,JSON.stringify(evidenceContent,null,2),"utf-8"),await fs149.promises.rename(tempPath,validatedPath);let snapshotInfo,snapshotError,qaProfileLocked,qaProfileLockError;if(normalizedVerdict==="approved")try{let currentPlan=await loadPlanJsonOnly(directory);if(currentPlan){let snapshotEvent=await takeSnapshotEvent(directory,currentPlan,{source:"critic_approved",approvalMetadata:{phase,verdict:"APPROVED",summary:summary.trim(),approved_at:new Date().toISOString()}});snapshotInfo={seq:snapshotEvent.seq,timestamp:snapshotEvent.timestamp};try{let planId=derivePlanId(currentPlan),locked=lockProfile(directory,planId,snapshotEvent.seq);qaProfileLocked={plan_id:planId,locked_at:locked.locked_at??"",locked_by_snapshot_seq:locked.locked_by_snapshot_seq??-1}}catch(lockErr){let msg=lockErr instanceof Error?lockErr.message:String(lockErr);if(!/No QA gate profile/i.test(msg))qaProfileLockError=msg,console.warn("[write_drift_evidence] QA gate profile lock failed:",msg)}}else snapshotError="plan.json not available for snapshot"}catch(err2){snapshotError=err2 instanceof Error?err2.message:String(err2),console.warn("[write_drift_evidence] critic-approved snapshot failed:",snapshotError)}return JSON.stringify({success:!0,phase,verdict:normalizedVerdict,message:`Drift evidence written to .swarm/evidence/${phase}/drift-verifier.json`,approvedSnapshot:snapshotInfo,snapshotError,qaProfileLocked,qaProfileLockError},null,2)}catch(error93){return JSON.stringify({success:!1,phase,message:error93 instanceof Error?error93.message:String(error93)},null,2)}}var _internals149={normalizeVerdict2,VERDICT_SET_2,isAcceptedVerdict2},write_drift_evidence=createSwarmTool({description:"Write drift verification evidence for a completed phase. Normalizes verdict (APPROVED->approved, NEEDS_REVISION->rejected) and writes a gate-contract formatted EvidenceBundle to .swarm/evidence/{phase}/drift-verifier.json. Use this after critic_drift_verifier delegation to persist the verification result.",args:{phase:exports_external.number().int().min(1).describe("The phase number for the drift verification (e.g., 1, 2, 3)"),verdict:exports_external.enum(VERDICT_SET_2).describe("Verdict of the drift verification: 'APPROVED' or 'NEEDS_REVISION'"),summary:exports_external.string().describe("Human-readable summary of the drift verification"),requirementCoverage:exports_external.string().optional().describe("Requirement coverage report from req_coverage tool (JSON string)"),provenanceAgentName:exports_external.string().min(1).optional().describe("Agent name that produced this evidence (optional provenance)"),provenanceSessionId:exports_external.string().min(1).optional().describe("Session ID of the agent that produced this evidence (optional provenance)")},execute:async(args2,directory)=>{let rawPhase=args2.phase!==void 0?Number(args2.phase):0;try{let writeDriftEvidenceArgs={phase:Number(args2.phase),verdict:String(args2.verdict),summary:String(args2.summary??""),requirementCoverage:args2.requirementCoverage!==void 0?String(args2.requirementCoverage):void 0,provenanceAgentName:args2.provenanceAgentName!==void 0?String(args2.provenanceAgentName):void 0,provenanceSessionId:args2.provenanceSessionId!==void 0?String(args2.provenanceSessionId):void 0};return await executeWriteDriftEvidence(writeDriftEvidenceArgs,directory)}catch(error93){return JSON.stringify({success:!1,phase:rawPhase,message:error93 instanceof Error?error93.message:"Unknown error"},null,2)}}});init_zod();init_loader();import fs150 from"node:fs";import path234 from"node:path";init_utils2();init_config2();init_gateway();init_reward_capture();init_ledger();init_manager();init_utils3();init_logger();init_create_tool();var FINAL_COUNCIL_MEMBERS=["critic","reviewer","sme","test_engineer","explorer"],VerdictSchema3=exports_external.object({agent:exports_external.enum(FINAL_COUNCIL_MEMBERS),verdict:exports_external.enum(["APPROVE","CONCERNS","REJECT"]),confidence:exports_external.number().min(0).max(1),findings:exports_external.array(exports_external.object({severity:exports_external.enum(["CRITICAL","HIGH","MEDIUM","LOW"]),category:exports_external.string().min(1),location:exports_external.string(),detail:exports_external.string(),evidence:exports_external.string()})),criteriaAssessed:exports_external.array(exports_external.string()),criteriaUnmet:exports_external.array(exports_external.string()),durationMs:exports_external.number().nonnegative()}),ArgsSchema9=exports_external.object({phase:exports_external.number().int().min(1).max(1000),projectSummary:exports_external.string().min(1),roundNumber:exports_external.number().int().min(1).max(10).optional(),verdicts:exports_external.array(VerdictSchema3).min(1).max(5)});function normalizeFinalVerdict(verdict,requiredFixesCount){if(verdict==="APPROVE")return"approved";if(verdict==="REJECT")return"rejected";return requiredFixesCount>0?"rejected":"concerns"}async function executeWriteFinalCouncilEvidence(args2,directory,ctx){let parsed=ArgsSchema9.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,reason:"invalid arguments",errors:parsed.error.issues.map((i)=>({path:i.path.join("."),message:i.message}))},null,2);let input=parsed.data,config3=loadPluginConfig(directory),requiredMembers=FINAL_COUNCIL_MEMBERS.length,distinctMembers=new Set(input.verdicts.map((v)=>v.agent)),membersVoted=[...distinctMembers],membersAbsent=FINAL_COUNCIL_MEMBERS.filter((m)=>!distinctMembers.has(m));if(membersVoted.length<requiredMembers)return JSON.stringify({success:!1,reason:"insufficient_quorum",message:`Final council quorum not met: ${membersVoted.length} of ${requiredMembers} required members provided verdicts. Members voted: [${membersVoted.join(", ")}]. Members absent: [${membersAbsent.join(", ")}]. Dispatch the absent council members with project-scoped context and collect their verdicts before calling write_final_council_evidence.`,membersVoted,membersAbsent,quorumRequired:requiredMembers},null,2);let synthesis=synthesizeFinalCouncilAdvisory(input.projectSummary.trim(),input.verdicts,input.roundNumber??1,config3.council);if(synthesis.overallVerdict==="CONCERNS"&&synthesis.blockingConcernsCount>0)return JSON.stringify({success:!1,reason:"blocking_concerns_unresolved",overallVerdict:synthesis.overallVerdict,blockingConcernsCount:synthesis.blockingConcernsCount,requiredFixes:synthesis.requiredFixes,unifiedFeedbackMd:synthesis.unifiedFeedbackMd,message:`Final council returned CONCERNS with ${synthesis.blockingConcernsCount} HIGH/CRITICAL finding(s) promoted to requiredFixes. These must be resolved before the project can close. Do NOT write evidence or proceed — address every requiredFix and resubmit.`},null,2);let plan=await loadPlan(directory);if(!plan)return JSON.stringify({success:!1,reason:"plan_not_found",message:"Cannot write final council evidence: plan.json not found. The plan must be loaded and available before writing final council evidence.",phase:input.phase,plan_id:"unknown"},null,2);let planId=derivePlanId(plan),planHash=computePlanHash(plan),planIdentityHash=derivePlanIdentityHash(plan),normalizedVerdict=normalizeFinalVerdict(synthesis.overallVerdict,synthesis.requiredFixes.length),evidenceEntry={type:"final-council",phase:input.phase,plan_id:planId,plan_hash:planHash,plan_identity_hash:planIdentityHash,verdict:normalizedVerdict,rawCouncilVerdict:synthesis.overallVerdict,quorumSize:synthesis.quorumSize,membersVoted,membersAbsent,requiredFixes:synthesis.requiredFixes,advisoryFindings:synthesis.advisoryFindings,advisoryNotes:synthesis.advisoryNotes,unresolvedConflicts:synthesis.unresolvedConflicts,roundNumber:synthesis.roundNumber,allCriteriaMet:synthesis.allCriteriaMet,memberVerdicts:synthesis.memberVerdicts,unifiedFeedbackMd:synthesis.unifiedFeedbackMd,projectSummary:synthesis.projectSummary,timestamp:synthesis.timestamp},filename="final-council.json",relativePath=path234.join("evidence",filename),validatedPath;try{validatedPath=validateSwarmPath(directory,relativePath)}catch(error93){return JSON.stringify({success:!1,phase:input.phase,message:error93 instanceof Error?error93.message:"Failed to validate path"},null,2)}let evidenceContent={entries:[evidenceEntry]},evidenceDir=path234.dirname(validatedPath);try{await fs150.promises.mkdir(evidenceDir,{recursive:!0});let tempPath=path234.join(evidenceDir,`.${filename}.tmp`);await fs150.promises.writeFile(tempPath,JSON.stringify(evidenceContent,null,2),"utf-8"),await fs150.promises.rename(tempPath,validatedPath);try{let memoryConfig=config3.memory;if(memoryConfig?.enabled===!0&&ctx?.sessionID){let provider=createConfiguredMemoryProvider(directory,memoryConfig);try{await applyCouncilReward(provider,{runId:ctx.sessionID,unitId:void 0,reward:COUNCIL_VERDICT_REWARDS[synthesis.overallVerdict],eta:memoryConfig.qLearning.learningRate,initialQValue:memoryConfig.qLearning.initialQValue,qLearning:memoryConfig.qLearning,timestamp:new Date().toISOString(),verdictLabel:synthesis.overallVerdict})}finally{await provider.close?.()}}}catch(rewardErr){warn(`[write-final-council-evidence] final council reward capture failed: ${rewardErr instanceof Error?rewardErr.message:String(rewardErr)}`)}return JSON.stringify({success:!0,phase:input.phase,overallVerdict:synthesis.overallVerdict,verdict:normalizedVerdict,vetoedBy:synthesis.vetoedBy,roundNumber:synthesis.roundNumber,allCriteriaMet:synthesis.allCriteriaMet,requiredFixesCount:synthesis.requiredFixes.length,advisoryFindingsCount:synthesis.advisoryFindings.length,unresolvedConflictsCount:synthesis.unresolvedConflicts.length,advisoryNotes:synthesis.advisoryNotes,membersVoted,membersAbsent,quorumSize:synthesis.quorumSize,quorumMet:!0,evidencePath:synthesis.evidencePath,unifiedFeedbackMd:synthesis.unifiedFeedbackMd,message:"Final council evidence written to .swarm/evidence/final-council.json"},null,2)}catch(error93){return JSON.stringify({success:!1,phase:input.phase,message:error93 instanceof Error?error93.message:String(error93)},null,2)}}var write_final_council_evidence=createSwarmTool({description:"Write final council evidence for a completed project. This is not General Council mode and does not use convene_general_council. PREREQUISITE: dispatch critic, reviewer, sme, test_engineer, and explorer as project-scoped Agent tasks, collect their CouncilMemberVerdict JSON, then call this tool to synthesize and persist .swarm/evidence/final-council.json.",args:{phase:exports_external.number().int().min(1).max(1000).describe("The final phase number for the project being reviewed"),projectSummary:exports_external.string().min(1).describe("Summary of the completed project and total work reviewed"),roundNumber:exports_external.number().int().min(1).max(10).optional().describe("1-indexed final council round number. Defaults to 1."),verdicts:exports_external.array(VerdictSchema3).min(1).max(5).describe("Collected CouncilMemberVerdict objects from critic, reviewer, sme, test_engineer, and explorer.")},execute:async(args2,directory,ctx)=>{let parsed=ArgsSchema9.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,reason:"invalid arguments",errors:parsed.error.issues.map((i)=>({path:i.path.join("."),message:i.message}))},null,2);return await executeWriteFinalCouncilEvidence(parsed.data,directory,ctx)}});init_zod();import fs151 from"node:fs";import path235 from"node:path";init_utils2();init_create_tool();async function executeWriteHallucinationEvidence(args2,directory){let phase=args2.phase;if(!Number.isInteger(phase)||phase<1)return JSON.stringify({success:!1,phase,message:"Invalid phase: must be a positive integer"},null,2);if(!isAcceptedVerdict2(args2.verdict))return JSON.stringify({success:!1,phase,message:"Invalid verdict: must be 'APPROVED' or 'NEEDS_REVISION'"},null,2);let summary=args2.summary;if(typeof summary!=="string"||summary.trim().length===0)return JSON.stringify({success:!1,phase,message:"Invalid summary: must be a non-empty string"},null,2);let normalizedVerdict=_internals150.normalizeVerdict2(args2.verdict),evidenceContent={entries:[{type:"hallucination-verification",verdict:normalizedVerdict,summary:summary.trim(),timestamp:new Date().toISOString(),findings:args2.findings}]},filename="hallucination-guard.json",relativePath=path235.join("evidence",String(phase),filename),validatedPath;try{validatedPath=validateSwarmPath(directory,relativePath)}catch(error93){return JSON.stringify({success:!1,phase,message:error93 instanceof Error?error93.message:"Failed to validate path"},null,2)}let evidenceDir=path235.dirname(validatedPath);try{await fs151.promises.mkdir(evidenceDir,{recursive:!0});let tempPath=path235.join(evidenceDir,`.${filename}.tmp`);return await fs151.promises.writeFile(tempPath,JSON.stringify(evidenceContent,null,2),"utf-8"),await fs151.promises.rename(tempPath,validatedPath),JSON.stringify({success:!0,phase,verdict:normalizedVerdict,message:`Hallucination evidence written to .swarm/evidence/${phase}/hallucination-guard.json`},null,2)}catch(error93){return JSON.stringify({success:!1,phase,message:error93 instanceof Error?error93.message:String(error93)},null,2)}}var _internals150={normalizeVerdict2,VERDICT_SET_2,isAcceptedVerdict2},write_hallucination_evidence=createSwarmTool({description:"Write hallucination verification evidence for a completed phase. Normalizes verdict (APPROVED->approved, NEEDS_REVISION->rejected) and writes a gate-contract formatted EvidenceBundle to .swarm/evidence/{phase}/hallucination-guard.json. Use this after critic_hallucination_verifier delegation to persist the verification result. Unlike write_drift_evidence, this tool does NOT lock the QA gate profile.",args:{phase:exports_external.number().int().min(1).describe("The phase number for the hallucination verification (e.g., 1, 2, 3)"),verdict:exports_external.enum(VERDICT_SET_2).describe("Verdict of the hallucination verification: 'APPROVED' or 'NEEDS_REVISION'"),summary:exports_external.string().describe("Human-readable summary of the hallucination verification"),findings:exports_external.string().optional().describe("Optional bullet list of FABRICATED/DRIFTED/UNSUPPORTED/BROKEN findings (for NEEDS_REVISION)")},execute:async(args2,directory)=>{let rawPhase=args2.phase!==void 0?Number(args2.phase):0;try{let typedArgs={phase:Number(args2.phase),verdict:String(args2.verdict),summary:String(args2.summary??""),findings:args2.findings!==void 0?String(args2.findings):void 0};return await executeWriteHallucinationEvidence(typedArgs,directory)}catch(error93){return JSON.stringify({success:!1,phase:rawPhase,message:error93 instanceof Error?error93.message:"Unknown error"},null,2)}}});init_zod();import fs152 from"node:fs";import path236 from"node:path";init_utils2();init_create_tool();async function executeWriteMutationEvidence(args2,directory){let phase=args2.phase;if(!Number.isInteger(phase)||phase<1)return JSON.stringify({success:!1,phase,message:"Invalid phase: must be a positive integer"},null,2);if(!isAcceptedVerdict4(args2.verdict))return JSON.stringify({success:!1,phase,message:"Invalid verdict: must be 'PASS', 'WARN', 'FAIL', or 'SKIP'"},null,2);if(args2.killRate!==void 0){if(typeof args2.killRate!=="number"||Number.isNaN(args2.killRate))return JSON.stringify({success:!1,phase,message:"Invalid killRate: must be a number"},null,2)}if(args2.adjustedKillRate!==void 0){if(typeof args2.adjustedKillRate!=="number"||Number.isNaN(args2.adjustedKillRate))return JSON.stringify({success:!1,phase,message:"Invalid adjustedKillRate: must be a number"},null,2)}let summary=args2.summary;if(typeof summary!=="string"||summary.trim().length===0)return JSON.stringify({success:!1,phase,message:"Invalid summary: must be a non-empty string"},null,2);let normalizedVerdict=_internals151.normalizeVerdict4(args2.verdict),evidenceEntry={type:"mutation-gate",verdict:normalizedVerdict,killRate:args2.killRate??0,adjustedKillRate:args2.adjustedKillRate??0,summary:summary.trim(),timestamp:new Date().toISOString()};if(args2.survivedMutants!==void 0)evidenceEntry.survivedMutants=args2.survivedMutants;let evidenceContent={entries:[evidenceEntry]},filename="mutation-gate.json",relativePath=path236.join("evidence",String(phase),filename),validatedPath;try{validatedPath=validateSwarmPath(directory,relativePath)}catch(error93){return JSON.stringify({success:!1,phase,message:error93 instanceof Error?error93.message:"Failed to validate path"},null,2)}let evidenceDir=path236.dirname(validatedPath);try{await fs152.promises.mkdir(evidenceDir,{recursive:!0});let tempPath=path236.join(evidenceDir,`.${filename}.tmp`);return await fs152.promises.writeFile(tempPath,JSON.stringify(evidenceContent,null,2),"utf-8"),await fs152.promises.rename(tempPath,validatedPath),JSON.stringify({success:!0,phase,verdict:normalizedVerdict,message:`Mutation gate evidence written to .swarm/evidence/${phase}/mutation-gate.json`},null,2)}catch(error93){return JSON.stringify({success:!1,phase,message:error93 instanceof Error?error93.message:String(error93)},null,2)}}var _internals151={normalizeVerdict4,VERDICT_SET_4,isAcceptedVerdict4},write_mutation_evidence=createSwarmTool({description:'Write mutation gate evidence for a completed phase. Accepts phase, verdict (PASS/WARN/FAIL/SKIP), killRate, adjustedKillRate, summary, and optional survivedMutants. Normalizes uppercase verdicts to lowercase (PASS→pass, WARN→warn, FAIL→fail, SKIP→skip) and writes entries[0].type="mutation-gate" to .swarm/evidence/{phase}/mutation-gate.json using atomic temp+rename write. Use this after mutation_test tool returns to persist the gate verdict.',args:{phase:exports_external.number().int().min(1).describe("The phase number for the mutation gate (e.g., 1, 2, 3)"),verdict:exports_external.enum(VERDICT_SET_4).describe("Verdict of the mutation gate: 'PASS', 'WARN', 'FAIL', or 'SKIP'"),killRate:exports_external.number().optional().describe("The raw kill rate (e.g., 0.85)"),adjustedKillRate:exports_external.number().optional().describe("The adjusted kill rate accounting for timeout survived mutants (e.g., 0.87)"),summary:exports_external.string().describe("Human-readable summary of the mutation gate result"),survivedMutants:exports_external.string().optional().describe("Optional JSON-serialized list of survived mutants")},execute:async(args2,directory)=>{let rawPhase=args2.phase!==void 0?Number(args2.phase):0;try{let typedArgs={phase:Number(args2.phase),verdict:String(args2.verdict),killRate:args2.killRate!==void 0?Number(args2.killRate):void 0,adjustedKillRate:args2.adjustedKillRate!==void 0?Number(args2.adjustedKillRate):void 0,summary:String(args2.summary??""),survivedMutants:args2.survivedMutants!==void 0?String(args2.survivedMutants):void 0};return await executeWriteMutationEvidence(typedArgs,directory)}catch(error93){return JSON.stringify({success:!1,phase:rawPhase,message:error93 instanceof Error?error93.message:"Unknown error"},null,2)}}});init_zod();init_utils2();init_create_tool();import{randomUUID as randomUUID15}from"node:crypto";import fs153 from"node:fs";import path237 from"node:path";var PR_REVIEW_TRIGGER_DEFINITIONS=[{id:"architect-prompts",trigger_row:"agents, prompts, templates, prompt interpolation, role text",micro_lane:"Architect prompt integrity"},{id:"council-orchestration",trigger_row:"council, verdict, quorum, veto, synthesis",micro_lane:"Council orchestration"},{id:"guardrail-bypass",trigger_row:"guardrail, gate, delegation, rate limit, approval checks",micro_lane:"Guardrail bypass paths"},{id:"evidence-schema",trigger_row:"schema, evidence, JSONL, migrations, serializers",micro_lane:"Evidence schema drift"},{id:"knowledge-contract",trigger_row:"knowledge, curator, hive, quarantine, memory",micro_lane:"Knowledge base contract"},{id:"phase-transitions",trigger_row:"phase, state, plan, .swarm/state, completion markers",micro_lane:"Phase transition validation"},{id:"model-role-mapping",trigger_row:"model, role, prefix, tool, agent config",micro_lane:"Model-to-role mapping"},{id:"config-ratchet",trigger_row:"config, defaults, ratchet, locks, policy flags",micro_lane:"Config ratchet semantics"},{id:"url-fetch",trigger_row:"url, fetch, http, GitHub PR/issue parsing, package fetch",micro_lane:"URL sanitization and external fetch"},{id:"git-safety",trigger_row:"git, branch, checkout, reset, worktree, .git",micro_lane:"Git safety"},{id:"shell-write",trigger_row:"shell, exec, command parser, file writes, delete/move/copy",micro_lane:"Shell/write authority and path containment"},{id:"test-infrastructure",trigger_row:"test, bun, mocks, fixtures, CI matrix",micro_lane:"Test infrastructure"},{id:"metrics-privacy",trigger_row:"metrics, telemetry, logs, serialized traces",micro_lane:"Metrics and evidence privacy"}],TriggerEvalRowSchema=exports_external.object({trigger_id:exports_external.string().min(1),result:exports_external.enum(["MATCHED","NO-MATCH"]),evidence:exports_external.string().trim().min(1).max(4000),source_batch_id:exports_external.string().trim().min(1).optional(),source_lane_id:exports_external.string().trim().min(1).optional()}).strict(),WritePrReviewTriggerEvalArgsSchema=exports_external.object({run_id:exports_external.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/,"run_id must be a safe relative identifier"),rows:exports_external.array(TriggerEvalRowSchema).min(1)}).strict();function failure(message){return JSON.stringify({success:!1,message},null,2)}async function executeWritePrReviewTriggerEval(args2,directory){let parsed=WritePrReviewTriggerEvalArgsSchema.safeParse(args2);if(!parsed.success)return failure(`Invalid trigger evaluation: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`);let expectedIds=new Set(PR_REVIEW_TRIGGER_DEFINITIONS.map((definition)=>definition.id)),seenIds=new Set,duplicateIds=new Set;for(let row of parsed.data.rows){if(seenIds.has(row.trigger_id))duplicateIds.add(row.trigger_id);seenIds.add(row.trigger_id)}if(duplicateIds.size>0)return failure(`duplicate trigger IDs: ${[...duplicateIds].join(", ")}`);let unknownIds=[...seenIds].filter((id)=>!expectedIds.has(id));if(unknownIds.length>0)return failure(`unknown trigger IDs: ${unknownIds.join(", ")}`);let missingIds=[...expectedIds].filter((id)=>!seenIds.has(id));if(missingIds.length>0)return failure(`missing trigger IDs: ${missingIds.join(", ")}`);let provenance=new Set;for(let row of parsed.data.rows)if(row.result==="MATCHED"){if(!row.source_batch_id||!row.source_lane_id)return failure(`MATCHED rows require source_batch_id and source_lane_id: ${row.trigger_id}`);let tuple3=`${row.source_batch_id}\x00${row.source_lane_id}`;if(provenance.has(tuple3))return failure(`MATCHED rows require unique dispatch provenance: ${row.trigger_id}`);provenance.add(tuple3)}else if(row.source_batch_id||row.source_lane_id)return failure(`NO-MATCH rows must not include dispatch provenance: ${row.trigger_id}`);let rowsById=new Map(parsed.data.rows.map((row)=>[row.trigger_id,row])),artifactRows=PR_REVIEW_TRIGGER_DEFINITIONS.map((definition)=>{let row=rowsById.get(definition.id);if(!row)throw Error(`Missing validated trigger row: ${definition.id}`);return{trigger_id:definition.id,trigger_row:definition.trigger_row,micro_lane:definition.micro_lane,result:row.result,evidence:row.evidence,...row.result==="MATCHED"?{source_batch_id:row.source_batch_id,source_lane_id:row.source_lane_id}:{}}}),matchedCount=artifactRows.filter((row)=>row.result==="MATCHED").length,artifact={schema_version:1,run_id:parsed.data.run_id,evaluated_at:new Date().toISOString(),trigger_count:artifactRows.length,matched_count:matchedCount,no_match_count:artifactRows.length-matchedCount,dispatched_micro_lane_count:matchedCount,rows:artifactRows},relativePath=path237.join("pr-review",parsed.data.run_id,"trigger-eval.json"),destination;try{destination=validateSwarmPath(directory,relativePath)}catch(error93){return failure(error93 instanceof Error?error93.message:String(error93))}let parent=path237.dirname(destination),tempPath=path237.join(parent,`.trigger-eval.${randomUUID15()}.tmp`);try{await fs153.promises.mkdir(parent,{recursive:!0}),await fs153.promises.writeFile(tempPath,`${JSON.stringify(artifact,null,2)}
|
|
6082
|
+
`).trim(),text=bodyText.length>MAX_TEXT_LENGTH2?`${bodyText.slice(0,MAX_TEXT_LENGTH2)}…`:bodyText,textTruncated=outcome.truncated||bodyText.length>MAX_TEXT_LENGTH2,evidence=await captureFetchEvidence(dirResult.directory,outcome.finalUrl,title,text),ok2={success:!0,url:parsed.data.url,finalUrl:outcome.finalUrl,status:outcome.status,contentType:outcome.contentType??void 0,title,text,truncated:textTruncated,bytesReturned:outcome.bytes.byteLength,evidence};return JSON.stringify(ok2,null,2)}});async function captureFetchEvidence(directory,url3,title,text){try{let written=await _internals147.writeEvidenceDocuments(directory,[{sourceType:"crawl",url:url3,title,text,createdBy:"web_fetch"}]);return{stored:written.records.length>0,ref:written.refs[0],path:written.path}}catch(err2){return{stored:!1,error:err2 instanceof Error?err2.message:String(err2)}}}var _internals147={httpRequest:performHttpRequest,dnsLookup:lookup,loadPluginConfig,writeEvidenceDocuments};init_zod();init_loader();var CURRENT_INTENT_RE=/\b(?:latest|current|currently|today|now|newest|recent|recently|up\s*-?\s*to\s*-?\s*date|this\s+(?:week|month|year)|as\s+of\s+(?:today|now))\b/i,HISTORICAL_INTENT_RE=/\b(?:history|historical|archive|archived|in\s+20\d{2}|during\s+20\d{2}|from\s+20\d{2}|for\s+20\d{2}|as\s+of\s+20\d{2})\b/i;function applySearchQueryPolicy(rawQuery,now=new Date){let originalQuery=rawQuery,query=rawQuery.trim().replace(/\s+/g," "),currentYear=now.getUTCFullYear(),temporalIntent=detectTemporalIntent(query),removedStaleYears=[];if(temporalIntent==="current")query=removeTrailingStaleCutoffYears(query,currentYear,removedStaleYears);return{originalQuery,query,temporalIntent,freshness:temporalIntent==="current"?chooseFreshness(query):void 0,removedStaleYears}}function detectTemporalIntent(query){if(CURRENT_INTENT_RE.test(query))return"current";if(HISTORICAL_INTENT_RE.test(query))return"historical";return"unspecified"}function chooseFreshness(query){if(/\b(?:today|now|as\s+of\s+(?:today|now))\b/i.test(query))return"day";if(/\bthis\s+week\b/i.test(query))return"week";if(/\b(?:recent|recently|this\s+month)\b/i.test(query))return"month";return"year"}function removeTrailingStaleCutoffYears(query,currentYear,removed){return query.replace(/\s+(?:as\s+of\s+)?(20\d{2})\s*$/i,(match,year)=>{if(Number(year)>=currentYear)return match;return removed.push(year),""}).replace(/\s+/g," ").trim()}class WebSearchError extends Error{cause;constructor(message,cause){super(message);this.cause=cause;this.name="WebSearchError"}}class WebSearchConfigError extends Error{constructor(message){super(message);this.name="WebSearchConfigError"}}class TavilyProvider{apiKey;constructor(apiKey){this.apiKey=apiKey}async search(query,maxResults,options={}){let requestBody={api_key:this.apiKey,query,max_results:maxResults,search_depth:"advanced"};if(options.freshness)requestBody.time_range=options.freshness;let response;try{response=await fetch("https://api.tavily.com/search",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(requestBody)})}catch(err2){throw new WebSearchError(`Tavily network error for query "${query}"`,err2)}if(!response.ok)throw new WebSearchError(`Tavily HTTP ${response.status} for query "${query}"`);let body;try{body=await response.json()}catch(err2){throw new WebSearchError("Tavily returned non-JSON response",err2)}let results=body?.results;if(!Array.isArray(results))return[];return results.filter((r)=>typeof r?.title==="string"&&typeof r?.url==="string"&&typeof r?.content==="string").map((r)=>({title:r.title,url:r.url,snippet:r.content,query}))}}class BraveProvider{apiKey;constructor(apiKey){this.apiKey=apiKey}async search(query,maxResults,options={}){let url3=new URL("https://api.search.brave.com/res/v1/web/search");url3.searchParams.set("q",query),url3.searchParams.set("count",String(maxResults));let freshness=toBraveFreshness(options.freshness);if(freshness)url3.searchParams.set("freshness",freshness);let response;try{response=await fetch(url3.toString(),{method:"GET",headers:{"X-Subscription-Token":this.apiKey,Accept:"application/json"}})}catch(err2){throw new WebSearchError(`Brave network error for query "${query}"`,err2)}if(!response.ok)throw new WebSearchError(`Brave HTTP ${response.status} for query "${query}"`);let body;try{body=await response.json()}catch(err2){throw new WebSearchError("Brave returned non-JSON response",err2)}let results=body?.web?.results;if(!Array.isArray(results))return[];return results.filter((r)=>typeof r?.title==="string"&&typeof r?.url==="string"&&typeof r?.description==="string").map((r)=>({title:r.title,url:r.url,snippet:r.description,query}))}}function toBraveFreshness(freshness){switch(freshness){case"day":return"pd";case"week":return"pw";case"month":return"pm";case"year":return"py";default:return}}function resolveApiKey(provider,configKey){if(configKey&&configKey.length>0)return configKey;let envName=provider==="tavily"?"TAVILY_API_KEY":"BRAVE_SEARCH_API_KEY",fromEnv=process.env[envName];return fromEnv&&fromEnv.length>0?fromEnv:void 0}function createWebSearchProvider(config3){let apiKey=resolveApiKey(config3.searchProvider,config3.searchApiKey);if(!apiKey){let envName=config3.searchProvider==="tavily"?"TAVILY_API_KEY":"BRAVE_SEARCH_API_KEY";throw new WebSearchConfigError(`No API key for search provider "${config3.searchProvider}". Set council.general.searchApiKey in the resolved config (global ~/.config/opencode/opencode-swarm.json, project .opencode/opencode-swarm.json override) or export ${envName}.`)}switch(config3.searchProvider){case"tavily":return new TavilyProvider(apiKey);case"brave":return new BraveProvider(apiKey)}}init_create_tool();init_resolve_working_directory();var MAX_RESULTS_HARD_CAP=10,ArgsSchema7=exports_external.object({query:exports_external.string().min(1).max(500),max_results:exports_external.number().int().min(1).max(20).optional(),freshness:exports_external.enum(["auto","none","day","week","month","year"]).default("auto"),working_directory:exports_external.string().optional()}),web_search=createSwarmTool({description:"External web search for architect-driven council research, SME domain research, and skill-improver research. Returns titled results with snippets and URLs. Used by the architect in MODE: COUNCIL to gather a RESEARCH CONTEXT before dispatching council agents and by SME to evaluate external skill/source candidates. Normalizes current-intent queries, strips trailing stale cutoff years, and applies provider freshness filters by default. Requires council.general.enabled and a configured search API key (Tavily or Brave) in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides. max_results is capped at 10 with default from council.general.maxSourcesPerMember.",args:{query:exports_external.string().min(1).max(500).describe("Search query string (1–500 characters)."),freshness:exports_external.enum(["auto","none","day","week","month","year"]).optional().describe('Optional freshness filter. Query normalization always runs; "auto" infers provider freshness from current/recency terms, while "none" disables provider freshness filtering.'),max_results:exports_external.number().int().min(1).max(20).optional().describe(`Number of results to request (1–20). Hard-capped at ${MAX_RESULTS_HARD_CAP}. Defaults to council.general.maxSourcesPerMember.`),working_directory:exports_external.string().optional().describe("Project root for config resolution. Optional.")},execute:async(args2,directory)=>{let parsed=ArgsSchema7.safeParse(args2);if(!parsed.success){let fail={success:!1,reason:"invalid_args",message:parsed.error.issues.map((i)=>`${i.path.join(".")}: ${i.message}`).join("; ")};return JSON.stringify(fail,null,2)}let dirResult=resolveWorkingDirectory(parsed.data.working_directory,directory);if(!dirResult.success){let fail={success:!1,reason:"invalid_working_directory",message:dirResult.message};return JSON.stringify(fail,null,2)}let generalConfig=loadPluginConfig(dirResult.directory).council?.general;if(!generalConfig||generalConfig.enabled!==!0)return JSON.stringify({success:!1,reason:"council_general_disabled",message:"web_search is disabled - set council.general.enabled: true in the resolved config: global ~/.config/opencode/opencode-swarm.json or project .opencode/opencode-swarm.json."},null,2);let requested=parsed.data.max_results??generalConfig.maxSourcesPerMember,maxResults=Math.min(requested,MAX_RESULTS_HARD_CAP),policy=applySearchQueryPolicy(parsed.data.query),requestedFreshness=parsed.data.freshness??"auto",freshness=requestedFreshness==="auto"?policy.freshness:requestedFreshness==="none"?void 0:requestedFreshness,provider;try{provider=createWebSearchProvider(generalConfig)}catch(err2){let fail={success:!1,reason:err2 instanceof WebSearchConfigError?"missing_api_key":"provider_init_failed",message:err2 instanceof Error?err2.message:String(err2)};return JSON.stringify(fail,null,2)}try{let results=await provider.search(policy.query,maxResults,{freshness}),evidence=await captureSearchEvidence(dirResult.directory,policy.query,results),scannedResults=results.map(({title,url:url3,snippet})=>{let titleScan=scanExternalContent(title,{trustLevel:"low"}),snippetScan=scanExternalContent(snippet,{trustLevel:"low"}),threatLevel=titleScan.threatLevel==="error"||snippetScan.threatLevel==="error"?"error":titleScan.threatLevel==="warning"||snippetScan.threatLevel==="warning"?"warning":"none";return{title:titleScan.clean?title:titleScan.neutralized,url:url3,snippet:snippetScan.clean?snippet:snippetScan.neutralized,evidenceRef:evidence.refByUrl.get(url3),threatLevel}}),ok2={success:!0,query:policy.query,originalQuery:policy.originalQuery,temporalIntent:policy.temporalIntent,freshness,removedStaleYears:policy.removedStaleYears,totalResults:results.length,results:scannedResults,evidence:{stored:evidence.stored,path:evidence.path,refs:evidence.refs,error:evidence.error}};return JSON.stringify(ok2,null,2)}catch(err2){let fail={success:!1,reason:err2 instanceof WebSearchError?"search_failed":"unknown",message:err2 instanceof Error?err2.message:String(err2)};return JSON.stringify(fail,null,2)}}});async function captureSearchEvidence(directory,query,results){try{let written=await _internals148.writeEvidenceDocuments(directory,results.map((result)=>({sourceType:"web_search",query,title:result.title,url:result.url,snippet:result.snippet,createdBy:"web_search"}))),refByUrl=new Map;for(let record3 of written.records)if(record3.url)refByUrl.set(record3.url,record3.ref);return{stored:written.records.length>0,path:written.path,refs:written.refs,refByUrl}}catch(err2){return{stored:!1,refs:[],refByUrl:new Map,error:err2 instanceof Error?err2.message:String(err2)}}}var _internals148={writeEvidenceDocuments};init_zod();init_loader();init_schema();init_curator_llm_factory();init_knowledge_curator();init_skill_generator();init_schema3();init_store();init_create_tool();init_resolve_working_directory();import*as path232 from"node:path";var FindingSchema2=exports_external.object({severity:exports_external.enum(["low","medium","high","critical"]),category:exports_external.string().min(1),agents:exports_external.array(exports_external.string().min(1)).default([]),tasks:exports_external.array(exports_external.string().min(1)).default([]),evidence_refs:exports_external.array(exports_external.string().min(1)).default([]),description:exports_external.string().min(1),recommendation:exports_external.string().default("")}),KnowledgeRecommendationSchema2=exports_external.object({lesson:exports_external.string().min(1),target_agents:exports_external.array(exports_external.string().min(1)).default([]),confidence:exports_external.number().min(0).max(1).default(0.5),evidence_refs:exports_external.array(exports_external.string().min(1)).default([])}),ArgsSchema8=exports_external.object({phase:exports_external.number().int().min(0).max(999),verdict:exports_external.enum(["APPROVE","CONCERNS","REJECT"]),findings:exports_external.array(FindingSchema2).default([]),knowledge_recommendations:exports_external.array(KnowledgeRecommendationSchema2).default([]),working_directory:exports_external.string().optional(),provenance_agent_name:exports_external.string().min(1).optional(),provenance_session_id:exports_external.string().min(1).optional()}),write_architecture_supervisor_evidence=createSwarmTool({description:"Persist the architecture supervisor verdict for a phase. PREREQUISITE: dispatch critic_architecture_supervisor as an Agent task with the phase + agent summaries, collect its strict-JSON verdict (verdict/findings/knowledge_recommendations), then call this tool with those values. Writes .swarm/evidence/{phase}/"+"architecture-supervisor.json. This tool persists only — it does not contact the "+"supervisor. Architect-only; config-gated via architectural_supervision.enabled.",args:{phase:exports_external.number().int().min(0).max(999).describe("Phase number being reviewed."),verdict:exports_external.enum(["APPROVE","CONCERNS","REJECT"]).describe("Supervisor verdict."),findings:exports_external.array(FindingSchema2).optional().describe("System-level findings from the supervisor."),knowledge_recommendations:exports_external.array(KnowledgeRecommendationSchema2).optional().describe("Durable lessons proposed by the supervisor."),working_directory:exports_external.string().optional(),provenance_agent_name:exports_external.string().min(1).optional().describe("Agent name that produced this evidence (optional provenance)."),provenance_session_id:exports_external.string().min(1).optional().describe("Session ID of the agent that produced this evidence (optional provenance).")},execute:async(rawArgs,directory)=>{let parsed=ArgsSchema8.safeParse(rawArgs);if(!parsed.success)return JSON.stringify({success:!1,reason:"invalid arguments",errors:parsed.error.issues.map((i)=>({path:i.path.join("."),message:i.message}))},null,2);let args2=parsed.data,dirResult=resolveWorkingDirectory(args2.working_directory,directory);if(!dirResult.success)return JSON.stringify({success:!1,reason:dirResult.message},null,2);let provenance=args2.provenance_agent_name||args2.provenance_session_id?{agent_name:args2.provenance_agent_name,session_id:args2.provenance_session_id,captured_at:new Date().toISOString()}:void 0,report={schema_version:SUMMARY_SCHEMA_VERSION,phase:args2.phase,verdict:args2.verdict,findings:args2.findings,knowledge_recommendations:args2.knowledge_recommendations,created_at:new Date().toISOString(),...provenance?{provenance}:{}},evidencePath=writeSupervisorReport(dirResult.directory,report),knowledgeProposed=0,knowledgeReinforced=0,knowledgeQuarantined=0;try{let config3=loadPluginConfig(dirResult.directory);if(config3.architectural_supervision?.persist_knowledge_recommendations&&args2.knowledge_recommendations.length>0){let knowledgeConfig=KnowledgeConfigSchema.parse(config3.knowledge??{}),lessons=args2.knowledge_recommendations.map((r)=>r.lesson),result=await curateAndStoreSwarm(lessons,path232.basename(dirResult.directory),{phase_number:args2.phase},dirResult.directory,knowledgeConfig,{skipAutoPromotion:!0,llmDelegate:createCuratorLLMDelegate(dirResult.directory,"phase"),enrichmentQuota:{maxCalls:knowledgeConfig.enrichment.max_calls_per_day,window:knowledgeConfig.enrichment.quota_window}});knowledgeProposed=result.stored,knowledgeReinforced=result.reinforced,knowledgeQuarantined=result.quarantined}}catch{}let skillsProposed=0;try{let config3=loadPluginConfig(dirResult.directory),hasFailureLoop=args2.findings.some((f)=>f.category==="failure_loop");if(config3.architectural_supervision?.persist_knowledge_recommendations&&hasFailureLoop)skillsProposed=(await generateSkills({directory:dirResult.directory,mode:"draft"})).written.length}catch{}return JSON.stringify({success:!0,phase:args2.phase,verdict:args2.verdict,findings_count:args2.findings.length,knowledge_proposed:knowledgeProposed,knowledge_reinforced:knowledgeReinforced,knowledge_quarantined:knowledgeQuarantined,skills_proposed:skillsProposed,evidence_path:evidencePath},null,2)}});init_zod();init_qa_gate_profile();import fs149 from"node:fs";import path233 from"node:path";function normalizeVerdict2(verdict){if(!LIVE_VERDICT_SET_2.includes(verdict))throw Error(`Invalid verdict: must be 'APPROVED' or 'NEEDS_REVISION', got '${verdict}'`);switch(verdict){case"APPROVED":return"approved";case"NEEDS_REVISION":return"rejected";default:return verdict.toLowerCase()}}function normalizeVerdict4(verdict){if(!LIVE_VERDICT_SET_4.includes(verdict))throw Error(`Invalid verdict: must be 'PASS', 'WARN', 'FAIL', or 'SKIP', got '${verdict}'`);switch(verdict){case"PASS":return"pass";case"WARN":return"warn";case"FAIL":return"fail";case"SKIP":return"skip";default:return verdict.toLowerCase()}}var LIVE_VERDICT_SET_2=["APPROVED","NEEDS_REVISION"],LIVE_VERDICT_SET_4=["PASS","WARN","FAIL","SKIP"],VERDICT_SET_2=LIVE_VERDICT_SET_2,VERDICT_SET_4=LIVE_VERDICT_SET_4;function isAcceptedVerdict2(v){return LIVE_VERDICT_SET_2.includes(v)}function isAcceptedVerdict4(v){return LIVE_VERDICT_SET_4.includes(v)}init_utils2();init_ledger();init_manager();init_utils3();init_logger();init_create_tool();async function executeWriteDriftEvidence(args2,directory){let phase=args2.phase;if(!Number.isInteger(phase)||phase<1)return JSON.stringify({success:!1,phase,message:"Invalid phase: must be a positive integer"},null,2);if(!isAcceptedVerdict2(args2.verdict))return JSON.stringify({success:!1,phase,message:"Invalid verdict: must be 'APPROVED' or 'NEEDS_REVISION'"},null,2);let summary=args2.summary;if(typeof summary!=="string"||summary.trim().length===0)return JSON.stringify({success:!1,phase,message:"Invalid summary: must be a non-empty string"},null,2);let normalizedVerdict=_internals149.normalizeVerdict2(args2.verdict),provenance=args2.provenanceAgentName||args2.provenanceSessionId?{agent_name:args2.provenanceAgentName,session_id:args2.provenanceSessionId,captured_at:new Date().toISOString()}:void 0,evidenceContent={entries:[{type:"drift-verification",verdict:normalizedVerdict,summary:summary.trim(),timestamp:new Date().toISOString(),requirementCoverage:args2.requirementCoverage,...provenance?{provenance}:{}}]},filename="drift-verifier.json",relativePath=path233.join("evidence",String(phase),filename),validatedPath;try{validatedPath=validateSwarmPath(directory,relativePath)}catch(error93){return JSON.stringify({success:!1,phase,message:error93 instanceof Error?error93.message:"Failed to validate path"},null,2)}let evidenceDir=path233.dirname(validatedPath);try{await fs149.promises.mkdir(evidenceDir,{recursive:!0});let tempPath=path233.join(evidenceDir,`.${filename}.tmp`);await fs149.promises.writeFile(tempPath,JSON.stringify(evidenceContent,null,2),"utf-8"),await fs149.promises.rename(tempPath,validatedPath);let snapshotInfo,snapshotError,qaProfileLocked,qaProfileLockError;if(normalizedVerdict==="approved")try{let currentPlan=await loadPlanJsonOnly(directory);if(currentPlan){let snapshotEvent=await takeSnapshotEvent(directory,currentPlan,{source:"critic_approved",approvalMetadata:{phase,verdict:"APPROVED",summary:summary.trim(),approved_at:new Date().toISOString()}});snapshotInfo={seq:snapshotEvent.seq,timestamp:snapshotEvent.timestamp};try{let planId=derivePlanId(currentPlan),locked=lockProfile(directory,planId,snapshotEvent.seq);qaProfileLocked={plan_id:planId,locked_at:locked.locked_at??"",locked_by_snapshot_seq:locked.locked_by_snapshot_seq??-1}}catch(lockErr){let msg=lockErr instanceof Error?lockErr.message:String(lockErr);if(!/No QA gate profile/i.test(msg))qaProfileLockError=msg,log("[write_drift_evidence] QA gate profile lock failed:",msg)}}else snapshotError="plan.json not available for snapshot"}catch(err2){snapshotError=err2 instanceof Error?err2.message:String(err2),log("[write_drift_evidence] critic-approved snapshot failed:",snapshotError)}return JSON.stringify({success:!0,phase,verdict:normalizedVerdict,message:`Drift evidence written to .swarm/evidence/${phase}/drift-verifier.json`,approvedSnapshot:snapshotInfo,snapshotError,qaProfileLocked,qaProfileLockError},null,2)}catch(error93){return JSON.stringify({success:!1,phase,message:error93 instanceof Error?error93.message:String(error93)},null,2)}}var _internals149={normalizeVerdict2,VERDICT_SET_2,isAcceptedVerdict2},write_drift_evidence=createSwarmTool({description:"Write drift verification evidence for a completed phase. Normalizes verdict (APPROVED->approved, NEEDS_REVISION->rejected) and writes a gate-contract formatted EvidenceBundle to .swarm/evidence/{phase}/drift-verifier.json. Use this after critic_drift_verifier delegation to persist the verification result.",args:{phase:exports_external.number().int().min(1).describe("The phase number for the drift verification (e.g., 1, 2, 3)"),verdict:exports_external.enum(VERDICT_SET_2).describe("Verdict of the drift verification: 'APPROVED' or 'NEEDS_REVISION'"),summary:exports_external.string().describe("Human-readable summary of the drift verification"),requirementCoverage:exports_external.string().optional().describe("Requirement coverage report from req_coverage tool (JSON string)"),provenanceAgentName:exports_external.string().min(1).optional().describe("Agent name that produced this evidence (optional provenance)"),provenanceSessionId:exports_external.string().min(1).optional().describe("Session ID of the agent that produced this evidence (optional provenance)")},execute:async(args2,directory)=>{let rawPhase=args2.phase!==void 0?Number(args2.phase):0;try{let writeDriftEvidenceArgs={phase:Number(args2.phase),verdict:String(args2.verdict),summary:String(args2.summary??""),requirementCoverage:args2.requirementCoverage!==void 0?String(args2.requirementCoverage):void 0,provenanceAgentName:args2.provenanceAgentName!==void 0?String(args2.provenanceAgentName):void 0,provenanceSessionId:args2.provenanceSessionId!==void 0?String(args2.provenanceSessionId):void 0};return await executeWriteDriftEvidence(writeDriftEvidenceArgs,directory)}catch(error93){return JSON.stringify({success:!1,phase:rawPhase,message:error93 instanceof Error?error93.message:"Unknown error"},null,2)}}});init_zod();init_loader();import fs150 from"node:fs";import path234 from"node:path";init_utils2();init_config2();init_gateway();init_reward_capture();init_ledger();init_manager();init_utils3();init_logger();init_create_tool();var FINAL_COUNCIL_MEMBERS=["critic","reviewer","sme","test_engineer","explorer"],VerdictSchema3=exports_external.object({agent:exports_external.enum(FINAL_COUNCIL_MEMBERS),verdict:exports_external.enum(["APPROVE","CONCERNS","REJECT"]),confidence:exports_external.number().min(0).max(1),findings:exports_external.array(exports_external.object({severity:exports_external.enum(["CRITICAL","HIGH","MEDIUM","LOW"]),category:exports_external.string().min(1),location:exports_external.string(),detail:exports_external.string(),evidence:exports_external.string()})),criteriaAssessed:exports_external.array(exports_external.string()),criteriaUnmet:exports_external.array(exports_external.string()),durationMs:exports_external.number().nonnegative()}),ArgsSchema9=exports_external.object({phase:exports_external.number().int().min(1).max(1000),projectSummary:exports_external.string().min(1),roundNumber:exports_external.number().int().min(1).max(10).optional(),verdicts:exports_external.array(VerdictSchema3).min(1).max(5)});function normalizeFinalVerdict(verdict,requiredFixesCount){if(verdict==="APPROVE")return"approved";if(verdict==="REJECT")return"rejected";return requiredFixesCount>0?"rejected":"concerns"}async function executeWriteFinalCouncilEvidence(args2,directory,ctx){let parsed=ArgsSchema9.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,reason:"invalid arguments",errors:parsed.error.issues.map((i)=>({path:i.path.join("."),message:i.message}))},null,2);let input=parsed.data,config3=loadPluginConfig(directory),requiredMembers=FINAL_COUNCIL_MEMBERS.length,distinctMembers=new Set(input.verdicts.map((v)=>v.agent)),membersVoted=[...distinctMembers],membersAbsent=FINAL_COUNCIL_MEMBERS.filter((m)=>!distinctMembers.has(m));if(membersVoted.length<requiredMembers)return JSON.stringify({success:!1,reason:"insufficient_quorum",message:`Final council quorum not met: ${membersVoted.length} of ${requiredMembers} required members provided verdicts. Members voted: [${membersVoted.join(", ")}]. Members absent: [${membersAbsent.join(", ")}]. Dispatch the absent council members with project-scoped context and collect their verdicts before calling write_final_council_evidence.`,membersVoted,membersAbsent,quorumRequired:requiredMembers},null,2);let synthesis=synthesizeFinalCouncilAdvisory(input.projectSummary.trim(),input.verdicts,input.roundNumber??1,config3.council);if(synthesis.overallVerdict==="CONCERNS"&&synthesis.blockingConcernsCount>0)return JSON.stringify({success:!1,reason:"blocking_concerns_unresolved",overallVerdict:synthesis.overallVerdict,blockingConcernsCount:synthesis.blockingConcernsCount,requiredFixes:synthesis.requiredFixes,unifiedFeedbackMd:synthesis.unifiedFeedbackMd,message:`Final council returned CONCERNS with ${synthesis.blockingConcernsCount} HIGH/CRITICAL finding(s) promoted to requiredFixes. These must be resolved before the project can close. Do NOT write evidence or proceed — address every requiredFix and resubmit.`},null,2);let plan=await loadPlan(directory);if(!plan)return JSON.stringify({success:!1,reason:"plan_not_found",message:"Cannot write final council evidence: plan.json not found. The plan must be loaded and available before writing final council evidence.",phase:input.phase,plan_id:"unknown"},null,2);let planId=derivePlanId(plan),planHash=computePlanHash(plan),planIdentityHash=derivePlanIdentityHash(plan),normalizedVerdict=normalizeFinalVerdict(synthesis.overallVerdict,synthesis.requiredFixes.length),evidenceEntry={type:"final-council",phase:input.phase,plan_id:planId,plan_hash:planHash,plan_identity_hash:planIdentityHash,verdict:normalizedVerdict,rawCouncilVerdict:synthesis.overallVerdict,quorumSize:synthesis.quorumSize,membersVoted,membersAbsent,requiredFixes:synthesis.requiredFixes,advisoryFindings:synthesis.advisoryFindings,advisoryNotes:synthesis.advisoryNotes,unresolvedConflicts:synthesis.unresolvedConflicts,roundNumber:synthesis.roundNumber,allCriteriaMet:synthesis.allCriteriaMet,memberVerdicts:synthesis.memberVerdicts,unifiedFeedbackMd:synthesis.unifiedFeedbackMd,projectSummary:synthesis.projectSummary,timestamp:synthesis.timestamp},filename="final-council.json",relativePath=path234.join("evidence",filename),validatedPath;try{validatedPath=validateSwarmPath(directory,relativePath)}catch(error93){return JSON.stringify({success:!1,phase:input.phase,message:error93 instanceof Error?error93.message:"Failed to validate path"},null,2)}let evidenceContent={entries:[evidenceEntry]},evidenceDir=path234.dirname(validatedPath);try{await fs150.promises.mkdir(evidenceDir,{recursive:!0});let tempPath=path234.join(evidenceDir,`.${filename}.tmp`);await fs150.promises.writeFile(tempPath,JSON.stringify(evidenceContent,null,2),"utf-8"),await fs150.promises.rename(tempPath,validatedPath);try{let memoryConfig=config3.memory;if(memoryConfig?.enabled===!0&&ctx?.sessionID){let provider=createConfiguredMemoryProvider(directory,memoryConfig);try{await applyCouncilReward(provider,{runId:ctx.sessionID,unitId:void 0,reward:COUNCIL_VERDICT_REWARDS[synthesis.overallVerdict],eta:memoryConfig.qLearning.learningRate,initialQValue:memoryConfig.qLearning.initialQValue,qLearning:memoryConfig.qLearning,timestamp:new Date().toISOString(),verdictLabel:synthesis.overallVerdict})}finally{await provider.close?.()}}}catch(rewardErr){warn(`[write-final-council-evidence] final council reward capture failed: ${rewardErr instanceof Error?rewardErr.message:String(rewardErr)}`)}return JSON.stringify({success:!0,phase:input.phase,overallVerdict:synthesis.overallVerdict,verdict:normalizedVerdict,vetoedBy:synthesis.vetoedBy,roundNumber:synthesis.roundNumber,allCriteriaMet:synthesis.allCriteriaMet,requiredFixesCount:synthesis.requiredFixes.length,advisoryFindingsCount:synthesis.advisoryFindings.length,unresolvedConflictsCount:synthesis.unresolvedConflicts.length,advisoryNotes:synthesis.advisoryNotes,membersVoted,membersAbsent,quorumSize:synthesis.quorumSize,quorumMet:!0,evidencePath:synthesis.evidencePath,unifiedFeedbackMd:synthesis.unifiedFeedbackMd,message:"Final council evidence written to .swarm/evidence/final-council.json"},null,2)}catch(error93){return JSON.stringify({success:!1,phase:input.phase,message:error93 instanceof Error?error93.message:String(error93)},null,2)}}var write_final_council_evidence=createSwarmTool({description:"Write final council evidence for a completed project. This is not General Council mode and does not use convene_general_council. PREREQUISITE: dispatch critic, reviewer, sme, test_engineer, and explorer as project-scoped Agent tasks, collect their CouncilMemberVerdict JSON, then call this tool to synthesize and persist .swarm/evidence/final-council.json.",args:{phase:exports_external.number().int().min(1).max(1000).describe("The final phase number for the project being reviewed"),projectSummary:exports_external.string().min(1).describe("Summary of the completed project and total work reviewed"),roundNumber:exports_external.number().int().min(1).max(10).optional().describe("1-indexed final council round number. Defaults to 1."),verdicts:exports_external.array(VerdictSchema3).min(1).max(5).describe("Collected CouncilMemberVerdict objects from critic, reviewer, sme, test_engineer, and explorer.")},execute:async(args2,directory,ctx)=>{let parsed=ArgsSchema9.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,reason:"invalid arguments",errors:parsed.error.issues.map((i)=>({path:i.path.join("."),message:i.message}))},null,2);return await executeWriteFinalCouncilEvidence(parsed.data,directory,ctx)}});init_zod();import fs151 from"node:fs";import path235 from"node:path";init_utils2();init_create_tool();async function executeWriteHallucinationEvidence(args2,directory){let phase=args2.phase;if(!Number.isInteger(phase)||phase<1)return JSON.stringify({success:!1,phase,message:"Invalid phase: must be a positive integer"},null,2);if(!isAcceptedVerdict2(args2.verdict))return JSON.stringify({success:!1,phase,message:"Invalid verdict: must be 'APPROVED' or 'NEEDS_REVISION'"},null,2);let summary=args2.summary;if(typeof summary!=="string"||summary.trim().length===0)return JSON.stringify({success:!1,phase,message:"Invalid summary: must be a non-empty string"},null,2);let normalizedVerdict=_internals150.normalizeVerdict2(args2.verdict),evidenceContent={entries:[{type:"hallucination-verification",verdict:normalizedVerdict,summary:summary.trim(),timestamp:new Date().toISOString(),findings:args2.findings}]},filename="hallucination-guard.json",relativePath=path235.join("evidence",String(phase),filename),validatedPath;try{validatedPath=validateSwarmPath(directory,relativePath)}catch(error93){return JSON.stringify({success:!1,phase,message:error93 instanceof Error?error93.message:"Failed to validate path"},null,2)}let evidenceDir=path235.dirname(validatedPath);try{await fs151.promises.mkdir(evidenceDir,{recursive:!0});let tempPath=path235.join(evidenceDir,`.${filename}.tmp`);return await fs151.promises.writeFile(tempPath,JSON.stringify(evidenceContent,null,2),"utf-8"),await fs151.promises.rename(tempPath,validatedPath),JSON.stringify({success:!0,phase,verdict:normalizedVerdict,message:`Hallucination evidence written to .swarm/evidence/${phase}/hallucination-guard.json`},null,2)}catch(error93){return JSON.stringify({success:!1,phase,message:error93 instanceof Error?error93.message:String(error93)},null,2)}}var _internals150={normalizeVerdict2,VERDICT_SET_2,isAcceptedVerdict2},write_hallucination_evidence=createSwarmTool({description:"Write hallucination verification evidence for a completed phase. Normalizes verdict (APPROVED->approved, NEEDS_REVISION->rejected) and writes a gate-contract formatted EvidenceBundle to .swarm/evidence/{phase}/hallucination-guard.json. Use this after critic_hallucination_verifier delegation to persist the verification result. Unlike write_drift_evidence, this tool does NOT lock the QA gate profile.",args:{phase:exports_external.number().int().min(1).describe("The phase number for the hallucination verification (e.g., 1, 2, 3)"),verdict:exports_external.enum(VERDICT_SET_2).describe("Verdict of the hallucination verification: 'APPROVED' or 'NEEDS_REVISION'"),summary:exports_external.string().describe("Human-readable summary of the hallucination verification"),findings:exports_external.string().optional().describe("Optional bullet list of FABRICATED/DRIFTED/UNSUPPORTED/BROKEN findings (for NEEDS_REVISION)")},execute:async(args2,directory)=>{let rawPhase=args2.phase!==void 0?Number(args2.phase):0;try{let typedArgs={phase:Number(args2.phase),verdict:String(args2.verdict),summary:String(args2.summary??""),findings:args2.findings!==void 0?String(args2.findings):void 0};return await executeWriteHallucinationEvidence(typedArgs,directory)}catch(error93){return JSON.stringify({success:!1,phase:rawPhase,message:error93 instanceof Error?error93.message:"Unknown error"},null,2)}}});init_zod();import fs152 from"node:fs";import path236 from"node:path";init_utils2();init_create_tool();async function executeWriteMutationEvidence(args2,directory){let phase=args2.phase;if(!Number.isInteger(phase)||phase<1)return JSON.stringify({success:!1,phase,message:"Invalid phase: must be a positive integer"},null,2);if(!isAcceptedVerdict4(args2.verdict))return JSON.stringify({success:!1,phase,message:"Invalid verdict: must be 'PASS', 'WARN', 'FAIL', or 'SKIP'"},null,2);if(args2.killRate!==void 0){if(typeof args2.killRate!=="number"||Number.isNaN(args2.killRate))return JSON.stringify({success:!1,phase,message:"Invalid killRate: must be a number"},null,2)}if(args2.adjustedKillRate!==void 0){if(typeof args2.adjustedKillRate!=="number"||Number.isNaN(args2.adjustedKillRate))return JSON.stringify({success:!1,phase,message:"Invalid adjustedKillRate: must be a number"},null,2)}let summary=args2.summary;if(typeof summary!=="string"||summary.trim().length===0)return JSON.stringify({success:!1,phase,message:"Invalid summary: must be a non-empty string"},null,2);let normalizedVerdict=_internals151.normalizeVerdict4(args2.verdict),evidenceEntry={type:"mutation-gate",verdict:normalizedVerdict,killRate:args2.killRate??0,adjustedKillRate:args2.adjustedKillRate??0,summary:summary.trim(),timestamp:new Date().toISOString()};if(args2.survivedMutants!==void 0)evidenceEntry.survivedMutants=args2.survivedMutants;let evidenceContent={entries:[evidenceEntry]},filename="mutation-gate.json",relativePath=path236.join("evidence",String(phase),filename),validatedPath;try{validatedPath=validateSwarmPath(directory,relativePath)}catch(error93){return JSON.stringify({success:!1,phase,message:error93 instanceof Error?error93.message:"Failed to validate path"},null,2)}let evidenceDir=path236.dirname(validatedPath);try{await fs152.promises.mkdir(evidenceDir,{recursive:!0});let tempPath=path236.join(evidenceDir,`.${filename}.tmp`);return await fs152.promises.writeFile(tempPath,JSON.stringify(evidenceContent,null,2),"utf-8"),await fs152.promises.rename(tempPath,validatedPath),JSON.stringify({success:!0,phase,verdict:normalizedVerdict,message:`Mutation gate evidence written to .swarm/evidence/${phase}/mutation-gate.json`},null,2)}catch(error93){return JSON.stringify({success:!1,phase,message:error93 instanceof Error?error93.message:String(error93)},null,2)}}var _internals151={normalizeVerdict4,VERDICT_SET_4,isAcceptedVerdict4},write_mutation_evidence=createSwarmTool({description:'Write mutation gate evidence for a completed phase. Accepts phase, verdict (PASS/WARN/FAIL/SKIP), killRate, adjustedKillRate, summary, and optional survivedMutants. Normalizes uppercase verdicts to lowercase (PASS→pass, WARN→warn, FAIL→fail, SKIP→skip) and writes entries[0].type="mutation-gate" to .swarm/evidence/{phase}/mutation-gate.json using atomic temp+rename write. Use this after mutation_test tool returns to persist the gate verdict.',args:{phase:exports_external.number().int().min(1).describe("The phase number for the mutation gate (e.g., 1, 2, 3)"),verdict:exports_external.enum(VERDICT_SET_4).describe("Verdict of the mutation gate: 'PASS', 'WARN', 'FAIL', or 'SKIP'"),killRate:exports_external.number().optional().describe("The raw kill rate (e.g., 0.85)"),adjustedKillRate:exports_external.number().optional().describe("The adjusted kill rate accounting for timeout survived mutants (e.g., 0.87)"),summary:exports_external.string().describe("Human-readable summary of the mutation gate result"),survivedMutants:exports_external.string().optional().describe("Optional JSON-serialized list of survived mutants")},execute:async(args2,directory)=>{let rawPhase=args2.phase!==void 0?Number(args2.phase):0;try{let typedArgs={phase:Number(args2.phase),verdict:String(args2.verdict),killRate:args2.killRate!==void 0?Number(args2.killRate):void 0,adjustedKillRate:args2.adjustedKillRate!==void 0?Number(args2.adjustedKillRate):void 0,summary:String(args2.summary??""),survivedMutants:args2.survivedMutants!==void 0?String(args2.survivedMutants):void 0};return await executeWriteMutationEvidence(typedArgs,directory)}catch(error93){return JSON.stringify({success:!1,phase:rawPhase,message:error93 instanceof Error?error93.message:"Unknown error"},null,2)}}});init_zod();init_utils2();init_create_tool();import{randomUUID as randomUUID15}from"node:crypto";import fs153 from"node:fs";import path237 from"node:path";var PR_REVIEW_TRIGGER_DEFINITIONS=[{id:"architect-prompts",trigger_row:"agents, prompts, templates, prompt interpolation, role text",micro_lane:"Architect prompt integrity"},{id:"council-orchestration",trigger_row:"council, verdict, quorum, veto, synthesis",micro_lane:"Council orchestration"},{id:"guardrail-bypass",trigger_row:"guardrail, gate, delegation, rate limit, approval checks",micro_lane:"Guardrail bypass paths"},{id:"evidence-schema",trigger_row:"schema, evidence, JSONL, migrations, serializers",micro_lane:"Evidence schema drift"},{id:"knowledge-contract",trigger_row:"knowledge, curator, hive, quarantine, memory",micro_lane:"Knowledge base contract"},{id:"phase-transitions",trigger_row:"phase, state, plan, .swarm/state, completion markers",micro_lane:"Phase transition validation"},{id:"model-role-mapping",trigger_row:"model, role, prefix, tool, agent config",micro_lane:"Model-to-role mapping"},{id:"config-ratchet",trigger_row:"config, defaults, ratchet, locks, policy flags",micro_lane:"Config ratchet semantics"},{id:"url-fetch",trigger_row:"url, fetch, http, GitHub PR/issue parsing, package fetch",micro_lane:"URL sanitization and external fetch"},{id:"git-safety",trigger_row:"git, branch, checkout, reset, worktree, .git",micro_lane:"Git safety"},{id:"shell-write",trigger_row:"shell, exec, command parser, file writes, delete/move/copy",micro_lane:"Shell/write authority and path containment"},{id:"test-infrastructure",trigger_row:"test, bun, mocks, fixtures, CI matrix",micro_lane:"Test infrastructure"},{id:"metrics-privacy",trigger_row:"metrics, telemetry, logs, serialized traces",micro_lane:"Metrics and evidence privacy"}],TriggerEvalRowSchema=exports_external.object({trigger_id:exports_external.string().min(1),result:exports_external.enum(["MATCHED","NO-MATCH"]),evidence:exports_external.string().trim().min(1).max(4000),source_batch_id:exports_external.string().trim().min(1).optional(),source_lane_id:exports_external.string().trim().min(1).optional()}).strict(),WritePrReviewTriggerEvalArgsSchema=exports_external.object({run_id:exports_external.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/,"run_id must be a safe relative identifier"),rows:exports_external.array(TriggerEvalRowSchema).min(1)}).strict();function failure(message){return JSON.stringify({success:!1,message},null,2)}async function executeWritePrReviewTriggerEval(args2,directory){let parsed=WritePrReviewTriggerEvalArgsSchema.safeParse(args2);if(!parsed.success)return failure(`Invalid trigger evaluation: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`);let expectedIds=new Set(PR_REVIEW_TRIGGER_DEFINITIONS.map((definition)=>definition.id)),seenIds=new Set,duplicateIds=new Set;for(let row of parsed.data.rows){if(seenIds.has(row.trigger_id))duplicateIds.add(row.trigger_id);seenIds.add(row.trigger_id)}if(duplicateIds.size>0)return failure(`duplicate trigger IDs: ${[...duplicateIds].join(", ")}`);let unknownIds=[...seenIds].filter((id)=>!expectedIds.has(id));if(unknownIds.length>0)return failure(`unknown trigger IDs: ${unknownIds.join(", ")}`);let missingIds=[...expectedIds].filter((id)=>!seenIds.has(id));if(missingIds.length>0)return failure(`missing trigger IDs: ${missingIds.join(", ")}`);let provenance=new Set;for(let row of parsed.data.rows)if(row.result==="MATCHED"){if(!row.source_batch_id||!row.source_lane_id)return failure(`MATCHED rows require source_batch_id and source_lane_id: ${row.trigger_id}`);let tuple3=`${row.source_batch_id}\x00${row.source_lane_id}`;if(provenance.has(tuple3))return failure(`MATCHED rows require unique dispatch provenance: ${row.trigger_id}`);provenance.add(tuple3)}else if(row.source_batch_id||row.source_lane_id)return failure(`NO-MATCH rows must not include dispatch provenance: ${row.trigger_id}`);let rowsById=new Map(parsed.data.rows.map((row)=>[row.trigger_id,row])),artifactRows=PR_REVIEW_TRIGGER_DEFINITIONS.map((definition)=>{let row=rowsById.get(definition.id);if(!row)throw Error(`Missing validated trigger row: ${definition.id}`);return{trigger_id:definition.id,trigger_row:definition.trigger_row,micro_lane:definition.micro_lane,result:row.result,evidence:row.evidence,...row.result==="MATCHED"?{source_batch_id:row.source_batch_id,source_lane_id:row.source_lane_id}:{}}}),matchedCount=artifactRows.filter((row)=>row.result==="MATCHED").length,artifact={schema_version:1,run_id:parsed.data.run_id,evaluated_at:new Date().toISOString(),trigger_count:artifactRows.length,matched_count:matchedCount,no_match_count:artifactRows.length-matchedCount,dispatched_micro_lane_count:matchedCount,rows:artifactRows},relativePath=path237.join("pr-review",parsed.data.run_id,"trigger-eval.json"),destination;try{destination=validateSwarmPath(directory,relativePath)}catch(error93){return failure(error93 instanceof Error?error93.message:String(error93))}let parent=path237.dirname(destination),tempPath=path237.join(parent,`.trigger-eval.${randomUUID15()}.tmp`);try{await fs153.promises.mkdir(parent,{recursive:!0}),await fs153.promises.writeFile(tempPath,`${JSON.stringify(artifact,null,2)}
|
|
6083
6083
|
`,{encoding:"utf-8",flag:"wx"}),await fs153.promises.rename(tempPath,destination)}catch(error93){return failure(`Failed to persist trigger evaluation: ${error93 instanceof Error?error93.message:String(error93)}`)}finally{await fs153.promises.rm(tempPath,{force:!0}).catch(()=>{return})}return JSON.stringify({success:!0,path:relativePath.split(path237.sep).join("/"),trigger_count:artifactRows.length,matched_count:matchedCount,no_match_count:artifactRows.length-matchedCount,dispatched_micro_lane_count:matchedCount},null,2)}var write_pr_review_trigger_eval=createSwarmTool({description:"Persist a complete, exact-set PR-review trigger ledger under .swarm/pr-review/<run_id>/trigger-eval.json.",args:{run_id:WritePrReviewTriggerEvalArgsSchema.shape.run_id,rows:WritePrReviewTriggerEvalArgsSchema.shape.rows},execute:executeWritePrReviewTriggerEval});init_write_retro();function defineHandlers(handlers){return handlers}var TOOL_MANIFEST=defineHandlers({diff:()=>diff,diff_summary:()=>diff_summary,syntax_check:()=>syntax_check,placeholder_scan:()=>placeholder_scan,imports:()=>imports,lint:()=>lint,secretscan:()=>secretscan,sast_scan:()=>sast_scan,build_check:()=>build_check,pre_check_batch:()=>pre_check_batch,quality_budget:()=>quality_budget,symbols:()=>symbols,complexity_hotspots:()=>complexity_hotspots,schema_drift:()=>schema_drift,todo_extract:()=>todo_extract,evidence_check:()=>evidence_check,check_gate_status:()=>check_gate_status,completion_verify:()=>completion_verify,submit_council_verdicts:()=>submit_council_verdicts,submit_phase_council_verdicts:()=>submit_phase_council_verdicts,declare_council_criteria:()=>declare_council_criteria,sbom_generate:()=>sbom_generate,checkpoint:()=>checkpoint,pkg_audit:()=>pkg_audit,parse_lane_candidates:()=>parse_lane_candidates,write_pr_review_trigger_eval:()=>write_pr_review_trigger_eval,test_runner:()=>test_runner,test_impact:()=>test_impact,mutation_test:()=>mutation_test,generate_mutants:()=>generate_mutants,detect_domains:()=>detect_domains,git_blame:()=>git_blame,gitingest:()=>gitingest,retrieve_summary:()=>retrieve_summary,retrieve_lane_output:()=>retrieve_lane_output,extract_code_blocks:()=>extract_code_blocks,phase_complete:()=>phase_complete,save_plan:()=>save_plan,update_task_status:()=>update_task_status,lint_spec:()=>lint_spec,write_retro:()=>write_retro,write_drift_evidence:()=>write_drift_evidence,write_hallucination_evidence:()=>write_hallucination_evidence,write_mutation_evidence:()=>write_mutation_evidence,declare_scope:()=>declare_scope,knowledge_query:()=>knowledge_query,doc_scan:()=>doc_scan,doc_extract:()=>doc_extract,curator_analyze:()=>curator_analyze,knowledge_add:()=>knowledge_add,knowledge_recall:()=>knowledge_recall,knowledge_remove:()=>knowledge_remove,co_change_analyzer:()=>co_change_analyzer,context_status:()=>context_status,search:()=>search,ast_grep:()=>ast_grep,actionlint_scan:()=>actionlint_scan,osv_scan:()=>osv_scan,gh_evidence:()=>gh_evidence,batch_symbols:()=>batch_symbols,suggest_patch:()=>suggestPatch,req_coverage:()=>req_coverage,get_approved_plan:()=>get_approved_plan,repo_map:()=>repo_map,get_qa_gate_profile:()=>get_qa_gate_profile,set_qa_gates:()=>set_qa_gates,web_search:()=>web_search,web_fetch:()=>web_fetch,convene_general_council:()=>convene_general_council,write_final_council_evidence:()=>write_final_council_evidence,skill_generate:()=>skill_generate,skill_list:()=>skill_list,skill_apply:()=>skill_apply,skill_inspect:()=>skill_inspect,run_stale_reconciliation:()=>run_stale_reconciliation,skill_regenerate:()=>skill_regenerate,skill_retire:()=>skill_retire,skill_improve:()=>skill_improve,spec_write:()=>spec_write,knowledge_receipt:()=>knowledge_receipt,knowledge_archive:()=>knowledge_archive,swarm_memory_recall:()=>swarm_memory_recall,swarm_memory_propose:()=>swarm_memory_propose,swarm_command:()=>swarm_command,dispatch_lanes:()=>dispatch_lanes,dispatch_lanes_async:()=>dispatch_lanes_async,collect_lane_results:()=>collect_lane_results,summarize_work:()=>summarize_work,write_architecture_supervisor_evidence:()=>write_architecture_supervisor_evidence,lean_turbo_plan_lanes:()=>lean_turbo_plan_lanes,lean_turbo_acquire_locks:()=>lean_turbo_acquire_locks,lean_turbo_runner_status:()=>lean_turbo_runner_status,lean_turbo_review:()=>lean_turbo_review,lean_turbo_run_phase:()=>lean_turbo_run_phase,lean_turbo_status:()=>lean_turbo_status,swarm_apply_patch:()=>swarmApplyPatch,external_skill_discover:()=>external_skill_discover,external_skill_list:()=>external_skill_list,external_skill_inspect:()=>external_skill_inspect,external_skill_promote:()=>external_skill_promote,external_skill_reject:()=>external_skill_reject,external_skill_delete:()=>external_skill_delete,external_skill_revoke:()=>external_skill_revoke,epic_decide_phase:()=>epic_decide_phase,epic_plan_waves:()=>epic_plan_waves,epic_record_divergence:()=>epic_record_divergence});function buildPluginToolObject(agents,config3){let tools={},knowledgeEnabled=config3?.knowledge?.enabled!==!1,knowledgeTools=new Set(["knowledge_add","knowledge_recall","knowledge_remove","knowledge_query","knowledge_receipt","knowledge_archive"]);for(let[name,handler]of Object.entries(TOOL_MANIFEST)){if(!knowledgeEnabled&&knowledgeTools.has(name))continue;tools[name]=handler()}return tools.swarm_command=createSwarmCommandTool(agents),tools}init_utils();function truncateToolOutput(output,maxLines,toolName,tailLines=10){if(!output)return output;if(tailLines>=maxLines)tailLines=Math.floor(maxLines/2);let lines=output.split(`
|
|
6084
6084
|
`);if(lines.length<=maxLines)return output;let omittedCount=lines.length-maxLines,headLines=lines.slice(0,maxLines-tailLines),tailContent=lines.slice(-tailLines),footerLines=[];if(footerLines.push(""),footerLines.push(`[... ${omittedCount} line${omittedCount===1?"":"s"} omitted ...]`),toolName)footerLines.push(`Tool: ${toolName}`);return footerLines.push("Use /swarm retrieve <id> to get the full content"),`${headLines.join(`
|
|
6085
6085
|
`)}
|