opencode-swarm 7.107.4 → 7.107.5
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-rb05fjjk.js → curator-k9swkynp.js} +3 -3
- package/dist/cli/{curator-llm-factory-abw56kg0.js → curator-llm-factory-ed67kywr.js} +3 -3
- package/dist/cli/{evidence-summary-service-nwdfnbz1.js → evidence-summary-service-6zsgw7x7.js} +2 -2
- package/dist/cli/{gate-evidence-ywys9vfs.js → gate-evidence-pgr7d942.js} +1 -1
- package/dist/cli/{guardrail-explain-dayy7zw4.js → guardrail-explain-vd6da30t.js} +4 -4
- package/dist/cli/{hive-promoter-34bdmw1w.js → hive-promoter-gh0nva5c.js} +3 -3
- package/dist/cli/{index-r8f89sm9.js → index-0kxc7t16.js} +2 -1
- package/dist/cli/{index-9b7a6agd.js → index-6h82c2h0.js} +25 -8
- package/dist/cli/{index-f45hbd5x.js → index-jrka8jd4.js} +1 -1
- package/dist/cli/{index-gyzxeza3.js → index-vzq4h90s.js} +10 -10
- package/dist/cli/{index-19vxtwa6.js → index-w1tvqh4x.js} +4 -4
- package/dist/cli/index.js +3 -3
- package/dist/index.js +12 -12
- 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.107.4",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",".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/design-docs",".opencode/skills/swarm-pr-review",".opencode/skills/swarm-pr-feedback",".opencode/skills/swarm-pr-subscribe",".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","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 .","drift:check":"bun run scripts/drift-check.ts",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","critic_oversight","explorer","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","critic_oversight","explorer","coder","test_engineer"]},complexity_hotspots:{description:"git churn × complexity risk map",agents:["architect","sme","researcher","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","reviewer","critic","critic_oversight","explorer","test_engineer"]},schema_drift:{description:"OpenAPI spec vs route drift",agents:["architect","sme","researcher","docs","explorer"]},todo_extract:{description:"structured TODO/FIXME extraction",agents:["architect","researcher","docs","explorer"]},evidence_check:{description:"verify task evidence completeness",agents:["architect","critic_oversight"]},check_gate_status:{description:"check the gate status of a specific task",agents:["architect","critic_oversight"]},completion_verify:{description:"verify completed tasks have required evidence",agents:["architect","critic_oversight"]},submit_council_verdicts:{description:"submit pre-collected council member verdicts for synthesis (architect MUST dispatch critic/reviewer/sme/test_engineer/explorer as Agent tasks first; this tool synthesizes only, it does not contact members)",agents:[]},submit_phase_council_verdicts:{description:"submit pre-collected phase-level council member verdicts for holistic phase synthesis (architect MUST dispatch all 5 council members with phase-scoped context first; this tool synthesizes only, it does not contact members)",agents:[]},declare_council_criteria:{description:"pre-declare acceptance criteria for a task before the coder starts work; criteria are read back during council evaluation",agents:[]},sbom_generate:{description:"SBOM generation for dependency inventory",agents:["architect"]},checkpoint:{description:"create named git checkpoints for save, restore, and delete — use before risky operations to enable rollback",agents:["architect"]},pkg_audit:{description:"dependency vulnerability scan — npm/pip/cargo",agents:["architect","critic_hallucination_verifier","reviewer","critic_oversight","test_engineer"]},parse_lane_candidates:{description:"Parse [CANDIDATE] rows from a dispatch_lanes or collect_lane_results artifact (by output_ref), produce structured records with provenance, optionally persist to a per-batch sidecar JSONL. Pure-parser variant exists as internal module.",agents:["architect"]},test_runner:{description:"auto-detect and run tests",agents:["architect","reviewer","test_engineer"]},test_impact:{description:"identify test files impacted by changed source files via import analysis",agents:["architect","reviewer","critic_oversight","test_engineer"]},mutation_test:{description:"executes pre-generated mutation patches against tests, evaluates kill rate against quality gate thresholds",agents:["architect","test_engineer"]},generate_mutants:{description:"generate LLM-based mutation testing patches for source files; returns MutationPatch[] for direct consumption by the mutation_test tool",agents:["architect"]},detect_domains:{description:"detect which SME domains are relevant for a given text",agents:["architect","sme","docs","docs_design","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","critic","critic_oversight","explorer"]},git_blame:{description:"per-line git blame metadata: sha, author, date, summary for each line in a file",agents:["reviewer","explorer","architect"]},gitingest:{description:"fetch a GitHub repository full content via gitingest.com",agents:["architect","docs","explorer"]},retrieve_summary:{description:"retrieve the full content of a stored tool output summary",agents:["architect","sme","docs","docs_design","designer","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","critic_architecture_supervisor","spec_writer","reviewer","critic","critic_oversight","explorer","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:["architect","sme","docs","docs_design","designer","spec_writer","reviewer","explorer","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","coder"]},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.107.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",".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/design-docs",".opencode/skills/swarm-pr-review",".opencode/skills/swarm-pr-feedback",".opencode/skills/swarm-pr-subscribe",".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","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 .","drift:check":"bun run scripts/drift-check.ts",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","critic_oversight","explorer","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","critic_oversight","explorer","coder","test_engineer"]},complexity_hotspots:{description:"git churn × complexity risk map",agents:["architect","sme","researcher","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","reviewer","critic","critic_oversight","explorer","test_engineer"]},schema_drift:{description:"OpenAPI spec vs route drift",agents:["architect","sme","researcher","docs","explorer"]},todo_extract:{description:"structured TODO/FIXME extraction",agents:["architect","researcher","docs","explorer"]},evidence_check:{description:"verify task evidence completeness",agents:["architect","critic_oversight"]},check_gate_status:{description:"check the gate status of a specific task",agents:["architect","critic_oversight"]},completion_verify:{description:"verify completed tasks have required evidence",agents:["architect","critic_oversight"]},submit_council_verdicts:{description:"submit pre-collected council member verdicts for synthesis (architect MUST dispatch critic/reviewer/sme/test_engineer/explorer as Agent tasks first; this tool synthesizes only, it does not contact members)",agents:[]},submit_phase_council_verdicts:{description:"submit pre-collected phase-level council member verdicts for holistic phase synthesis (architect MUST dispatch all 5 council members with phase-scoped context first; this tool synthesizes only, it does not contact members)",agents:[]},declare_council_criteria:{description:"pre-declare acceptance criteria for a task before the coder starts work; criteria are read back during council evaluation",agents:[]},sbom_generate:{description:"SBOM generation for dependency inventory",agents:["architect"]},checkpoint:{description:"create named git checkpoints for save, restore, and delete — use before risky operations to enable rollback",agents:["architect"]},pkg_audit:{description:"dependency vulnerability scan — npm/pip/cargo",agents:["architect","critic_hallucination_verifier","reviewer","critic_oversight","test_engineer"]},parse_lane_candidates:{description:"Parse [CANDIDATE] rows from a dispatch_lanes or collect_lane_results artifact (by output_ref), produce structured records with provenance, optionally persist to a per-batch sidecar JSONL. Pure-parser variant exists as internal module.",agents:["architect"]},test_runner:{description:"auto-detect and run tests",agents:["architect","reviewer","test_engineer"]},test_impact:{description:"identify test files impacted by changed source files via import analysis",agents:["architect","reviewer","critic_oversight","test_engineer"]},mutation_test:{description:"executes pre-generated mutation patches against tests, evaluates kill rate against quality gate thresholds",agents:["architect","test_engineer"]},generate_mutants:{description:"generate LLM-based mutation testing patches for source files; returns MutationPatch[] for direct consumption by the mutation_test tool",agents:["architect"]},detect_domains:{description:"detect which SME domains are relevant for a given text",agents:["architect","sme","docs","docs_design","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","critic","critic_oversight","explorer"]},git_blame:{description:"per-line git blame metadata: sha, author, date, summary for each line in a file",agents:["reviewer","explorer","architect"]},gitingest:{description:"fetch a GitHub repository full content via gitingest.com",agents:["architect","docs","explorer"]},retrieve_summary:{description:"retrieve the full content of a stored tool output summary",agents:["architect","sme","docs","docs_design","designer","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","critic_architecture_supervisor","spec_writer","reviewer","critic","critic_oversight","explorer","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:["architect","sme","docs","docs_design","designer","spec_writer","reviewer","explorer","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","coder"]},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
|
|
|
@@ -192,9 +192,9 @@ GFS4: `),console.error(m)};if(!fs9[gracefulQueue]){if(queue=global[gracefulQueue
|
|
|
192
192
|
`;fs10.writeFileSync(tempPath,line,"utf8"),fs10.renameSync(tempPath,ledgerPath)}async function appendLedgerEvent(directory,eventInput,options){return withEvidenceLock(directory,LEDGER_LOCK_PATH,"plan-ledger","append-ledger-event",async()=>{let ledgerPath=getLedgerPath(directory),latestSeq=await getLatestLedgerSeq(directory),nextSeq=latestSeq+1,planHashBefore=computeCurrentPlanHash(directory);if(options?.expectedSeq!==void 0&&options.expectedSeq!==latestSeq)throw new LedgerStaleWriterError(`Stale writer: expected seq ${options.expectedSeq} but found ${latestSeq}`);if(options?.expectedHash!==void 0&&options.expectedHash!==planHashBefore)throw new LedgerStaleWriterError(`Stale writer: expected hash ${options.expectedHash} but found ${planHashBefore}`);let planHashAfter=options?.planHashAfter??planHashBefore,event={...eventInput,seq:nextSeq,timestamp:new Date().toISOString(),plan_hash_before:planHashBefore,plan_hash_after:planHashAfter,schema_version:LEDGER_SCHEMA_VERSION};fs10.mkdirSync(path13.join(directory,".swarm"),{recursive:!0});let tempPath=`${ledgerPath}.tmp.${Date.now()}.${Math.floor(Math.random()*1e9)}`,line=`${JSON.stringify(event)}
|
|
193
193
|
`;if(fs10.existsSync(ledgerPath)){let existingContent=fs10.readFileSync(ledgerPath,"utf8");fs10.writeFileSync(tempPath,existingContent+line,"utf8")}else throw Error("Ledger not initialized. Call initLedger() first.");return fs10.renameSync(tempPath,ledgerPath),event})}async function takeSnapshotWithRetry(directory,plan,options){let telemetrySource=options?.source??"save_plan_tool",snapshotOptions={planHashAfter:options?.planHashAfter},lastError;for(let attempt=1;attempt<=4;attempt++)try{await takeSnapshotEvent(directory,plan,snapshotOptions);return}catch(err){if(lastError=err instanceof Error?err:Error(String(err)),attempt<4)await new Promise((r)=>setTimeout(r,10*2**(attempt-1)))}console.warn(`[takeSnapshotWithRetry] Snapshot failed after 3 retries (4 attempts): ${lastError.message}`);try{emit("snapshot_failed",{error:lastError.message,retries:3,source:telemetrySource})}catch{}}async function takeSnapshotEvent(directory,plan,options){let payloadHash=computePlanHash(plan),snapshotPayload={plan,payload_hash:payloadHash};if(options?.approvalMetadata)snapshotPayload.approval=options.approvalMetadata;let planId=derivePlanId(plan);return appendLedgerEvent(directory,{event_type:"snapshot",source:options?.source??"takeSnapshotEvent",plan_id:planId,payload:snapshotPayload},{planHashAfter:options?.planHashAfter})}async function replayFromLedger(directory,_options){let{events,truncated,badSuffix}=await readLedgerEventsWithIntegrity(directory);if(events.length===0)return null;if(truncated&&badSuffix!==null)await quarantineLedgerSuffix(directory,badSuffix);let targetPlanId=events[0].plan_id,relevantEvents=events.filter((e)=>e.plan_id===targetPlanId);{let snapshotEvents=relevantEvents.filter((e)=>e.event_type==="snapshot");if(snapshotEvents.length>0){let latestSnapshotEvent=snapshotEvents[snapshotEvents.length-1],plan2=latestSnapshotEvent.payload.plan,eventsAfterSnapshot=relevantEvents.filter((e)=>e.seq>latestSnapshotEvent.seq);for(let event of eventsAfterSnapshot)if(plan2=applyEventToPlan(plan2,event),plan2===null)return null;return plan2}}let createdEvent=relevantEvents.find((e)=>e.event_type==="plan_created");if(createdEvent?.payload&&typeof createdEvent.payload==="object"&&"plan"in createdEvent.payload){let parseResult=PlanSchema.safeParse(createdEvent.payload.plan);if(parseResult.success){let plan2=parseResult.data,eventsAfterCreated=relevantEvents.filter((e)=>e.seq>createdEvent.seq);for(let event of eventsAfterCreated){if(plan2===null)return null;plan2=applyEventToPlan(plan2,event)}return plan2}}let planJsonPath=getPlanJsonPath(directory);if(!fs10.existsSync(planJsonPath))return null;let plan;try{let content=fs10.readFileSync(planJsonPath,"utf8");plan=JSON.parse(content)}catch{return null}for(let event of relevantEvents){if(plan===null)return null;plan=applyEventToPlan(plan,event)}return plan}function applyEventToPlan(plan,event){switch(event.event_type){case"plan_created":if(event.payload&&typeof event.payload==="object"&&"plan"in event.payload){let parsed=PlanSchema.safeParse(event.payload.plan);if(parsed.success)return parsed.data}return plan;case"task_status_changed":if(event.task_id&&event.to_status){let parseResult=TaskStatusSchema.safeParse(event.to_status);if(!parseResult.success)return plan;for(let phase of plan.phases){let task=phase.tasks.find((t)=>t.id===event.task_id);if(task){task.status=parseResult.data;break}}}return plan;case"phase_completed":if(event.phase_id){let phase=plan.phases.find((p)=>p.id===event.phase_id);if(phase)phase.status="complete"}return plan;case"plan_exported":return plan;case"task_added":return plan;case"task_removed":if(event.task_id)for(let phase of plan.phases){let idx=phase.tasks.findIndex((t)=>t.id===event.task_id);if(idx!==-1){phase.tasks.splice(idx,1);break}}return plan;case"task_updated":return plan;case"plan_rebuilt":return plan;case"task_reordered":return plan;case"snapshot":return plan;case"plan_reset":return null;case"execution_profile_set":{let rawProfile=event.payload?.execution_profile;if(rawProfile!==void 0){let parsed=ExecutionProfileSchema.safeParse(rawProfile);if(parsed.success)return{...plan,execution_profile:parsed.data}}return plan}case"execution_profile_locked":{if(plan.execution_profile)return{...plan,execution_profile:{...plan.execution_profile,locked:!0}};return plan}default:throw Error(`applyEventToPlan: unhandled event type "${event.event_type}" at seq ${event.seq}`)}}async function readLedgerEventsWithIntegrity(directory){let ledgerPath=getLedgerPath(directory);if(!fs10.existsSync(ledgerPath))return{events:[],truncated:!1,badSuffix:null};try{let lines=fs10.readFileSync(ledgerPath,"utf8").split(`
|
|
194
194
|
`),events=[],truncated=!1,badSuffix=null;for(let i=0;i<lines.length;i++){let line=lines[i];if(line.trim()==="")continue;try{let event=JSON.parse(line);events.push(event)}catch{truncated=!0,badSuffix=lines.slice(i).join(`
|
|
195
|
-
`);break}}return events.sort((a,b)=>a.seq-b.seq),{events,truncated,badSuffix}}catch{return{events:[],truncated:!1,badSuffix:null}}}async function quarantineLedgerSuffix(directory,badSuffix){try{let quarantinePath=path13.join(directory,".swarm","plan-ledger.quarantine");fs10.writeFileSync(quarantinePath,badSuffix,"utf8"),console.warn(`[ledger] Corrupted suffix quarantined to ${path13.relative(directory,quarantinePath)}`)}catch{}}async function loadLastApprovedPlan(directory,expectedPlanId){let events=await readLedgerEvents(directory);if(events.length===0)return null;for(let i=events.length-1;i>=0;i--){let event=events[i];if(event.event_type!=="snapshot")continue;if(event.source!=="critic_approved")continue;if(expectedPlanId!==void 0&&event.plan_id!==expectedPlanId)continue;let payload=event.payload;if(!payload||typeof payload!=="object"||!payload.plan)continue;if(expectedPlanId!==void 0){if(derivePlanId(payload.plan)!==expectedPlanId)continue}return{plan:payload.plan,seq:event.seq,timestamp:event.timestamp,approval:payload.approval,payloadHash:payload.payload_hash}}return null}var LEDGER_SCHEMA_VERSION="1.1.0",LEDGER_FILENAME="plan-ledger.jsonl",LEDGER_LOCK_PATH,PLAN_JSON_FILENAME="plan.json",LedgerStaleWriterError;var init_ledger=__esm(()=>{init_plan_schema();init_lock();init_telemetry();init_utils3();LEDGER_LOCK_PATH=path13.join(".swarm",LEDGER_FILENAME);LedgerStaleWriterError=class LedgerStaleWriterError extends Error{constructor(message){super(message);this.name="LedgerStaleWriterError"}}});import{copyFileSync,existsSync as existsSync10,readdirSync as readdirSync3,renameSync as renameSync6,unlinkSync as unlinkSync4}from"node:fs";import*as fsPromises3 from"node:fs/promises";import*as path14 from"node:path";function derivePhaseStatusesInPlace(plan){for(let phase of plan.phases){let tasks=phase.tasks;if(tasks.length>0&&tasks.every((t)=>t.status==="completed"))phase.status="complete";else if(tasks.some((t)=>t.status==="in_progress"))phase.status="in_progress";else if(tasks.some((t)=>t.status==="blocked"))phase.status="blocked";else phase.status="pending"}}function
|
|
195
|
+
`);break}}return events.sort((a,b)=>a.seq-b.seq),{events,truncated,badSuffix}}catch{return{events:[],truncated:!1,badSuffix:null}}}async function quarantineLedgerSuffix(directory,badSuffix){try{let quarantinePath=path13.join(directory,".swarm","plan-ledger.quarantine");fs10.writeFileSync(quarantinePath,badSuffix,"utf8"),console.warn(`[ledger] Corrupted suffix quarantined to ${path13.relative(directory,quarantinePath)}`)}catch{}}async function loadLastApprovedPlan(directory,expectedPlanId){let events=await readLedgerEvents(directory);if(events.length===0)return null;for(let i=events.length-1;i>=0;i--){let event=events[i];if(event.event_type!=="snapshot")continue;if(event.source!=="critic_approved")continue;if(expectedPlanId!==void 0&&event.plan_id!==expectedPlanId)continue;let payload=event.payload;if(!payload||typeof payload!=="object"||!payload.plan)continue;if(expectedPlanId!==void 0){if(derivePlanId(payload.plan)!==expectedPlanId)continue}return{plan:payload.plan,seq:event.seq,timestamp:event.timestamp,approval:payload.approval,payloadHash:payload.payload_hash}}return null}var LEDGER_SCHEMA_VERSION="1.1.0",LEDGER_FILENAME="plan-ledger.jsonl",LEDGER_LOCK_PATH,PLAN_JSON_FILENAME="plan.json",LedgerStaleWriterError;var init_ledger=__esm(()=>{init_plan_schema();init_lock();init_telemetry();init_utils3();LEDGER_LOCK_PATH=path13.join(".swarm",LEDGER_FILENAME);LedgerStaleWriterError=class LedgerStaleWriterError extends Error{constructor(message){super(message);this.name="LedgerStaleWriterError"}}});import{copyFileSync,existsSync as existsSync10,readdirSync as readdirSync3,renameSync as renameSync6,unlinkSync as unlinkSync4}from"node:fs";import*as fsPromises3 from"node:fs/promises";import*as path14 from"node:path";function derivePhaseStatusesInPlace(plan){for(let phase of plan.phases){let tasks=phase.tasks;if(tasks.length>0&&tasks.every((t)=>t.status==="completed"))phase.status="complete";else if(tasks.some((t)=>t.status==="in_progress"))phase.status="in_progress";else if(tasks.some((t)=>t.status==="blocked"))phase.status="blocked";else phase.status="pending"}}function statusRank(s){switch(s){case"closed":return 5;case"completed":return 4;case"blocked":return 3;case"in_progress":return 2;case"pending":return 1;default:return 0}}function mergeStatusesTakingPrecedence(validated,replayed,ledgerStatusTaskIds){let projected=structuredClone(validated),replayedByTaskId=new Map;for(let phase of replayed.phases)for(let task of phase.tasks)if(ledgerStatusTaskIds.has(task.id))replayedByTaskId.set(task.id,task.status);for(let phase of projected.phases)for(let task of phase.tasks){let replayedStatus=replayedByTaskId.get(task.id);if(replayedStatus&&statusRank(replayedStatus)>statusRank(task.status))task.status=replayedStatus}return derivePhaseStatusesInPlace(projected),projected}function collectLedgerStatusTaskIds(events){let statusTaskIds=new Set;for(let event of events)if(event.event_type==="task_status_changed"&&typeof event.task_id==="string")statusTaskIds.add(event.task_id);return statusTaskIds}async function retryCasWithBackoff(directory,eventInput,options){let maxRetries=options.maxRetries??CAS_MAX_RETRIES,currentExpected=options.expectedHash,attempt=0;while(!0)try{return await appendLedgerEvent(directory,eventInput,{expectedHash:currentExpected,planHashAfter:options.planHashAfter})}catch(error49){if(!(error49 instanceof LedgerStaleWriterError)||attempt>=maxRetries)throw error49;attempt++;let base=Math.min(CAS_BACKOFF_START_MS*2**(attempt-1),CAS_BACKOFF_CAP_MS),jitter=base*CAS_BACKOFF_JITTER*(Math.random()*2-1),delayMs=Math.max(1,Math.round(base+jitter));if(emit("plan_ledger_cas_retry",{attempt,expectedHashPrefix:currentExpected.slice(0,8),delayMs}),await new Promise((resolve8)=>setTimeout(resolve8,delayMs)),options.verifyValid){if(!await options.verifyValid())return null}currentExpected=computeCurrentPlanHash(directory)}}async function loadPlanJsonOnly(directory){try{return await parsePlanJsonCached(directory)}catch(error49){warn(`Plan validation failed for .swarm/plan.json: ${error49 instanceof Error?error49.message:String(error49)}`)}return null}function compareTaskIds(a,b){let partsA=a.split(".").map((n)=>parseInt(n,10)),partsB=b.split(".").map((n)=>parseInt(n,10)),maxLen=Math.max(partsA.length,partsB.length);for(let i=0;i<maxLen;i++){let numA=partsA[i]??0,numB=partsB[i]??0;if(numA!==numB)return numA-numB}return 0}async function getLatestLedgerHash(directory){try{let events=await readLedgerEvents(directory);if(events.length===0)return"";return events[events.length-1].plan_hash_after}catch{return""}}async function surfaceLedgerStaleIfPersisted(directory,plan){let resolvedWorkspace=path14.resolve(directory);if(!ledgerStaleWorkspaces.has(resolvedWorkspace))return plan;try{let planHash=computePlanHash(plan),ledgerHash=await getLatestLedgerHash(directory);if(ledgerHash!==""&&planHash===ledgerHash)return ledgerStaleWorkspaces.delete(resolvedWorkspace),plan}catch{}if(plan._ledgerReplayStale=!0,typeof plan._ledgerReplayStaleReason!=="string"||plan._ledgerReplayStaleReason.length===0)plan._ledgerReplayStaleReason="plan.json still hash-mismatches the ledger after a startup ledger-replay failure (replay could not be applied and no critic-approved snapshot was available). Run /swarm reset-session if this persists.";return plan}async function parsePlanJsonCached(directory){let planJsonPath=path14.resolve(directory,".swarm","plan.json");return readCachedParsedFile(planJsonPath,PLAN_JSON_CACHE_NAMESPACE,()=>readSwarmFileAsync(directory,"plan.json"),(planJsonContent)=>{if(planJsonContent.includes("\x00")||planJsonContent.includes("�"))throw Error("Plan rejected: .swarm/plan.json contains null bytes or invalid encoding");let parsed=JSON.parse(planJsonContent);return PlanSchema.parse(parsed)})}function computePlanContentHash(plan){let content={schema_version:plan.schema_version,title:plan.title,swarm:plan.swarm,current_phase:plan.current_phase,migration_status:plan.migration_status,phases:plan.phases.map((phase)=>({id:phase.id,name:phase.name,status:phase.status,tasks:phase.tasks.map((task)=>({id:task.id,phase:task.phase,status:task.status,size:task.size,description:task.description,depends:[...task.depends].sort(compareTaskIds),acceptance:task.acceptance,files_touched:[...task.files_touched].sort(),evidence_path:task.evidence_path,blocked_reason:task.blocked_reason})).sort((a,b)=>compareTaskIds(a.id,b.id))})).sort((a,b)=>a.id-b.id)},jsonString=JSON.stringify(content);return bunHash(jsonString).toString(36)}function extractPlanHashFromMarkdown(markdown){let match=markdown.match(/<!--\s*PLAN_HASH:\s*(\S+)\s*-->/);return match?match[1]:null}async function isPlanMdInSync(directory,plan,cache){let planMdContent=await readSwarmFileAsync(directory,"plan.md",cache);if(planMdContent===null)return!1;let expectedHash=computePlanContentHash(plan);if(extractPlanHashFromMarkdown(planMdContent)===expectedHash)return!0;let normalizedExpected=derivePlanMarkdown(plan).trim();if(planMdContent.trim()===normalizedExpected)return!0;return!1}async function regeneratePlanMarkdown(directory,plan){let swarmDir=path14.resolve(directory,".swarm"),contentHash=computePlanContentHash(plan),markdown=derivePlanMarkdown(plan),markdownWithHash=`<!-- PLAN_HASH: ${contentHash} -->
|
|
196
196
|
${markdown}`,mdPath=path14.join(swarmDir,"plan.md"),mdTempPath=path14.join(swarmDir,`plan.md.tmp.${Date.now()}.${Math.floor(Math.random()*1e9)}`);try{await bunWrite(mdTempPath,markdownWithHash),renameSync6(mdTempPath,mdPath)}finally{try{unlinkSync4(mdTempPath)}catch{}}}async function loadPlan(directory,cache){let planJsonContent=await readSwarmFileAsync(directory,"plan.json",cache);if(planJsonContent!==null)if(planJsonContent.includes("\x00")||planJsonContent.includes("�"))warn("Plan rejected: .swarm/plan.json contains null bytes or invalid encoding");else try{let validated=await parsePlanJsonCached(directory);if(validated===null)warn("[loadPlan] plan.json disappeared during cached parse. Falling back to plan.md migration or ledger recovery.");else{if(!await isPlanMdInSync(directory,validated,cache))try{await _internals9.regeneratePlanMarkdown(directory,validated)}catch(regenError){warn(`Failed to regenerate plan.md: ${regenError instanceof Error?regenError.message:String(regenError)}. Proceeding with plan.json only.`)}if(await ledgerExists(directory)){let planHash=computePlanHash(validated),ledgerHash=await getLatestLedgerHash(directory),resolvedWorkspace=path14.resolve(directory);if(!startupLedgerCheckedWorkspaces.has(resolvedWorkspace)){if(startupLedgerCheckedWorkspaces.add(resolvedWorkspace),ledgerHash!==""&&planHash!==ledgerHash){let currentPlanId=derivePlanId(validated),ledgerEvents=await readLedgerEvents(directory),firstEvent=ledgerEvents.length>0?ledgerEvents[0]:null;if(firstEvent&&firstEvent.plan_id!==currentPlanId)warn(`[loadPlan] Ledger identity mismatch (ledger: ${firstEvent.plan_id}, plan: ${currentPlanId}) — skipping ledger rebuild (migration detected). Use /swarm reset-session to reinitialize the ledger.`);else{warn("[loadPlan] plan.json is stale (hash mismatch with ledger) — rebuilding from ledger. If this recurs, run /swarm reset-session to clear stale session state.");try{let rebuilt=await replayFromLedger(directory);if(rebuilt)return await rebuildPlan(directory,rebuilt,{reason:"ledger_hash_mismatch_recovery"}),warn("[loadPlan] Rebuilt plan from ledger. Checkpoint available at .swarm/plan-export/SWARM_PLAN.md if it exists."),rebuilt}catch(replayError){try{let approved=await loadLastApprovedPlan(directory,currentPlanId);if(approved){await rebuildPlan(directory,approved.plan,{reason:"approved_snapshot_fallback"});try{await takeSnapshotEvent(directory,approved.plan,{source:"recovery_from_approved_snapshot",approvalMetadata:approved.approval})}catch(healError){warn(`[loadPlan] Recovery-heal snapshot append failed: ${healError instanceof Error?healError.message:String(healError)}. Next loadPlan may re-enter recovery path.`)}let approvedPhase=approved.approval&&typeof approved.approval==="object"&&"phase"in approved.approval?approved.approval.phase:void 0;return warn(`[loadPlan] Ledger replay failed (${replayError instanceof Error?replayError.message:String(replayError)}) — recovered from critic-approved snapshot seq=${approved.seq} (approval phase=${approvedPhase??"unknown"}, timestamp=${approved.timestamp}). This may roll the plan back to an earlier phase — verify before continuing.`),approved.plan}}catch{}{let runtimeStale=validated;runtimeStale._ledgerReplayStale=!0,runtimeStale._ledgerReplayStaleReason=`Ledger replay failed during hash-mismatch rebuild and no approved snapshot was available: ${replayError instanceof Error?replayError.message:String(replayError)}`,ledgerStaleWorkspaces.add(resolvedWorkspace)}warn(`[loadPlan] Ledger replay failed during hash-mismatch rebuild: ${replayError instanceof Error?replayError.message:String(replayError)}. Returning stale plan.json. To recover: check .swarm/plan-export/SWARM_PLAN.md for a checkpoint, or run /swarm reset-session.`)}}}}else if(ledgerHash!==""&&planHash!==ledgerHash){if(process.env.DEBUG_SWARM)console.warn(`[loadPlan] Ledger hash mismatch during active session for ${resolvedWorkspace} — skipping rebuild (startup check already performed).`)}}if(validated.specHash){let staleResult=await isSpecStale(directory,validated);if(staleResult.stale){let runtimePlan=validated;if(runtimePlan._specStale=!0,runtimePlan._specStaleReason=staleResult.reason,!await isObligationPreserving(directory)){try{let diffInfo=computeSpecDiff(directory),specStalenessPath=path14.join(directory,".swarm","spec-staleness.json");await fsPromises3.writeFile(specStalenessPath,JSON.stringify({type:"spec_stale_detected",timestamp:new Date().toISOString(),phase:validated.current_phase??1,specHash_plan:validated.specHash,specHash_current:staleResult.currentHash??null,reason:staleResult.reason,planTitle:validated.title,diff:diffInfo?.diff??null,changedSections:diffInfo?.changedSections??[]},null,2),"utf-8")}catch{}try{let eventsPath=path14.join(directory,".swarm","events.jsonl"),event={type:"spec_stale_detected",timestamp:new Date().toISOString(),phase:validated.current_phase??1,specHash_plan:validated.specHash,specHash_current:staleResult.currentHash??null,reason:staleResult.reason??"unknown",planTitle:validated.title};await fsPromises3.appendFile(eventsPath,`${JSON.stringify(event)}
|
|
197
|
-
`,"utf-8")}catch{}}}}return await surfaceLedgerStaleIfPersisted(directory,validated)}}catch(error49){warn(`[loadPlan] plan.json validation failed: ${error49 instanceof Error?error49.message:String(error49)}. Attempting rebuild from ledger. If rebuild fails, check .swarm/plan-export/SWARM_PLAN.md for a checkpoint.`);let rawPlanId=null;try{let rawParsed=JSON.parse(planJsonContent);if(typeof rawParsed?.swarm==="string"&&typeof rawParsed?.title==="string")rawPlanId=derivePlanId(rawParsed)}catch{}if(await ledgerExists(directory)){let ledgerEventsForCatch=await readLedgerEvents(directory),catchFirstEvent=ledgerEventsForCatch.length>0?ledgerEventsForCatch[0]:null;if(!(rawPlanId===null||catchFirstEvent===null||catchFirstEvent.plan_id===rawPlanId))warn(`[loadPlan] Ledger identity mismatch in validation-failure path (ledger: ${catchFirstEvent?.plan_id}, plan: ${rawPlanId}) — skipping ledger rebuild (migration detected).`);else if(catchFirstEvent!==null&&rawPlanId!==null){let rebuilt=await replayFromLedger(directory);if(rebuilt)return await rebuildPlan(directory,rebuilt,{reason:"validation_failure_recovery"}),warn("[loadPlan] Rebuilt plan from ledger after validation failure. Projection was stale."),rebuilt}}let planMdContent2=await readSwarmFileAsync(directory,"plan.md",cache);if(planMdContent2!==null){let migrated=migrateLegacyPlan(planMdContent2),{removedCount}=await savePlanWithAutoAcknowledgedRemovals(directory,migrated,"load_plan_migration_from_md","migrate legacy plan.md to plan.json");if(removedCount>0)migrated._midLoadRemovals={count:removedCount,source:"load_plan_migration_from_md"};return migrated}}let planMdContent=await readSwarmFileAsync(directory,"plan.md",cache);if(planMdContent!==null){let migrated=migrateLegacyPlan(planMdContent);return await savePlan(directory,migrated),migrated}if(await ledgerExists(directory)){let resolvedDir=path14.resolve(directory),existingMutex=recoveryMutexes.get(resolvedDir);if(existingMutex){await existingMutex;let postRecoveryPlan=await _internals9.loadPlanJsonOnly(directory);if(postRecoveryPlan)return postRecoveryPlan}let resolveRecovery,mutex=new Promise((r)=>{resolveRecovery=r});recoveryMutexes.set(resolvedDir,mutex);try{let rebuilt=await replayFromLedger(directory);if(rebuilt){let{removedCount}=await savePlanWithAutoAcknowledgedRemovals(directory,rebuilt,"load_plan_rebuild_from_ledger","rebuild plan from ledger replay");if(removedCount>0)rebuilt._midLoadRemovals={count:removedCount,source:"load_plan_rebuild_from_ledger"};return rebuilt}try{let anchorEvents=await readLedgerEvents(directory);if(anchorEvents.length===0)return warn("[loadPlan] Ledger present but no events readable — refusing approved-snapshot recovery (cannot verify plan identity)."),null;let expectedPlanId=anchorEvents[0].plan_id,approved=await loadLastApprovedPlan(directory,expectedPlanId);if(approved){let approvedPhase=approved.approval&&typeof approved.approval==="object"&&"phase"in approved.approval?approved.approval.phase:void 0;warn(`[loadPlan] Ledger replay returned no plan — recovered from critic-approved snapshot seq=${approved.seq} timestamp=${approved.timestamp} (approval phase=${approvedPhase??"unknown"}). This may roll the plan back to an earlier phase — verify before continuing.`);let{removedCount:snapshotRemovedCount}=await savePlanWithAutoAcknowledgedRemovals(directory,approved.plan,"load_plan_recovery_from_approved_snapshot","restore from critic-approved snapshot");if(snapshotRemovedCount>0)approved.plan._midLoadRemovals={count:snapshotRemovedCount,source:"load_plan_recovery_from_approved_snapshot"};try{await takeSnapshotEvent(directory,approved.plan,{source:"recovery_from_approved_snapshot",approvalMetadata:approved.approval})}catch(healError){warn(`[loadPlan] Recovery-heal snapshot append failed: ${healError instanceof Error?healError.message:String(healError)}. Next loadPlan may re-enter recovery path.`)}return approved.plan}}catch(recoveryError){warn(`[loadPlan] Approved-snapshot recovery failed: ${recoveryError instanceof Error?recoveryError.message:String(recoveryError)}`)}}finally{resolveRecovery(),recoveryMutexes.delete(resolvedDir)}}return null}async function savePlanWithAutoAcknowledgedRemovals(directory,plan,source,reason,options){let existing=await _internals9.loadPlanJsonOnly(directory),newIds=new Set;for(let phase of plan.phases)for(let task of phase.tasks)newIds.add(task.id);let removedIds=[];if(existing){for(let phase of existing.phases)for(let task of phase.tasks)if(!newIds.has(task.id))removedIds.push(task.id)}return await savePlan(directory,plan,{...options??{},acknowledged_removals:{ids:removedIds,reason,source}}),{removedCount:removedIds.length}}async function savePlan(directory,plan,options){if(directory===null||directory===void 0||typeof directory!=="string"||directory.trim().length===0)throw Error("Invalid directory: directory must be a non-empty string");let validated=PlanSchema.parse(plan);if(options?.preserveCompletedStatuses!==!1)try{let currentPlan2=await _internals9.loadPlanJsonOnly(directory);if(currentPlan2){let completedTaskIds=new Set;for(let phase of currentPlan2.phases)for(let task of phase.tasks)if(task.status==="completed")completedTaskIds.add(task.id);if(completedTaskIds.size>0){for(let phase of validated.phases)for(let task of phase.tasks)if(completedTaskIds.has(task.id)&&task.status!=="completed")task.status="completed"}}}catch{}derivePhaseStatusesInPlace(validated);let currentPlan=await _internals9.loadPlanJsonOnly(directory),planId=derivePlanId(validated),planHashForInit=computePlanHash(validated);if(!await ledgerExists(directory))try{await initLedger(directory,planId,planHashForInit,validated)}catch(initErr){let msg=initErr instanceof Error?initErr.message:String(initErr);if(!/already initialized/i.test(msg))throw initErr}else{let existingEvents=await readLedgerEvents(directory);if(existingEvents.length>0&&existingEvents[0].plan_id!==planId){let swarmDir2=path14.resolve(directory,".swarm"),oldLedgerPath=path14.join(swarmDir2,"plan-ledger.jsonl"),oldLedgerBackupPath=path14.join(swarmDir2,`plan-ledger.backup-${Date.now()}-${Math.floor(Math.random()*1e9)}.jsonl`),backupExists=!1;if(existsSync10(oldLedgerPath))try{renameSync6(oldLedgerPath,oldLedgerBackupPath),backupExists=!0}catch(renameErr){throw Error(`[savePlan] Cannot reinitialize ledger: could not move old ledger aside (rename failed: ${renameErr instanceof Error?renameErr.message:String(renameErr)}). The existing ledger has plan_id="${existingEvents[0].plan_id}" which does not match the current plan="${planId}". To proceed, close any programs that may have the ledger file open, or run /swarm reset-session to clear the ledger.`)}let initSucceeded=!1;if(backupExists)try{await initLedger(directory,planId,planHashForInit,validated),initSucceeded=!0}catch(initErr){if(String(initErr).includes("already initialized"))try{if(existsSync10(oldLedgerBackupPath))unlinkSync4(oldLedgerBackupPath)}catch{}else{if(existsSync10(oldLedgerBackupPath))try{renameSync6(oldLedgerBackupPath,oldLedgerPath)}catch{copyFileSync(oldLedgerBackupPath,oldLedgerPath);try{unlinkSync4(oldLedgerBackupPath)}catch{}}throw initErr}}if(initSucceeded&&backupExists){let archivePath=path14.join(swarmDir2,`plan-ledger.archived-${Date.now()}-${Math.floor(Math.random()*1e9)}.jsonl`);try{renameSync6(oldLedgerBackupPath,archivePath),warn(`[savePlan] Ledger identity mismatch (was "${existingEvents[0].plan_id}", now "${planId}") — archived old ledger to ${archivePath} and reinitializing.`)}catch(renameErr){warn(`[savePlan] Could not archive old ledger (rename failed: ${renameErr instanceof Error?renameErr.message:String(renameErr)}). Old ledger may still exist at ${oldLedgerBackupPath}.`);try{if(existsSync10(oldLedgerBackupPath))unlinkSync4(oldLedgerBackupPath)}catch{}}}else if(!initSucceeded&&backupExists)try{if(existsSync10(oldLedgerBackupPath))unlinkSync4(oldLedgerBackupPath)}catch{}let MAX_ARCHIVED_SIBLINGS=5;try{let archivedSiblings=readdirSync3(swarmDir2).filter((f)=>f.startsWith("plan-ledger.archived-")&&f.endsWith(".jsonl")).sort();if(archivedSiblings.length>MAX_ARCHIVED_SIBLINGS){let toRemove=archivedSiblings.slice(0,archivedSiblings.length-MAX_ARCHIVED_SIBLINGS);for(let file2 of toRemove)try{unlinkSync4(path14.join(swarmDir2,file2))}catch{}}}catch{}}}let currentHash=computeCurrentPlanHash(directory),hashAfter=computePlanHash(validated);if(currentPlan){let oldTaskMap=new Map;for(let phase of currentPlan.phases)for(let task of phase.tasks)oldTaskMap.set(task.id,{phase:task.phase,status:task.status});let newTaskIds=new Set;for(let phase of validated.phases)for(let task of phase.tasks)newTaskIds.add(task.id);let missingTasks=[];for(let[id,info]of oldTaskMap.entries())if(!newTaskIds.has(id))missingTasks.push({id,phase:info.phase,status:info.status});let ack=options?.acknowledged_removals;if(missingTasks.length>0){if(!ack)throw new PlanTaskRemovalNotAcknowledgedError(missingTasks);if(typeof ack.reason!=="string"||ack.reason.trim().length===0)throw Error("PLAN_ACKNOWLEDGED_REMOVAL_INVALID: acknowledged_removals.reason must be a non-empty string.");if(typeof ack.source!=="string"||ack.source.trim().length===0)throw Error("PLAN_ACKNOWLEDGED_REMOVAL_INVALID: acknowledged_removals.source must be a non-empty string.");let ackSet=new Set(ack.ids),missingIdsSet=new Set(missingTasks.map((t)=>t.id)),unacked=missingTasks.filter((t)=>!ackSet.has(t.id));if(unacked.length>0)throw new PlanTaskRemovalNotAcknowledgedError(unacked);for(let id of ack.ids)if(!missingIdsSet.has(id))throw Error(`PLAN_ACKNOWLEDGED_REMOVAL_INVALID: acknowledged_removals contains "${id}" but that task is not missing from the plan.`);try{for(let missing of missingTasks){let eventInput={plan_id:derivePlanId(validated),event_type:"task_removed",task_id:missing.id,phase_id:missing.phase,from_status:missing.status,source:ack.source,payload:{reason:ack.reason,source:ack.source}},capturedTaskId=missing.id;await retryCasWithBackoff(directory,eventInput,{expectedHash:currentHash,planHashAfter:hashAfter,verifyValid:async()=>{let onDisk=await _internals9.loadPlanJsonOnly(directory);if(!onDisk)return!0;for(let p of onDisk.phases)if(p.tasks.some((x)=>x.id===capturedTaskId))return!0;return!1}})}}catch(error49){if(error49 instanceof LedgerStaleWriterError)throw new PlanConcurrentModificationError(`Concurrent plan modification detected after retries: ${error49.message}. Please retry the operation.`);throw error49}}try{for(let phase of validated.phases)for(let task of phase.tasks){let oldTask=oldTaskMap.get(task.id);if(oldTask&&oldTask.status!==task.status){let eventInput={plan_id:derivePlanId(validated),event_type:"task_status_changed",task_id:task.id,phase_id:phase.id,from_status:oldTask.status,to_status:task.status,source:"savePlan"},capturedFromStatus=oldTask.status,capturedTaskId=task.id;await retryCasWithBackoff(directory,eventInput,{expectedHash:currentHash,planHashAfter:hashAfter,verifyValid:async()=>{let onDisk=await _internals9.loadPlanJsonOnly(directory);if(!onDisk)return!0;for(let p of onDisk.phases){let t=p.tasks.find((x)=>x.id===capturedTaskId);if(t)return t.status===capturedFromStatus}return!1}})}}}catch(error49){if(error49 instanceof LedgerStaleWriterError)throw new PlanConcurrentModificationError(`Concurrent plan modification detected after retries: ${error49.message}. Please retry the operation.`);throw error49}}let ledgerStatusTaskIds=collectLedgerStatusTaskIds(await readLedgerEvents(directory)),replayedBeforeProjection=await replayFromLedger(directory),projectionCandidate=replayedBeforeProjection?overlayLedgerStatuses(validated,replayedBeforeProjection,ledgerStatusTaskIds):validated;if(replayedBeforeProjection&&computePlanHash(replayedBeforeProjection)!==computePlanHash(projectionCandidate))await takeSnapshotEvent(directory,projectionCandidate,{planHashAfter:computePlanHash(projectionCandidate),source:"savePlan_structural_projection"});let projectedPlan=await replayFromLedger(directory)??projectionCandidate,SNAPSHOT_INTERVAL=50,latestSeq=await getLatestLedgerSeq(directory);if(latestSeq>0&&latestSeq%SNAPSHOT_INTERVAL===0)await takeSnapshotWithRetry(directory,projectedPlan,{planHashAfter:computePlanHash(projectedPlan),source:"savePlan_manager"});let swarmDir=path14.resolve(directory,".swarm"),planPath=path14.join(swarmDir,"plan.json"),tempPath=path14.join(swarmDir,`plan.json.tmp.${Date.now()}.${Math.floor(Math.random()*1e9)}`);try{await bunWrite(tempPath,JSON.stringify(projectedPlan,null,2)),renameSync6(tempPath,planPath)}finally{try{unlinkSync4(tempPath)}catch{}}try{let markerPath=path14.join(swarmDir,".plan-write-marker"),inProgressMarker=JSON.stringify({source:"plan_manager",timestamp:new Date().toISOString(),phases_count:projectedPlan.phases.length,tasks_count:projectedPlan.phases.reduce((sum,p)=>sum+p.tasks.length,0),in_progress:!0});await bunWrite(markerPath,inProgressMarker)}catch{}try{let contentHash=computePlanContentHash(projectedPlan),markdown=derivePlanMarkdown(projectedPlan),markdownWithHash=`<!-- PLAN_HASH: ${contentHash} -->
|
|
197
|
+
`,"utf-8")}catch{}}}}return await surfaceLedgerStaleIfPersisted(directory,validated)}}catch(error49){warn(`[loadPlan] plan.json validation failed: ${error49 instanceof Error?error49.message:String(error49)}. Attempting rebuild from ledger. If rebuild fails, check .swarm/plan-export/SWARM_PLAN.md for a checkpoint.`);let rawPlanId=null;try{let rawParsed=JSON.parse(planJsonContent);if(typeof rawParsed?.swarm==="string"&&typeof rawParsed?.title==="string")rawPlanId=derivePlanId(rawParsed)}catch{}if(await ledgerExists(directory)){let ledgerEventsForCatch=await readLedgerEvents(directory),catchFirstEvent=ledgerEventsForCatch.length>0?ledgerEventsForCatch[0]:null;if(!(rawPlanId===null||catchFirstEvent===null||catchFirstEvent.plan_id===rawPlanId))warn(`[loadPlan] Ledger identity mismatch in validation-failure path (ledger: ${catchFirstEvent?.plan_id}, plan: ${rawPlanId}) — skipping ledger rebuild (migration detected).`);else if(catchFirstEvent!==null&&rawPlanId!==null){let rebuilt=await replayFromLedger(directory);if(rebuilt)return await rebuildPlan(directory,rebuilt,{reason:"validation_failure_recovery"}),warn("[loadPlan] Rebuilt plan from ledger after validation failure. Projection was stale."),rebuilt}}let planMdContent2=await readSwarmFileAsync(directory,"plan.md",cache);if(planMdContent2!==null){let migrated=migrateLegacyPlan(planMdContent2),{removedCount}=await savePlanWithAutoAcknowledgedRemovals(directory,migrated,"load_plan_migration_from_md","migrate legacy plan.md to plan.json");if(removedCount>0)migrated._midLoadRemovals={count:removedCount,source:"load_plan_migration_from_md"};return migrated}}let planMdContent=await readSwarmFileAsync(directory,"plan.md",cache);if(planMdContent!==null){let migrated=migrateLegacyPlan(planMdContent);return await savePlan(directory,migrated),migrated}if(await ledgerExists(directory)){let resolvedDir=path14.resolve(directory),existingMutex=recoveryMutexes.get(resolvedDir);if(existingMutex){await existingMutex;let postRecoveryPlan=await _internals9.loadPlanJsonOnly(directory);if(postRecoveryPlan)return postRecoveryPlan}let resolveRecovery,mutex=new Promise((r)=>{resolveRecovery=r});recoveryMutexes.set(resolvedDir,mutex);try{let rebuilt=await replayFromLedger(directory);if(rebuilt){let{removedCount}=await savePlanWithAutoAcknowledgedRemovals(directory,rebuilt,"load_plan_rebuild_from_ledger","rebuild plan from ledger replay");if(removedCount>0)rebuilt._midLoadRemovals={count:removedCount,source:"load_plan_rebuild_from_ledger"};return rebuilt}try{let anchorEvents=await readLedgerEvents(directory);if(anchorEvents.length===0)return warn("[loadPlan] Ledger present but no events readable — refusing approved-snapshot recovery (cannot verify plan identity)."),null;let expectedPlanId=anchorEvents[0].plan_id,approved=await loadLastApprovedPlan(directory,expectedPlanId);if(approved){let approvedPhase=approved.approval&&typeof approved.approval==="object"&&"phase"in approved.approval?approved.approval.phase:void 0;warn(`[loadPlan] Ledger replay returned no plan — recovered from critic-approved snapshot seq=${approved.seq} timestamp=${approved.timestamp} (approval phase=${approvedPhase??"unknown"}). This may roll the plan back to an earlier phase — verify before continuing.`);let{removedCount:snapshotRemovedCount}=await savePlanWithAutoAcknowledgedRemovals(directory,approved.plan,"load_plan_recovery_from_approved_snapshot","restore from critic-approved snapshot");if(snapshotRemovedCount>0)approved.plan._midLoadRemovals={count:snapshotRemovedCount,source:"load_plan_recovery_from_approved_snapshot"};try{await takeSnapshotEvent(directory,approved.plan,{source:"recovery_from_approved_snapshot",approvalMetadata:approved.approval})}catch(healError){warn(`[loadPlan] Recovery-heal snapshot append failed: ${healError instanceof Error?healError.message:String(healError)}. Next loadPlan may re-enter recovery path.`)}return approved.plan}}catch(recoveryError){warn(`[loadPlan] Approved-snapshot recovery failed: ${recoveryError instanceof Error?recoveryError.message:String(recoveryError)}`)}}finally{resolveRecovery(),recoveryMutexes.delete(resolvedDir)}}return null}async function savePlanWithAutoAcknowledgedRemovals(directory,plan,source,reason,options){let existing=await _internals9.loadPlanJsonOnly(directory),newIds=new Set;for(let phase of plan.phases)for(let task of phase.tasks)newIds.add(task.id);let removedIds=[];if(existing){for(let phase of existing.phases)for(let task of phase.tasks)if(!newIds.has(task.id))removedIds.push(task.id)}return await savePlan(directory,plan,{...options??{},acknowledged_removals:{ids:removedIds,reason,source}}),{removedCount:removedIds.length}}async function savePlan(directory,plan,options){if(directory===null||directory===void 0||typeof directory!=="string"||directory.trim().length===0)throw Error("Invalid directory: directory must be a non-empty string");let validated=PlanSchema.parse(plan);if(options?.preserveCompletedStatuses!==!1)try{let currentPlan2=await _internals9.loadPlanJsonOnly(directory);if(currentPlan2){let completedTaskIds=new Set;for(let phase of currentPlan2.phases)for(let task of phase.tasks)if(task.status==="completed")completedTaskIds.add(task.id);if(completedTaskIds.size>0){for(let phase of validated.phases)for(let task of phase.tasks)if(completedTaskIds.has(task.id)&&task.status!=="completed")task.status="completed"}}}catch{}derivePhaseStatusesInPlace(validated);let currentPlan=await _internals9.loadPlanJsonOnly(directory),planId=derivePlanId(validated),planHashForInit=computePlanHash(validated);if(!await ledgerExists(directory))try{await initLedger(directory,planId,planHashForInit,validated)}catch(initErr){let msg=initErr instanceof Error?initErr.message:String(initErr);if(!/already initialized/i.test(msg))throw initErr}else{let existingEvents=await readLedgerEvents(directory);if(existingEvents.length>0&&existingEvents[0].plan_id!==planId){let swarmDir2=path14.resolve(directory,".swarm"),oldLedgerPath=path14.join(swarmDir2,"plan-ledger.jsonl"),oldLedgerBackupPath=path14.join(swarmDir2,`plan-ledger.backup-${Date.now()}-${Math.floor(Math.random()*1e9)}.jsonl`),backupExists=!1;if(existsSync10(oldLedgerPath))try{renameSync6(oldLedgerPath,oldLedgerBackupPath),backupExists=!0}catch(renameErr){throw Error(`[savePlan] Cannot reinitialize ledger: could not move old ledger aside (rename failed: ${renameErr instanceof Error?renameErr.message:String(renameErr)}). The existing ledger has plan_id="${existingEvents[0].plan_id}" which does not match the current plan="${planId}". To proceed, close any programs that may have the ledger file open, or run /swarm reset-session to clear the ledger.`)}let initSucceeded=!1;if(backupExists)try{await initLedger(directory,planId,planHashForInit,validated),initSucceeded=!0}catch(initErr){if(String(initErr).includes("already initialized"))try{if(existsSync10(oldLedgerBackupPath))unlinkSync4(oldLedgerBackupPath)}catch{}else{if(existsSync10(oldLedgerBackupPath))try{renameSync6(oldLedgerBackupPath,oldLedgerPath)}catch{copyFileSync(oldLedgerBackupPath,oldLedgerPath);try{unlinkSync4(oldLedgerBackupPath)}catch{}}throw initErr}}if(initSucceeded&&backupExists){let archivePath=path14.join(swarmDir2,`plan-ledger.archived-${Date.now()}-${Math.floor(Math.random()*1e9)}.jsonl`);try{renameSync6(oldLedgerBackupPath,archivePath),warn(`[savePlan] Ledger identity mismatch (was "${existingEvents[0].plan_id}", now "${planId}") — archived old ledger to ${archivePath} and reinitializing.`)}catch(renameErr){warn(`[savePlan] Could not archive old ledger (rename failed: ${renameErr instanceof Error?renameErr.message:String(renameErr)}). Old ledger may still exist at ${oldLedgerBackupPath}.`);try{if(existsSync10(oldLedgerBackupPath))unlinkSync4(oldLedgerBackupPath)}catch{}}}else if(!initSucceeded&&backupExists)try{if(existsSync10(oldLedgerBackupPath))unlinkSync4(oldLedgerBackupPath)}catch{}let MAX_ARCHIVED_SIBLINGS=5;try{let archivedSiblings=readdirSync3(swarmDir2).filter((f)=>f.startsWith("plan-ledger.archived-")&&f.endsWith(".jsonl")).sort();if(archivedSiblings.length>MAX_ARCHIVED_SIBLINGS){let toRemove=archivedSiblings.slice(0,archivedSiblings.length-MAX_ARCHIVED_SIBLINGS);for(let file2 of toRemove)try{unlinkSync4(path14.join(swarmDir2,file2))}catch{}}}catch{}}}let currentHash=computeCurrentPlanHash(directory),hashAfter=computePlanHash(validated);if(currentPlan){let oldTaskMap=new Map;for(let phase of currentPlan.phases)for(let task of phase.tasks)oldTaskMap.set(task.id,{phase:task.phase,status:task.status});let newTaskIds=new Set;for(let phase of validated.phases)for(let task of phase.tasks)newTaskIds.add(task.id);let missingTasks=[];for(let[id,info]of oldTaskMap.entries())if(!newTaskIds.has(id))missingTasks.push({id,phase:info.phase,status:info.status});let ack=options?.acknowledged_removals;if(missingTasks.length>0){if(!ack)throw new PlanTaskRemovalNotAcknowledgedError(missingTasks);if(typeof ack.reason!=="string"||ack.reason.trim().length===0)throw Error("PLAN_ACKNOWLEDGED_REMOVAL_INVALID: acknowledged_removals.reason must be a non-empty string.");if(typeof ack.source!=="string"||ack.source.trim().length===0)throw Error("PLAN_ACKNOWLEDGED_REMOVAL_INVALID: acknowledged_removals.source must be a non-empty string.");let ackSet=new Set(ack.ids),missingIdsSet=new Set(missingTasks.map((t)=>t.id)),unacked=missingTasks.filter((t)=>!ackSet.has(t.id));if(unacked.length>0)throw new PlanTaskRemovalNotAcknowledgedError(unacked);for(let id of ack.ids)if(!missingIdsSet.has(id))throw Error(`PLAN_ACKNOWLEDGED_REMOVAL_INVALID: acknowledged_removals contains "${id}" but that task is not missing from the plan.`);try{for(let missing of missingTasks){let eventInput={plan_id:derivePlanId(validated),event_type:"task_removed",task_id:missing.id,phase_id:missing.phase,from_status:missing.status,source:ack.source,payload:{reason:ack.reason,source:ack.source}},capturedTaskId=missing.id;await retryCasWithBackoff(directory,eventInput,{expectedHash:currentHash,planHashAfter:hashAfter,verifyValid:async()=>{let onDisk=await _internals9.loadPlanJsonOnly(directory);if(!onDisk)return!0;for(let p of onDisk.phases)if(p.tasks.some((x)=>x.id===capturedTaskId))return!0;return!1}})}}catch(error49){if(error49 instanceof LedgerStaleWriterError)throw new PlanConcurrentModificationError(`Concurrent plan modification detected after retries: ${error49.message}. Please retry the operation.`);throw error49}}try{for(let phase of validated.phases)for(let task of phase.tasks){let oldTask=oldTaskMap.get(task.id);if(oldTask&&oldTask.status!==task.status){let eventInput={plan_id:derivePlanId(validated),event_type:"task_status_changed",task_id:task.id,phase_id:phase.id,from_status:oldTask.status,to_status:task.status,source:"savePlan"},capturedFromStatus=oldTask.status,capturedTaskId=task.id;await retryCasWithBackoff(directory,eventInput,{expectedHash:currentHash,planHashAfter:hashAfter,verifyValid:async()=>{let onDisk=await _internals9.loadPlanJsonOnly(directory);if(!onDisk)return!0;for(let p of onDisk.phases){let t=p.tasks.find((x)=>x.id===capturedTaskId);if(t)return t.status===capturedFromStatus}return!1}})}}}catch(error49){if(error49 instanceof LedgerStaleWriterError)throw new PlanConcurrentModificationError(`Concurrent plan modification detected after retries: ${error49.message}. Please retry the operation.`);throw error49}}let ledgerStatusTaskIds=collectLedgerStatusTaskIds(await readLedgerEvents(directory)),replayedBeforeProjection=await replayFromLedger(directory),projectionCandidate=replayedBeforeProjection?mergeStatusesTakingPrecedence(validated,replayedBeforeProjection,ledgerStatusTaskIds):validated;if(replayedBeforeProjection&&computePlanHash(replayedBeforeProjection)!==computePlanHash(projectionCandidate))await takeSnapshotEvent(directory,projectionCandidate,{planHashAfter:computePlanHash(projectionCandidate),source:"savePlan_structural_projection"});let projectedPlan=projectionCandidate,SNAPSHOT_INTERVAL=50,latestSeq=await getLatestLedgerSeq(directory);if(latestSeq>0&&latestSeq%SNAPSHOT_INTERVAL===0)await takeSnapshotWithRetry(directory,projectedPlan,{planHashAfter:computePlanHash(projectedPlan),source:"savePlan_manager"});let swarmDir=path14.resolve(directory,".swarm"),planPath=path14.join(swarmDir,"plan.json"),tempPath=path14.join(swarmDir,`plan.json.tmp.${Date.now()}.${Math.floor(Math.random()*1e9)}`);try{await bunWrite(tempPath,JSON.stringify(projectedPlan,null,2)),renameSync6(tempPath,planPath)}finally{try{unlinkSync4(tempPath)}catch{}}try{let markerPath=path14.join(swarmDir,".plan-write-marker"),inProgressMarker=JSON.stringify({source:"plan_manager",timestamp:new Date().toISOString(),phases_count:projectedPlan.phases.length,tasks_count:projectedPlan.phases.reduce((sum,p)=>sum+p.tasks.length,0),in_progress:!0});await bunWrite(markerPath,inProgressMarker)}catch{}try{let contentHash=computePlanContentHash(projectedPlan),markdown=derivePlanMarkdown(projectedPlan),markdownWithHash=`<!-- PLAN_HASH: ${contentHash} -->
|
|
198
198
|
${markdown}`,mdPath=path14.join(swarmDir,"plan.md"),mdTempPath=path14.join(swarmDir,`plan.md.tmp.${Date.now()}.${Math.floor(Math.random()*1e9)}`);try{await bunWrite(mdTempPath,markdownWithHash),renameSync6(mdTempPath,mdPath)}finally{try{unlinkSync4(mdTempPath)}catch{}}}catch(mdError){let message=mdError instanceof Error?mdError.message:String(mdError);warn(`[savePlan] plan.md write failed (non-fatal, plan.json is authoritative): ${message}`);try{emit("plan_md_write_failed",{directory,error:message,timestamp:new Date().toISOString()})}catch{}}try{let markerPath=path14.join(swarmDir,".plan-write-marker"),tasksCount=projectedPlan.phases.reduce((sum,phase)=>sum+phase.tasks.length,0),marker=JSON.stringify({source:"plan_manager",timestamp:new Date().toISOString(),phases_count:projectedPlan.phases.length,tasks_count:tasksCount,in_progress:!1});await bunWrite(markerPath,marker)}catch{}}async function rebuildPlan(directory,plan,options){let targetPlan=plan??await replayFromLedger(directory);if(!targetPlan)return null;let swarmDir=path14.join(directory,".swarm"),planPath=path14.join(swarmDir,"plan.json"),mdPath=path14.join(swarmDir,"plan.md"),tempPlanPath=path14.join(swarmDir,`plan.json.rebuild.${Date.now()}.${Math.floor(Math.random()*1e9)}`);await bunWrite(tempPlanPath,JSON.stringify(targetPlan,null,2)),renameSync6(tempPlanPath,planPath);try{let markerPath=path14.join(swarmDir,".plan-write-marker"),inProgressMarker=JSON.stringify({source:"plan_manager",timestamp:new Date().toISOString(),phases_count:targetPlan.phases.length,tasks_count:targetPlan.phases.reduce((sum,phase)=>sum+phase.tasks.length,0),in_progress:!0});await bunWrite(markerPath,inProgressMarker)}catch{}try{let contentHash=computePlanContentHash(targetPlan),markdown=derivePlanMarkdown(targetPlan),markdownWithHash=`<!-- PLAN_HASH: ${contentHash} -->
|
|
199
199
|
${markdown}`,tempMdPath=path14.join(swarmDir,`plan.md.rebuild.${Date.now()}.${Math.floor(Math.random()*1e9)}`);await bunWrite(tempMdPath,markdownWithHash),renameSync6(tempMdPath,mdPath)}finally{try{let markerPath=path14.join(swarmDir,".plan-write-marker"),tasksCount=targetPlan.phases.reduce((sum,phase)=>sum+phase.tasks.length,0),marker=JSON.stringify({source:"plan_manager",timestamp:new Date().toISOString(),phases_count:targetPlan.phases.length,tasks_count:tasksCount,in_progress:!1});await bunWrite(markerPath,marker)}catch{}}try{let planId=derivePlanId(targetPlan),planHashAfter=computePlanHash(targetPlan);await appendLedgerEvent(directory,{event_type:"plan_rebuilt",source:"rebuildPlan",plan_id:planId,payload:{reason:options?.reason??"ledger_replay_recovery",phases_count:targetPlan.phases.length,tasks_count:targetPlan.phases.reduce((sum,p)=>sum+p.tasks.length,0)}},{planHashAfter})}catch{}return targetPlan}async function closePlanTerminalState(directory,plan,options){let planId=derivePlanId(plan),validated=PlanSchema.parse(plan),hashAfter=computePlanHash(validated);for(let taskId of options.closedTaskIds){let taskPhaseId;for(let phase of validated.phases)if(phase.tasks.some((t)=>t.id===taskId)){taskPhaseId=phase.id;break}let fromStatus=options.originalStatuses?.get(taskId)??"in_progress";await appendLedgerEvent(directory,{plan_id:planId,event_type:"task_status_changed",task_id:taskId,phase_id:taskPhaseId,from_status:fromStatus,to_status:"closed",source:"close_terminal"},{planHashAfter:hashAfter})}for(let phaseId of options.closedPhaseIds)await appendLedgerEvent(directory,{plan_id:planId,event_type:"phase_completed",phase_id:phaseId,source:"close_terminal"},{planHashAfter:hashAfter});await takeSnapshotEvent(directory,validated,{planHashAfter:hashAfter,source:"close_terminal"});let swarmDir=path14.join(directory,".swarm"),planPath=path14.join(swarmDir,"plan.json"),tempPlanPath=path14.join(swarmDir,`plan.json.close.${Date.now()}.${Math.floor(Math.random()*1e9)}`);await bunWrite(tempPlanPath,JSON.stringify(validated,null,2)),renameSync6(tempPlanPath,planPath);try{let markerPath=path14.join(swarmDir,".plan-write-marker"),inProgressMarker=JSON.stringify({source:"plan_manager_close",timestamp:new Date().toISOString(),phases_count:validated.phases.length,tasks_count:validated.phases.reduce((sum,phase)=>sum+phase.tasks.length,0),in_progress:!0});await bunWrite(markerPath,inProgressMarker)}catch{}try{let mdPath=path14.join(swarmDir,"plan.md"),contentHash=computePlanContentHash(validated),markdown=derivePlanMarkdown(validated),markdownWithHash=`<!-- PLAN_HASH: ${contentHash} -->
|
|
200
200
|
${markdown}`,mdTempPath=path14.join(swarmDir,`plan.md.close.${Date.now()}.${Math.floor(Math.random()*1e9)}`);await bunWrite(mdTempPath,markdownWithHash),renameSync6(mdTempPath,mdPath)}finally{try{let markerPath=path14.join(swarmDir,".plan-write-marker"),tasksCount=validated.phases.reduce((sum,phase)=>sum+phase.tasks.length,0),marker=JSON.stringify({source:"plan_manager_close",timestamp:new Date().toISOString(),phases_count:validated.phases.length,tasks_count:tasksCount,in_progress:!1});await bunWrite(markerPath,marker)}catch{}}}async function isTaskSettled(directory,taskId){let plan=await _internals9.loadPlanJsonOnly(directory);if(!plan)return!1;let task=plan.phases.flatMap((p)=>p.tasks).find((t)=>t.id===taskId);if(!task)return!1;return task.status!=="pending"&&task.status!=="in_progress"}async function updateTaskStatus(directory,taskId,status,options){let derivePhaseStatusFromTasks=(tasks)=>{if(tasks.length>0&&tasks.every((task)=>task.status==="completed"))return"complete";if(tasks.some((task)=>task.status==="in_progress"))return"in_progress";if(tasks.some((task)=>task.status==="blocked"))return"blocked";return"pending"};if(status==="in_progress"&&options?.force!==!0){let currentPlan=await _internals9.loadPlanJsonOnly(directory);if(currentPlan){let currentTask=currentPlan.phases.flatMap((p)=>p.tasks).find((t)=>t.id===taskId);if(currentTask&¤tTask.status!=="pending"&¤tTask.status!=="in_progress")return warn(`[updateTaskStatus] refusing to re-open settled task ${taskId} (${currentTask.status}) to in_progress without force`),currentPlan}}let MAX_OUTER_RETRIES=1;for(let attempt=0;attempt<=MAX_OUTER_RETRIES;attempt++){let plan=await _internals9.loadPlan(directory);if(plan===null)throw Error(`Plan not found in directory: ${directory}`);let taskFound=!1,updatedPhases=plan.phases.map((phase)=>{let updatedTasks=phase.tasks.map((task)=>{if(task.id===taskId)return taskFound=!0,{...task,status};return task});return{...phase,status:derivePhaseStatusFromTasks(updatedTasks),tasks:updatedTasks}});if(!taskFound)throw Error(`Task not found: ${taskId}`);let updatedPlan={...plan,phases:updatedPhases};try{if(await savePlan(directory,updatedPlan,{preserveCompletedStatuses:!1}),status==="completed"&&_internals9.isGitRepo(directory)&&_internals9.isEpicModeActiveForProject(directory)){let mergeFailure=_internals9.getWorktreeMergeFailure(taskId);if(mergeFailure)return criticalWarn(`[plan/manager] Rule 2 auto-commit SKIPPED for ${taskId}: worktree merge-back ${mergeFailure.outcome} at stage '${mergeFailure.stage}'. The task's changes are NOT in the main tree, so no completion marker is written (Rule 3 must not treat this task as satisfied). Resolve the preserved worktree, then re-run the task. Detail: ${mergeFailure.message}`),updatedPlan;try{let taskDescription;for(let phase of updatedPlan.phases){let found=phase.tasks.find((t)=>t.id===taskId);if(found){taskDescription=found.description;break}}let canonicalScope=_internals9.readTaskScopes(directory,taskId);await _internals9.commitTaskCompletion(directory,taskId,taskDescription,canonicalScope??void 0)}catch(commitErr){criticalWarn(`[plan/manager] Rule 2 auto-commit for ${taskId} threw (non-fatal): ${commitErr instanceof Error?commitErr.message:String(commitErr)}`)}}return updatedPlan}catch(error49){if(error49 instanceof PlanConcurrentModificationError&&attempt<MAX_OUTER_RETRIES)continue;throw error49}}throw Error("updateTaskStatus: unexpected loop exit")}function derivePlanMarkdown(plan){let statusMap={pending:"PENDING",in_progress:"IN PROGRESS",complete:"COMPLETE",completed:"COMPLETE",blocked:"BLOCKED",closed:"CLOSED"},now=new Date().toISOString(),currentPhase=plan.current_phase??1,phaseStatus=statusMap[plan.phases[currentPhase-1]?.status]||"PENDING",markdown=`# ${plan.title}
|
|
@@ -246,7 +246,7 @@ ${warnings.map((w)=>` - ${w}`).join(`
|
|
|
246
246
|
BEGIN
|
|
247
247
|
SELECT RAISE(ABORT, 'qa_gate_profile row is locked and cannot be modified after critic approval');
|
|
248
248
|
END`}],_projectDbs=new Map});import{createHash as createHash5}from"node:crypto";function rowToProfile(row){let parsed={};try{let maybeGates=JSON.parse(row.gates);if(maybeGates&&typeof maybeGates==="object"&&!Array.isArray(maybeGates))parsed=maybeGates}catch{parsed={}}let raw=parsed;if(raw.council_mode===!0&&raw.phase_council===void 0)parsed.phase_council=!0,parsed.council_mode=!1;let knownKeys=new Set(Object.keys(DEFAULT_QA_GATES)),filteredParsed={};for(let key of Object.keys(parsed))if(knownKeys.has(key))filteredParsed[key]=parsed[key];let gates={...DEFAULT_QA_GATES,...filteredParsed};return{id:row.id,plan_id:row.plan_id,created_at:row.created_at,project_type:row.project_type,gates,locked_at:row.locked_at,locked_by_snapshot_seq:row.locked_by_snapshot_seq}}function getProfile(directory,planId){if(!projectDbExists(directory))return null;let row=getProjectDb(directory).query("SELECT * FROM qa_gate_profile WHERE plan_id = ?").get(planId);return row?rowToProfile(row):null}function hasAnyProfileWithEnabledGate(directory,gate){if(!projectDbExists(directory))return!1;let rows=getProjectDb(directory).query("SELECT gates FROM qa_gate_profile").all();for(let row of rows)try{if(JSON.parse(row.gates)?.[gate]===!0)return!0}catch{}return!1}function getOrCreateProfile(directory,planId,projectType){let existing=_internals11.getProfile(directory,planId);if(existing)return existing;let db=getProjectDb(directory),gatesJson=JSON.stringify(DEFAULT_QA_GATES),insert=db.transaction(()=>{db.run("INSERT INTO qa_gate_profile (plan_id, project_type, gates) VALUES (?, ?, ?)",[planId,projectType??null,gatesJson])});try{insert()}catch(err){if(!(err instanceof Error?err.message:String(err)).toLowerCase().includes("unique"))throw err}let after=_internals11.getProfile(directory,planId);if(!after)throw Error(`Failed to create or load QA gate profile for plan_id=${planId}`);return after}function setGates(directory,planId,gates){let current=_internals11.getProfile(directory,planId);if(!current)throw Error(`No QA gate profile found for plan_id=${planId} — call getOrCreateProfile first`);if(current.locked_at!==null)throw Error("Cannot modify gates: QA gate profile is locked after critic approval");let merged={...current.gates};for(let key of Object.keys(gates)){let incoming=gates[key];if(incoming===void 0)continue;if(incoming===!1&¤t.gates[key]===!0)throw Error(`Cannot disable gate '${key}': sessions can only ratchet tighter`);if(incoming===!0)merged[key]=!0}getProjectDb(directory).run("UPDATE qa_gate_profile SET gates = ? WHERE plan_id = ?",[JSON.stringify(merged),planId]);let updated=_internals11.getProfile(directory,planId);if(!updated)throw Error(`Failed to re-read QA gate profile after update for plan_id=${planId}`);return updated}function lockProfile(directory,planId,snapshotSeq){let current=_internals11.getProfile(directory,planId);if(!current)throw Error(`No QA gate profile found for plan_id=${planId} — cannot lock`);if(current.locked_at!==null)return current;getProjectDb(directory).run("UPDATE qa_gate_profile SET locked_at = datetime('now'), locked_by_snapshot_seq = ? WHERE plan_id = ?",[snapshotSeq,planId]);let locked=_internals11.getProfile(directory,planId);if(!locked)throw Error(`Failed to re-read locked QA gate profile for plan_id=${planId}`);return locked}function computeProfileHash(profile){let payload=JSON.stringify({plan_id:profile.plan_id,gates:profile.gates});return createHash5("sha256").update(payload).digest("hex")}function getEffectiveGates(profile,sessionOverrides){let merged={...profile.gates};for(let key of Object.keys(sessionOverrides))if(sessionOverrides[key]===!0)merged[key]=!0;return merged}var _internals11,DEFAULT_QA_GATES;var init_qa_gate_profile=__esm(()=>{init_project_db();_internals11={getProfile,getOrCreateProfile,setGates,getEffectiveGates,computeProfileHash,hasAnyProfileWithEnabledGate},DEFAULT_QA_GATES={reviewer:!0,test_engineer:!0,council_mode:!1,sme_enabled:!0,critic_pre_plan:!0,hallucination_guard:!1,sast_enabled:!0,mutation_test:!1,phase_council:!1,drift_check:!0,final_council:!1}});function detectHostOS(){switch(process.platform){case"win32":return"windows";case"darwin":return"macos";case"linux":return"linux";default:return"unknown"}}function detectShellFamily(){if(process.env.PSModulePath)return"powershell";if((process.env.ComSpec??"").toLowerCase().includes("cmd.exe"))return"cmd";let shell=process.env.SHELL??"";if(shell.includes("bash"))return"bash";if(shell.includes("zsh"))return"zsh";if(shell.includes("/sh"))return"sh";return"unknown"}function detectExecutionMode(hostOS){if(process.env.WSL_DISTRO_NAME)return"wsl";if(hostOS==="linux"){if(["DOCKER_CONTAINER","KUBERNETES_SERVICE_HOST","CONTAINER"].some((k)=>process.env[k]))return"docker"}return"native"}function deriveOperatingMode(hostOS,_executionMode){if(hostOS==="linux")return"linux";if(hostOS==="macos")return"macos-native";if(hostOS==="windows")return"windows-native";return"unknown"}function buildCommandPolicy(profile){if(profile.isWindowsNative)return{preferredShell:"powershell",avoidPosixExamples:!0,preferNodeApis:!0,preferToolingOverShell:!0,pathExampleStyle:"windows",examples:{listDir:"Get-ChildItem -Force",removeFile:"Remove-Item file.tmp",setEnv:'$env:DEBUG = "1"',printEnv:"$env:PATH",searchText:'Get-ChildItem -Recurse src | Select-String "foo"'}};return{preferredShell:profile.shellFamily==="unknown"?"bash":profile.shellFamily,avoidPosixExamples:!1,preferNodeApis:!0,preferToolingOverShell:!0,pathExampleStyle:"posix",examples:{listDir:"ls -la",removeFile:"rm file.tmp",setEnv:"export DEBUG=1",printEnv:"echo $PATH",searchText:'grep -R "foo" src/'}}}function detectEnvironmentProfile(){let hostOS=detectHostOS(),shellFamily=detectShellFamily(),executionMode=detectExecutionMode(hostOS),operatingMode=deriveOperatingMode(hostOS,executionMode),isWindowsNative=hostOS==="windows"&&executionMode==="native",isWindowsDocker=!1;return{hostOS,shellFamily,executionMode,operatingMode,isWindowsNative,isWindowsDocker:!1,isWSL:executionMode==="wsl",pathStyle:hostOS==="windows"?"windows":"posix",shellCommandPreference:isWindowsNative?"powershell-native":"posix-native",evidence:{processPlatform:process.platform,comspec:process.env.ComSpec,psModulePath:process.env.PSModulePath,termProgram:process.env.TERM_PROGRAM,shell:process.env.SHELL,wslDistroName:process.env.WSL_DISTRO_NAME,containerMarkers:["DOCKER_CONTAINER","KUBERNETES_SERVICE_HOST","CONTAINER"].filter((k)=>!!process.env[k])}}}function deriveCommandPolicy(profile){return buildCommandPolicy(profile)}async function computeComplexity(directory,changedFiles){let functionCount=0,astChangeCount=0,maxFileComplexity=0;for(let file2 of changedFiles){if(!/\.(ts|js|tsx|jsx|py|go|rs)$/.test(file2))continue;try{let fs12=await import("node:fs"),filePath=(await import("node:path")).join(directory,file2);if(!fs12.existsSync(filePath))continue;let content=fs12.readFileSync(filePath,"utf-8"),fileFunctionCount=content.match(/\b(function|def|func|fn)\s+\w+/g)?.length||0;functionCount+=fileFunctionCount;let lines=content.split(`
|
|
249
|
-
`).length,estimatedChanges=Math.min(lines/10,50);astChangeCount+=estimatedChanges;let fileComplexity=fileFunctionCount+lines/100;maxFileComplexity=Math.max(maxFileComplexity,fileComplexity)}catch{}}return{fileCount:changedFiles.length,functionCount,astChangeCount:Math.round(astChangeCount),maxFileComplexity:Math.round(maxFileComplexity*10)/10}}function routeReview(metrics){if(metrics.fileCount>=5||metrics.functionCount>=10||metrics.astChangeCount>=30||metrics.maxFileComplexity>=15)return{reviewerCount:2,testEngineerCount:2,depth:"double",reason:`High complexity: ${metrics.fileCount} files, ${metrics.functionCount} functions, complexity score ${metrics.maxFileComplexity}`};return{reviewerCount:1,testEngineerCount:1,depth:"single",reason:`Standard complexity: ${metrics.fileCount} files, ${metrics.functionCount} functions`}}async function routeReviewForChanges(directory,changedFiles){let metrics=await computeComplexity(directory,changedFiles);return routeReview(metrics)}function shouldParallelizeReview(routing){return routing.depth==="double"}import*as os4 from"node:os";import*as path17 from"node:path";async function runGit(args2,cwd,timeoutMs=WORKTREE_TIMEOUT_MS){let proc=_internals12.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{}}}async function checkPathBudget(worktreeRoot,directory){if(_internals12.platform!=="win32")return{ok:!0};let longPaths;try{longPaths=await _internals12.getCoreLongPaths(directory)}catch{}if(longPaths==="true")return{ok:!0};let proc=_internals12.bunSpawn(["git","ls-files"],{cwd:directory,timeout:WORKTREE_TIMEOUT_MS,stdin:"ignore",stdout:"pipe",stderr:"ignore",env:{...process.env,LC_ALL:"C"}});try{let exitCode=await proc.exited,stdout=await proc.stdout.text();if(exitCode!==0||stdout.trim().length===0)return{ok:!0};let files=stdout.split(/\r?\n/),longest=0;for(let file2 of files)if(file2.length>longest)longest=file2.length;let totalPathLength=worktreeRoot.length+1+longest;if(totalPathLength>=WIN_PATH_BUDGET)return{ok:!1,error:`Total path budget exceeded: worktree root "${worktreeRoot}" (${worktreeRoot.length} chars) + longest file "${files.find((f)=>f.length===longest)}" (${longest} chars) = ${totalPathLength} chars (budget: ${WIN_PATH_BUDGET})`,suggestion:"Set config.worktree_dir to a shorter absolute path, or let the auto-shorten feature relocate the worktree to the system temp directory."};return{ok:!0}}finally{try{proc.kill()}catch{}}}function shortenWorktreePath(_directory,sessionId,laneId){return path17.join(
|
|
249
|
+
`).length,estimatedChanges=Math.min(lines/10,50);astChangeCount+=estimatedChanges;let fileComplexity=fileFunctionCount+lines/100;maxFileComplexity=Math.max(maxFileComplexity,fileComplexity)}catch{}}return{fileCount:changedFiles.length,functionCount,astChangeCount:Math.round(astChangeCount),maxFileComplexity:Math.round(maxFileComplexity*10)/10}}function routeReview(metrics){if(metrics.fileCount>=5||metrics.functionCount>=10||metrics.astChangeCount>=30||metrics.maxFileComplexity>=15)return{reviewerCount:2,testEngineerCount:2,depth:"double",reason:`High complexity: ${metrics.fileCount} files, ${metrics.functionCount} functions, complexity score ${metrics.maxFileComplexity}`};return{reviewerCount:1,testEngineerCount:1,depth:"single",reason:`Standard complexity: ${metrics.fileCount} files, ${metrics.functionCount} functions`}}async function routeReviewForChanges(directory,changedFiles){let metrics=await computeComplexity(directory,changedFiles);return routeReview(metrics)}function shouldParallelizeReview(routing){return routing.depth==="double"}import{realpathSync as realpathSync3}from"node:fs";import*as os4 from"node:os";import*as path17 from"node:path";async function runGit(args2,cwd,timeoutMs=WORKTREE_TIMEOUT_MS){let proc=_internals12.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{}}}async function checkPathBudget(worktreeRoot,directory){if(_internals12.platform!=="win32")return{ok:!0};let longPaths;try{longPaths=await _internals12.getCoreLongPaths(directory)}catch{}if(longPaths==="true")return{ok:!0};let proc=_internals12.bunSpawn(["git","ls-files"],{cwd:directory,timeout:WORKTREE_TIMEOUT_MS,stdin:"ignore",stdout:"pipe",stderr:"ignore",env:{...process.env,LC_ALL:"C"}});try{let exitCode=await proc.exited,stdout=await proc.stdout.text();if(exitCode!==0||stdout.trim().length===0)return{ok:!0};let files=stdout.split(/\r?\n/),longest=0;for(let file2 of files)if(file2.length>longest)longest=file2.length;let totalPathLength=worktreeRoot.length+1+longest;if(totalPathLength>=WIN_PATH_BUDGET)return{ok:!1,error:`Total path budget exceeded: worktree root "${worktreeRoot}" (${worktreeRoot.length} chars) + longest file "${files.find((f)=>f.length===longest)}" (${longest} chars) = ${totalPathLength} chars (budget: ${WIN_PATH_BUDGET})`,suggestion:"Set config.worktree_dir to a shorter absolute path, or let the auto-shorten feature relocate the worktree to the system temp directory."};return{ok:!0}}finally{try{proc.kill()}catch{}}}function shortenWorktreePath(_directory,sessionId,laneId){let tmp=_internals12.osTmpdir();try{tmp=realpathSync3(tmp)}catch{}return path17.join(tmp,"swwt",sessionId,laneId)}function makeWorktreeBranchName(sessionId,id,options){if(options.branchStyle==="legacy-lane"&&options.purpose==="lane")return`swarm-lane/${sessionId}/${id}`;return`swarm/${options.purpose}/${sessionId}/${id}`}async function provisionWorktree(directory,id,sessionId,options){let branchName=makeWorktreeBranchName(sessionId,id,options),worktreePath=options.worktreeDir?path17.resolve(directory,options.worktreeDir,sessionId,id):path17.resolve(path17.dirname(directory),".swarm-worktrees",sessionId,id),budgetResult=await checkPathBudget(worktreePath,directory);if(budgetResult.ok===!1)if(options.worktreeDir)console.warn(`[swarm] Path budget warning: ${budgetResult.error} ${budgetResult.suggestion}`);else{let shortPath=shortenWorktreePath(directory,sessionId,id);if((await checkPathBudget(shortPath,directory)).ok===!1)return{error:budgetResult.error};worktreePath=shortPath}if((await runGit(["show-ref","--verify","--quiet",`refs/heads/${branchName}`],directory)).exitCode===0){let listResult=await runGit(["worktree","list","--porcelain"],directory),normalizeGitPath=(p)=>{let lexical=p.replace(/\\/g,"/").replace(/\/+$/,"");try{return realpathSync3(p).replace(/\\/g,"/").replace(/\/+$/,"")}catch{return lexical}},expectedPath=normalizeGitPath(worktreePath),entries=[],current={path:"",branch:void 0};if(listResult.exitCode!==0){let raw=listResult.stderr.trim()||listResult.stdout.trim();return{error:`worktree enumeration failed: ${raw.length>500?`${raw.slice(0,500)}... (truncated)`:raw}`}}for(let rawLine of listResult.stdout.split(`
|
|
250
250
|
`)){let line=rawLine.trim();if(line.startsWith("worktree ")){if(current.path)entries.push(current);current={path:normalizeGitPath(line.slice(9)),branch:void 0}}else if(line.startsWith("branch "))current.branch=line.slice(7)}if(current.path)entries.push(current);let branchIsActiveSomewhere=entries.some((e)=>e.branch===`refs/heads/${branchName}`),expectedPathIsRegistered=entries.some((e)=>e.path===expectedPath);if(branchIsActiveSomewhere||expectedPathIsRegistered)return{error:`Branch already exists and worktree is active: ${branchName} (owned by another session)`};console.warn(`[swarm] adopting existing branch ${branchName} (stale worktree)`);let adoptResult=await runGit(["worktree","add","-f",worktreePath,branchName],directory);if(adoptResult.exitCode!==0)return{error:`Failed to adopt existing worktree: ${adoptResult.stderr.trim()||adoptResult.stdout.trim()}`};return{worktreePath,branchName,purpose:options.purpose,id,sessionId}}let addResult=await runGit(["worktree","add","-b",branchName,worktreePath,"HEAD"],directory);if(addResult.exitCode!==0)return{error:`Failed to create worktree: ${addResult.stderr.trim()||addResult.stdout.trim()}`};return{worktreePath,branchName,purpose:options.purpose,id,sessionId}}async function removeWorktree(worktreePath,projectRoot){let isWindows=_internals12.platform==="win32",MAX_RETRIES=4,RETRY_DELAY_MS=2000,lastError="";for(let attempt=0;attempt<4;attempt++){let result=await runGit(["worktree","remove",worktreePath],projectRoot);if(result.exitCode===0)return{success:!0};if(lastError=result.stderr.trim()||result.stdout.trim(),isWindows&&(lastError.includes("EBUSY")||lastError.includes("EPERM"))&&attempt<3){await _internals12.sleep(2000);continue}return{error:lastError}}return{error:lastError}}async function autoCommitDirty(worktreePath){let addResult=await runGit(["add","-A"],worktreePath);if(addResult.exitCode!==0)return{committed:!1,reason:`git add failed: ${addResult.stderr.trim()||addResult.stdout.trim()}`};let commitResult=await runGit(["commit","-m","swarm-lane: auto-commit before cleanup"],worktreePath);if(commitResult.exitCode!==0){let stderr=commitResult.stderr.trim(),stdout=commitResult.stdout.trim();if(stderr.includes("nothing to commit")||stdout.includes("nothing to commit")||stderr.includes("nothing added to commit"))return{committed:!1,reason:"Nothing to commit"};return{committed:!1,reason:`git commit failed: ${stderr||stdout}`}}return{committed:!0,message:"swarm-lane: auto-commit before cleanup"}}function isSafeToClean(candidatePath){let normalized=candidatePath.replace(/\\/g,"/").toLowerCase();return SAFE_CLEAN_PATTERNS.some((pattern)=>{let p=pattern.toLowerCase();if(p.endsWith("/"))return normalized.startsWith(p)||normalized.includes(`/${p}`);return normalized.endsWith(p)})}async function cleanUntrackedFiles(worktreePath){let dryRun=await runGit(["clean","-fdn"],worktreePath);if(dryRun.exitCode===0){let unsafePaths=dryRun.stdout.trim().split(`
|
|
251
251
|
`).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 runGit(["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([runGit(["status","--porcelain"],directory),runGit(["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 _internals12,WORKTREE_TIMEOUT_MS=30000,WIN_PATH_BUDGET=250,SAFE_CLEAN_PATTERNS;var init_core3=__esm(()=>{init_bun_compat();_internals12={bunSpawn,platform:process.platform,sleep:(ms)=>new Promise((resolve11)=>setTimeout(resolve11,ms)),osTmpdir:()=>os4.tmpdir(),getCoreLongPaths:async(directory)=>{let result=await runGit(["config","core.longpaths"],directory);if(result.exitCode!==0)return;let value=result.stdout.trim().toLowerCase();return value===""?void 0:value}};SAFE_CLEAN_PATTERNS=["dist/","build/",".turbo/","coverage/","node_modules/.cache/",".log",".tmp",".o",".pyc",".class"]});async function runGit2(args2,cwd,timeoutMs=MERGE_TIMEOUT_MS){let proc=_internals13.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(`
|
|
252
252
|
`);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 runGit2(["merge","--no-edit",branchName],primaryDir);break;case"rebase":result=await runGit2(["rebase",branchName],primaryDir);break;case"cherry-pick":{let mergeBaseResult=await runGit2(["merge-base","HEAD",branchName],primaryDir);if(mergeBaseResult.exitCode===0&&mergeBaseResult.stdout.trim()){let mergeBase=mergeBaseResult.stdout.trim();result=await runGit2(["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 runGit2(["cherry-pick",branchName],primaryDir);break}}if(result.exitCode===0)return{merged:!0,strategy};let combinedOutput=`${result.stderr}
|
|
@@ -425,7 +425,7 @@ ${request.task??""}`,terms=Array.from(extractFtsTerms(text)).slice(0,40);if(term
|
|
|
425
425
|
ALTER TABLE memory_recall_usage ADD COLUMN unit_id TEXT;
|
|
426
426
|
CREATE INDEX IF NOT EXISTS idx_memory_recall_usage_unit_id
|
|
427
427
|
ON memory_recall_usage(unit_id);
|
|
428
|
-
`}];FTS_STOP_WORDS=new Set(["a","an","and","are","as","at","be","by","for","from","goal","how","in","into","is","it","of","on","or","role","task","that","the","this","to","user","what","when","with"])});import{realpathSync as realpathSync3}from"node:fs";import*as path23 from"node:path";function markAsPooled(provider){let originalClose=provider.close;if(provider.close=()=>{return releaseProvider(provider),Promise.resolve()},provider[POOLED_MARKER]=!0,originalClose)provider[REAL_CLOSE]=originalClose}function callRealClose(provider){let realClose=provider[REAL_CLOSE];try{realClose?.call(provider)}catch(err){let msg=err instanceof Error?err.message:String(err);if(process.env.OPENCODE_SWARM_DEBUG==="1")console.debug(`[provider-pool] real close failed: ${msg}`)}}function isPooledProvider(provider){return POOLED_MARKER in provider}function getOrCreateProvider(directory,config2){let key=resolvePoolKey(directory),existing=entriesByKey.get(key);if(existing)return moveToHead(existing),existing.refCount++,existing.provider;for(let deferred of deferredEntries)if(deferred.key===key){if(deferredEntries.delete(deferred),entriesByKey.size>=MAX_POOL_SIZE)evictLru();if(deferred.prev=null,deferred.next=head,head)head.prev=deferred;if(head=deferred,!tail)tail=deferred;return entriesByKey.set(key,deferred),deferred.refCount++,deferred.provider}let provider=new SQLiteMemoryProvider(directory,config2);if(markAsPooled(provider),entriesByKey.size>=MAX_POOL_SIZE)evictLru();let entry={key,provider,refCount:1,prev:null,next:head};if(head)head.prev=entry;if(head=entry,!tail)tail=entry;return entriesByKey.set(key,entry),provider}function releaseProvider(provider){for(let[_key,entry]of entriesByKey)if(entry.provider===provider){entry.refCount=Math.max(0,entry.refCount-1);return}for(let entry of deferredEntries)if(entry.provider===provider){if(entry.refCount--,entry.refCount<=0)deferredEntries.delete(entry),callRealClose(provider);return}if(isPooledProvider(provider))callRealClose(provider)}function evictLru(){if(!tail)return;let evicted=tail;if(entriesByKey.delete(evicted.key),unlinkEntry(evicted),evicted.refCount>0)deferredEntries.add(evicted);else callRealClose(evicted.provider)}function moveToHead(entry){if(head===entry)return;if(unlinkEntry(entry),entry.prev=null,entry.next=head,head)head.prev=entry;if(head=entry,!tail)tail=entry}function unlinkEntry(entry){if(entry.prev)entry.prev.next=entry.next;if(entry.next)entry.next.prev=entry.prev;if(head===entry)head=entry.next;if(tail===entry)tail=entry.prev}function resolvePoolKey(directory){try{return realpathSync3(directory)}catch{return path23.resolve(directory)}}function evictAndClose(directory){let key=resolvePoolKey(directory),active=entriesByKey.get(key);if(active)entriesByKey.delete(key),unlinkEntry(active),callRealClose(active.provider);for(let deferred of[...deferredEntries])if(deferred.key===key)deferredEntries.delete(deferred),callRealClose(deferred.provider)}var MAX_POOL_SIZE=16,POOLED_MARKER,REAL_CLOSE,head=null,tail=null,entriesByKey,deferredEntries;var init_provider_pool=__esm(()=>{init_sqlite_provider();POOLED_MARKER=Symbol("opencode-swarm-pooled-provider"),REAL_CLOSE=Symbol("opencode-swarm-real-close"),entriesByKey=new Map,deferredEntries=new Set});import{createHash as createHash7}from"node:crypto";import{existsSync as existsSync14,readFileSync as readFileSync9}from"node:fs";import*as path24 from"node:path";class MemoryGateway{context;config;provider;now;disposed=!1;constructor(context,options={}){this.context=context;this.config=resolveMemoryConfig(options.config??DEFAULT_MEMORY_CONFIG),this.provider=options.provider??createConfiguredMemoryProvider(context.directory,this.config),this.now=options.now??(()=>new Date)}isEnabled(){return this.config.enabled}async dispose(){if(this.disposed)return;this.disposed=!0,await this.provider.close?.()}deriveAllowedScopes(){let resolvedRoot=path24.resolve(this.context.directory),repoId=createStableId(readGitRemoteUrl(resolvedRoot)??path24.basename(resolvedRoot)),scopes=[{type:"workspace",workspaceId:createStableId(path24.dirname(resolvedRoot))},{type:"repository",repoId,repoRoot:resolvedRoot}];if(this.context.runId||this.context.sessionID)scopes.push({type:"run",runId:this.context.runId??this.context.sessionID});if(this.context.agentId||this.context.agentRole)scopes.push({type:"agent",agentId:this.context.agentId??this.context.agentRole,runId:this.context.runId??this.context.sessionID});return scopes}async recall(input){this.assertEnabled();let query=normalizeMemoryText(input.query);if(query.length<3)throw new MemoryValidationError("query must be at least 3 characters");let maxItems=clampInt(input.maxItems??this.config.recall.defaultMaxItems,1,20),tokenBudget=clampInt(input.tokenBudget??this.config.recall.defaultTokenBudget,100,5000),generatedAt=this.now().toISOString(),allowedScopes=this.deriveAllowedScopes(),scopes=input.scopes?validateRequestedScopes(input.scopes,allowedScopes):allowedScopes,request={query,task:input.task,agentRole:this.context.agentRole,mode:input.mode??"manual",scopes,kinds:input.kinds,maxItems,tokenBudget,minScore:input.minScore??this.config.recall.minScore,requireQuerySignal:input.requireQuerySignal,includeExpired:input.includeExpired},recallResult=this.provider.recallWithDiagnostics?await this.provider.recallWithDiagnostics(request):{items:await this.provider.recall(request)},bundle=toRecallBundle({id:createBundleId(query,generatedAt),query,generatedAt,items:recallResult.items,tokenBudget,diagnostics:recallResult.diagnostics?{injectionSkipReason:input.mode==="injection"?resolveInjectionSkipReason(recallResult.diagnostics):void 0,candidateCount:recallResult.diagnostics.candidateCount,preScoredFilteredCount:recallResult.diagnostics.preScoredFilteredCount,noSignalCount:recallResult.diagnostics.noSignalCount,belowThresholdCount:recallResult.diagnostics.belowThresholdCount}:void 0});return await this.provider.recordRecallUsage?.({bundleId:bundle.id,query,scopes,kinds:input.kinds,memoryIds:bundle.items.map((item)=>item.record.id),scores:bundle.items.map((item)=>item.score),tokenEstimate:bundle.tokenEstimate,agentRole:this.context.agentRole,runId:this.context.runId??this.context.sessionID,unitId:this.context.unitId,timestamp:generatedAt}),bundle}async propose(input){if(this.assertEnabled(),!this.provider.createProposal)throw new MemoryValidationError("memory provider does not support proposals");let redactedFields=new Set,redactProposalField=(field,value)=>{let redacted=redactSecrets(value);if(redacted!==value)redactedFields.add(field);return redacted},rationale=redactProposalField("rationale",normalizeMemoryText(input.rationale));if(!rationale)throw new MemoryValidationError("rationale is required");let evidenceRefs=(input.evidenceRefs??[]).map((ref)=>normalizeMemoryText(ref)).filter(Boolean).map((ref)=>redactProposalField("evidenceRefs",ref)).slice(0,20),needsRecord=input.operation==="add"||input.operation==="update"||input.operation==="supersede",proposedRecord,status="pending",reviewer,reviewedAt,rejectionReason,targetMemoryId=input.targetMemoryId===void 0?void 0:redactProposalField("targetMemoryId",normalizeMemoryText(input.targetMemoryId)),relatedMemoryIds=input.relatedMemoryIds?.map((id)=>redactProposalField("relatedMemoryIds",normalizeMemoryText(id))),proposalText=`${input.operation}:${targetMemoryId??""}`;if(needsRecord){if(!input.kind)throw new MemoryValidationError("kind is required for this operation");if(!input.text)throw new MemoryValidationError("text is required for this operation");proposalText=input.text;let normalizedText=normalizeMemoryText(input.text),redactedText=redactProposalField("text",normalizedText),extractedPaths=extractFilePaths(evidenceRefs),extractedSymbols=extractSymbols(evidenceRefs),recordMetadata={};if(extractedPaths.length>0)recordMetadata.files=extractedPaths;if(extractedSymbols.length>0)recordMetadata.symbols=extractedSymbols;proposedRecord=this.createRecord({kind:input.kind,text:redactedText,evidenceRefs,source:sourceFromEvidence(evidenceRefs,this.context),metadata:recordMetadata}),validateMemoryRecordRules(proposedRecord,{rejectDurableSecrets:this.config.redaction.rejectDurableSecrets})}if(redactedFields.size>0)status="rejected",reviewer="auto_policy",reviewedAt=this.now().toISOString(),rejectionReason=`proposal field(s) contained a likely secret and were redacted: ${Array.from(redactedFields).join(", ")}`;if((input.operation==="update"||input.operation==="delete"||input.operation==="supersede")&&!targetMemoryId)throw new MemoryValidationError(`${input.operation} proposals require targetMemoryId`);if(input.operation==="merge"&&(relatedMemoryIds??[]).length<2)throw new MemoryValidationError("merge proposals require relatedMemoryIds");let createdAt=this.now().toISOString(),proposer=this.context.agentId??this.context.agentRole??this.context.sessionID??"unknown",proposal={id:createProposalId({createdAt,proposer,text:proposalText}),operation:input.operation,proposedRecord,targetMemoryId,relatedMemoryIds,proposedBy:{agentRole:this.context.agentRole,agentId:this.context.agentId,runId:this.context.runId??this.context.sessionID},rationale,evidenceRefs,status,reviewer,reviewedAt,rejectionReason,createdAt,metadata:{}};return this.provider.createProposal(proposal)}async listMemories(filter={}){return this.assertEnabled(),this.provider.list(filter)}async listProposals(filter){if(this.assertEnabled(),!this.provider.listProposals)throw new MemoryValidationError("memory provider does not support proposals");return this.provider.listProposals(filter)}async listRecallUsage(filter){if(this.assertEnabled(),!this.provider.listRecallUsage)return[];return this.provider.listRecallUsage(filter)}async upsertCurated(record2){this.assertEnabled();let parsed=validateMemoryRecordRules(record2,{rejectDurableSecrets:this.config.redaction.rejectDurableSecrets});return this.provider.upsert(parsed)}async applyCuratorDecision(decision){if(this.assertEnabled(),!this.provider.applyCuratorDecision)throw new MemoryValidationError("memory provider does not support curator decisions");let parsed=validateCuratorMemoryDecision(decision),resolved=this.resolveCuratorDecision(parsed);return this.provider.applyCuratorDecision(resolved)}createRecord(input){let now=this.now().toISOString(),text=normalizeMemoryText(input.text),scope=this.resolveRecordScope(input.scope),kind=input.kind,stability=input.stability??(kind==="scratch"?"ephemeral":"durable"),expiresAt=kind==="scratch"?new Date(this.now().getTime()+604800000).toISOString():void 0,recordBase={scope,kind,text};return{id:createMemoryId(recordBase),scope,kind,text,tags:normalizeTags2(input.tags??inferTags(text)),confidence:clamp(input.confidence??0.5,0,1),stability,source:input.source??sourceFromEvidence(input.evidenceRefs??[],this.context),createdAt:now,updatedAt:now,expiresAt,contentHash:computeMemoryContentHash(recordBase),metadata:input.metadata??{}}}resolveCuratorDecision(decision){switch(decision.action){case"add":return{action:"add",proposalId:decision.proposalId,memory:this.createRecordFromNew(decision.memory)};case"supersede":return{action:"supersede",proposalId:decision.proposalId,oldMemoryId:decision.oldMemoryId,replacement:this.createRecordFromNew(decision.replacement),reason:normalizeMemoryText(decision.reason)};case"update":{let patch=normalizeMemoryPatch(decision.patch);if(patch.scope)patch.scope=this.resolveRecordScope(patch.scope);return{action:"update",proposalId:decision.proposalId,targetMemoryId:decision.targetMemoryId,patch,reason:normalizeMemoryText(decision.reason)}}case"reject":case"noop":return{action:decision.action,proposalId:decision.proposalId,reason:normalizeMemoryText(decision.reason)}}}createRecordFromNew(input){let record2=this.createRecord({kind:input.kind,text:input.text,scope:input.scope,tags:input.tags,confidence:input.confidence,stability:input.stability,source:input.source,metadata:input.metadata}),next=input.expiresAt?{...record2,expiresAt:input.expiresAt}:record2;return validateMemoryRecordRules(next,{rejectDurableSecrets:this.config.redaction.rejectDurableSecrets})}resolveRecordScope(scope){let allowedScopes=this.deriveAllowedScopes();if(!scope){let defaultScope=allowedScopes[1]??allowedScopes[0];if(!defaultScope)throw new MemoryValidationError("memory scope is not available for this context");return defaultScope}return validateRequestedScopes([scope],allowedScopes,"memory scope is not allowed for this context"),scope}assertEnabled(){if(!this.config.enabled)throw new MemoryDisabledError}}function createMemoryGateway(context,options={}){return new MemoryGateway(context,options)}function createConfiguredMemoryProvider(directory,config2){if(config2.provider==="sqlite")return getOrCreateProvider(directory,config2);return new LocalJsonlMemoryProvider(directory,config2)}function sourceFromEvidence(evidenceRefs,context){let first=evidenceRefs[0];if(!first)return{type:"agent",createdBy:context.agentId??context.agentRole};if(/^https?:\/\//i.test(first))return{type:"web",url:first};if(/^[a-f0-9]{40}$/i.test(first))return{type:"commit",commitSha:first};let filePath=extractFilePaths(evidenceRefs)[0]??first;if(filePath!==first&&(filePath.includes("/")||filePath.includes("\\")||filePath.includes(".")))return{type:"file",filePath};if(first.includes("/")||first.includes("\\")||first.includes("."))return{type:"file",filePath:first};return{type:"manual",ref:first}}function createStableId(value){return createHash7("sha256").update(value.toLowerCase()).digest("hex").slice(0,16)}function readGitRemoteUrl(directory){if(gitRemoteUrlCache.has(directory))return gitRemoteUrlCache.get(directory);let gitConfigPath=path24.join(directory,".git","config");if(!existsSync14(gitConfigPath)){gitRemoteUrlCache.set(directory,void 0);return}try{let remoteUrl=readFileSync9(gitConfigPath,"utf-8").match(/\[remote "origin"\][\s\S]*?\n\s*url\s*=\s*(.+)/)?.[1]?.trim();return gitRemoteUrlCache.set(directory,remoteUrl),remoteUrl}catch{gitRemoteUrlCache.set(directory,void 0);return}}function validateRequestedScopes(requested,allowed,disallowedMessage="recall scope is not allowed for this context"){if(requested.length===0)throw new MemoryValidationError("recall scopes must not be empty");let allowedKeys=new Set(allowed.map(scopeKey));for(let scope of requested)if(!allowedKeys.has(scopeKey(scope)))throw new MemoryValidationError(disallowedMessage);return requested}function resolveInjectionSkipReason(diagnostics){if(diagnostics.returnedCount>0)return;if(diagnostics.candidateCount===0)return"no_results";let signalEligibleCount=diagnostics.candidateCount-diagnostics.preScoredFilteredCount-diagnostics.suppressedLowQCount;if(signalEligibleCount>0&&diagnostics.noSignalCount>0&&diagnostics.noSignalCount>=signalEligibleCount)return"no_signal";if(diagnostics.belowThresholdCount>0)return"below_threshold";return"no_results"}function scopeKey(scope){return JSON.stringify({type:scope.type,userId:scope.userId,workspaceId:scope.workspaceId,projectId:scope.projectId,repoId:scope.repoId,repoRoot:scope.repoRoot?path24.resolve(scope.repoRoot):void 0,runId:scope.runId,agentId:scope.agentId})}function clamp(value,min,max){return Math.min(max,Math.max(min,value))}function clampInt(value,min,max){return Math.trunc(clamp(value,min,max))}function normalizeTags2(tags){return Array.from(new Set(tags.map((tag)=>tag.toLowerCase().replace(/[^\w-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")).filter(Boolean))).slice(0,32)}function normalizeMemoryPatch(patch){return{...patch,text:patch.text===void 0?void 0:normalizeMemoryText(patch.text),tags:patch.tags===void 0?void 0:normalizeTags2(patch.tags)}}function inferTags(text){let lower=text.toLowerCase(),tags=[];for(let[tag,pattern]of[["testing",/\b(test|spec|bun|jest|vitest)\b/],["tooling",/\b(pnpm|npm|yarn|bun|biome|eslint|typescript)\b/],["security",/\b(security|auth|token|secret|password|csp)\b/],["api",/\b(api|endpoint|graphql|rest|sdk)\b/],["architecture",/\b(architecture|decision|adr|pattern)\b/],["failure",/\b(fail|failure|regression|flaky|timeout)\b/]])if(pattern.test(lower))tags.push(tag);return tags}function extractFilePaths(refs){let seen=new Set,paths=[];for(let ref of refs){FILE_PATH_REGEX.lastIndex=0;let matches=ref.match(FILE_PATH_REGEX);if(!matches)continue;for(let m of matches)if(!seen.has(m)){if(seen.add(m),paths.push(m),paths.length>=20)return paths}}return paths}function extractSymbols(refs){let seen=new Set,symbols=[],identRegex=/\b[a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*\b/g;for(let ref of refs){identRegex.lastIndex=0;let matches=ref.match(identRegex);if(!matches)continue;for(let m of matches)if(m.length>=3&&!seen.has(m)&&!RESERVED_IDENTIFIERS.has(m)){if(seen.add(m),symbols.push(m),symbols.length>=20)return symbols}}return symbols}var gitRemoteUrlCache,FILE_PATH_REGEX,RESERVED_IDENTIFIERS;var init_gateway=__esm(()=>{init_config2();init_errors4();init_local_jsonl_provider();init_prompt_block();init_provider_pool();init_redaction();init_schema2();gitRemoteUrlCache=new Map;FILE_PATH_REGEX=/\b(?:src|tests|test|docs|scripts|packages|lib|config|examples|internal|cmd|pkg|bin|tools|cli|api|server|client|app|core|utils|hooks|services|commands|agents|memory)\/[A-Za-z0-9._/@+-]+/g,RESERVED_IDENTIFIERS=new Set(["const","let","var","function","class","interface","type","async","await","return","if","else","for","while","do","switch","case","break","continue","new","this","super","extends","implements","import","export","from","default","try","catch","finally","throw","typeof","instanceof","in","of","as","yield","static","get","set","readonly","public","private","protected"])});async function applyCouncilReward(provider,opts){let bundles=await provider.listRecallUsage?.({runId:opts.runId})??[];if(bundles.length===0)return{memoriesRewarded:0};let attributedBundles=bundles.filter((bundle)=>bundle.unitId==null||opts.unitId==null||bundle.unitId===opts.unitId),distinctIds=new Set;for(let bundle of attributedBundles)for(let id of bundle.memoryIds)distinctIds.add(id);let result=await(provider.withTransaction?provider.withTransaction(async()=>{let updates=new Map;for(let id of distinctIds){let rec=await provider.get(id);if(!rec)continue;let qBefore=getQValue(rec,opts.initialQValue),qAfter=applyEmaUpdate(qBefore,opts.reward,opts.eta);updates.set(id,{rec,qBefore,qAfter})}for(let[id,{rec,qBefore,qAfter}]of updates)await provider.upsert(setQValue(rec,qAfter)),await provider.appendRewardEvent?.({memoryId:id,runId:opts.runId,unitId:opts.unitId,verdict:opts.verdictLabel??"APPROVE",reward:opts.reward,qBefore,qAfter,verdictSynthesisJson:opts.verdictSynthesisJson,timestamp:opts.timestamp});return updates}):(async()=>{let updates=new Map;for(let id of distinctIds){let rec=await provider.get(id);if(!rec)continue;let qBefore=getQValue(rec,opts.initialQValue),qAfter=applyEmaUpdate(qBefore,opts.reward,opts.eta);updates.set(id,{rec,qBefore,qAfter})}for(let[id,{rec,qBefore,qAfter}]of updates)await provider.upsert(setQValue(rec,qAfter)),await provider.appendRewardEvent?.({memoryId:id,runId:opts.runId,unitId:opts.unitId,verdict:opts.verdictLabel??"APPROVE",reward:opts.reward,qBefore,qAfter,verdictSynthesisJson:opts.verdictSynthesisJson,timestamp:opts.timestamp});return updates})()),memoriesRewarded=result.size,rewardedRecords=[...result.values()].map(({rec})=>rec);try{await propagateReward(provider,opts,rewardedRecords,distinctIds)}catch(err){log(`[memory:propagation] skipped after error: ${err instanceof Error?err.message:String(err)}`)}return{memoriesRewarded}}async function propagateReward(provider,opts,sources,directlyRewardedIds){if(sources.length===0)return;let qConfig=opts.qLearning??DEFAULT_QLEARNING_CONFIG,fraction=qConfig.propagationFraction,fanoutCap=qConfig.propagationFanoutCap,windowDays=qConfig.propagationWindowDays,relatednessThreshold=qConfig.propagationRelatednessThreshold;if(!Number.isFinite(fraction)||fraction<=0)return;if(!Number.isFinite(fanoutCap)||fanoutCap<=0)return;if(!Number.isFinite(windowDays)||windowDays<=0)return;if(!Number.isFinite(relatednessThreshold))return;if(typeof provider.list!=="function")return;let nowMs=Date.parse(opts.timestamp);if(!Number.isFinite(nowMs))return;let windowMs=windowDays*MS_PER_DAY2,recencyById=await buildRetrievalRecency(provider);if(!recencyById)return;let orderedSources=[...sources].sort((a,b)=>a.id.localeCompare(b.id)),scheduled=new Map,listCache=new Map;for(let source of orderedSources){let scopeKey2=stableScopeKey(source.scope),cacheKey=`${scopeKey2}::${source.kind}`,candidates=listCache.get(cacheKey);if(!candidates)candidates=await provider.list({scopes:[source.scope],kinds:[source.kind]}),listCache.set(cacheKey,candidates);let sourceTokens=tokenize(source.text),qualified=[];for(let cand of candidates){if(cand.id===source.id)continue;if(directlyRewardedIds.has(cand.id))continue;if(stableScopeKey(cand.scope)!==scopeKey2)continue;if(cand.kind!==source.kind)continue;let retrievedAt=recencyById.get(cand.id);if(retrievedAt===void 0)continue;if(nowMs-retrievedAt>windowMs)continue;let overlap2=jaccard(sourceTokens,tokenize(cand.text));if(overlap2<relatednessThreshold)continue;qualified.push({record:cand,overlap:overlap2})}qualified.sort((a,b)=>b.overlap-a.overlap||a.record.id.localeCompare(b.record.id));let cap=Math.trunc(fanoutCap),selected=qualified.slice(0,cap),dropped=qualified.length-selected.length;if(dropped>0)log(`[memory:propagation] fan-out cap reached for source ${source.id}: ${qualified.length} qualified, ${selected.length} propagated, ${dropped} dropped by cap ${cap}`);for(let{record:record2}of selected)if(!scheduled.has(record2.id))scheduled.set(record2.id,record2)}for(let record2 of scheduled.values()){let qBefore=getQValue(record2,opts.initialQValue),qAfter=applyPropagatedEmaUpdate(qBefore,opts.reward,opts.eta,fraction);await provider.upsert(setQValue(record2,qAfter)),await provider.appendRewardEvent?.({memoryId:record2.id,runId:opts.runId,unitId:opts.unitId,verdict:`${opts.verdictLabel??"APPROVE"}${PROPAGATED_VERDICT_SUFFIX}`,reward:opts.reward,qBefore,qAfter,verdictSynthesisJson:opts.verdictSynthesisJson,timestamp:opts.timestamp})}}function truncateObjectForJson(obj,capBytes){let asIs=JSON.stringify(obj);if(asIs.length<=capBytes)return obj;if(JSON.stringify({...obj,__truncated__:!0}).length<=capBytes)return{...obj,__truncated__:!0};return{__truncated__:!0,originalSize:asIs.length,cap:capBytes}}async function buildRetrievalRecency(provider){if(typeof provider.listRecallUsage!=="function")return null;let since=new Date(Date.now()-RECENCY_WINDOW_MS).toISOString(),usage=await provider.listRecallUsage({since,limit:RECENCY_EVENT_LIMIT})??[],recency=new Map;for(let event of usage){let ts=Date.parse(event.timestamp);if(!Number.isFinite(ts))continue;for(let id of event.memoryIds){let prev=recency.get(id);if(prev===void 0||ts>prev)recency.set(id,ts)}}return recency}var PROPAGATED_VERDICT_SUFFIX="_PROPAGATED",MS_PER_DAY2=86400000,RECENCY_WINDOW_MS,RECENCY_EVENT_LIMIT=1000;var init_reward_capture=__esm(()=>{init_logger();init_config2();init_schema2();init_scoring();RECENCY_WINDOW_MS=30*MS_PER_DAY2});var require_constants=__commonJS((exports,module)=>{var POSIX_CHARS={DOT_LITERAL:"\\.",PLUS_LITERAL:"\\+",QMARK_LITERAL:"\\?",SLASH_LITERAL:"\\/",ONE_CHAR:"(?=.)",QMARK:"[^/]",END_ANCHOR:"(?:\\/|$)",DOTS_SLASH:"\\.{1,2}(?:\\/|$)",NO_DOT:"(?!\\.)",NO_DOTS:"(?!(?:^|\\/)\\.{1,2}(?:\\/|$))",NO_DOT_SLASH:"(?!\\.{0,1}(?:\\/|$))",NO_DOTS_SLASH:"(?!\\.{1,2}(?:\\/|$))",QMARK_NO_DOT:"[^.\\/]",STAR:"[^/]*?",START_ANCHOR:"(?:^|\\/)",SEP:"/"},WINDOWS_CHARS={...POSIX_CHARS,SLASH_LITERAL:"[\\\\/]",QMARK:"[^\\\\/]",STAR:"[^\\\\/]*?",DOTS_SLASH:"\\.{1,2}(?:[\\\\/]|$)",NO_DOT:"(?!\\.)",NO_DOTS:"(?!(?:^|[\\\\/])\\.{1,2}(?:[\\\\/]|$))",NO_DOT_SLASH:"(?!\\.{0,1}(?:[\\\\/]|$))",NO_DOTS_SLASH:"(?!\\.{1,2}(?:[\\\\/]|$))",QMARK_NO_DOT:"[^.\\\\/]",START_ANCHOR:"(?:^|[\\\\/])",END_ANCHOR:"(?:[\\\\/]|$)",SEP:"\\"},POSIX_REGEX_SOURCE={__proto__:null,alnum:"a-zA-Z0-9",alpha:"a-zA-Z",ascii:"\\x00-\\x7F",blank:" \\t",cntrl:"\\x00-\\x1F\\x7F",digit:"0-9",graph:"\\x21-\\x7E",lower:"a-z",print:"\\x20-\\x7E ",punct:"\\-!\"#$%&'()\\*+,./:;<=>?@[\\]^_`{|}~",space:" \\t\\r\\n\\v\\f",upper:"A-Z",word:"A-Za-z0-9_",xdigit:"A-Fa-f0-9"};module.exports={DEFAULT_MAX_EXTGLOB_RECURSION:0,MAX_LENGTH:65536,POSIX_REGEX_SOURCE,REGEX_BACKSLASH:/\\(?![*+?^${}(|)[\]])/g,REGEX_NON_SPECIAL_CHARS:/^[^@![\].,$*+?^{}()|\\/]+/,REGEX_SPECIAL_CHARS:/[-*+?.^${}(|)[\]]/,REGEX_SPECIAL_CHARS_BACKREF:/(\\?)((\W)(\3*))/g,REGEX_SPECIAL_CHARS_GLOBAL:/([-*+?.^${}(|)[\]])/g,REGEX_REMOVE_BACKSLASH:/(?:\[.*?[^\\]\]|\\(?=.))/g,REPLACEMENTS:{__proto__:null,"***":"*","**/**":"**","**/**/**":"**"},CHAR_0:48,CHAR_9:57,CHAR_UPPERCASE_A:65,CHAR_LOWERCASE_A:97,CHAR_UPPERCASE_Z:90,CHAR_LOWERCASE_Z:122,CHAR_LEFT_PARENTHESES:40,CHAR_RIGHT_PARENTHESES:41,CHAR_ASTERISK:42,CHAR_AMPERSAND:38,CHAR_AT:64,CHAR_BACKWARD_SLASH:92,CHAR_CARRIAGE_RETURN:13,CHAR_CIRCUMFLEX_ACCENT:94,CHAR_COLON:58,CHAR_COMMA:44,CHAR_DOT:46,CHAR_DOUBLE_QUOTE:34,CHAR_EQUAL:61,CHAR_EXCLAMATION_MARK:33,CHAR_FORM_FEED:12,CHAR_FORWARD_SLASH:47,CHAR_GRAVE_ACCENT:96,CHAR_HASH:35,CHAR_HYPHEN_MINUS:45,CHAR_LEFT_ANGLE_BRACKET:60,CHAR_LEFT_CURLY_BRACE:123,CHAR_LEFT_SQUARE_BRACKET:91,CHAR_LINE_FEED:10,CHAR_NO_BREAK_SPACE:160,CHAR_PERCENT:37,CHAR_PLUS:43,CHAR_QUESTION_MARK:63,CHAR_RIGHT_ANGLE_BRACKET:62,CHAR_RIGHT_CURLY_BRACE:125,CHAR_RIGHT_SQUARE_BRACKET:93,CHAR_SEMICOLON:59,CHAR_SINGLE_QUOTE:39,CHAR_SPACE:32,CHAR_TAB:9,CHAR_UNDERSCORE:95,CHAR_VERTICAL_LINE:124,CHAR_ZERO_WIDTH_NOBREAK_SPACE:65279,extglobChars(chars){return{"!":{type:"negate",open:"(?:(?!(?:",close:`))${chars.STAR})`},"?":{type:"qmark",open:"(?:",close:")?"},"+":{type:"plus",open:"(?:",close:")+"},"*":{type:"star",open:"(?:",close:")*"},"@":{type:"at",open:"(?:",close:")"}}},globChars(win32){return win32===!0?WINDOWS_CHARS:POSIX_CHARS}}});var require_utils=__commonJS((exports)=>{var{REGEX_BACKSLASH,REGEX_REMOVE_BACKSLASH,REGEX_SPECIAL_CHARS,REGEX_SPECIAL_CHARS_GLOBAL}=require_constants();exports.isObject=(val)=>val!==null&&typeof val==="object"&&!Array.isArray(val);exports.hasRegexChars=(str)=>REGEX_SPECIAL_CHARS.test(str);exports.isRegexChar=(str)=>str.length===1&&exports.hasRegexChars(str);exports.escapeRegex=(str)=>str.replace(REGEX_SPECIAL_CHARS_GLOBAL,"\\$1");exports.toPosixSlashes=(str)=>str.replace(REGEX_BACKSLASH,"/");exports.isWindows=()=>{if(typeof navigator<"u"&&navigator.platform){let platform=navigator.platform.toLowerCase();return platform==="win32"||platform==="windows"}if(typeof process<"u"&&process.platform)return process.platform==="win32";return!1};exports.removeBackslashes=(str)=>{return str.replace(REGEX_REMOVE_BACKSLASH,(match)=>{return match==="\\"?"":match})};exports.escapeLast=(input,char,lastIdx)=>{let idx=input.lastIndexOf(char,lastIdx);if(idx===-1)return input;if(input[idx-1]==="\\")return exports.escapeLast(input,char,idx-1);return`${input.slice(0,idx)}\\${input.slice(idx)}`};exports.removePrefix=(input,state={})=>{let output=input;if(output.startsWith("./"))output=output.slice(2),state.prefix="./";return output};exports.wrapOutput=(input,state={},options={})=>{let prepend=options.contains?"":"^",append=options.contains?"":"$",output=`${prepend}(?:${input})${append}`;if(state.negated===!0)output=`(?:^(?!${output}).*$)`;return output};exports.basename=(path25,{windows}={})=>{let segs=path25.split(windows?/[\\/]/:"/"),last=segs[segs.length-1];if(last==="")return segs[segs.length-2];return last}});var require_scan=__commonJS((exports,module)=>{var utils=require_utils(),{CHAR_ASTERISK,CHAR_AT,CHAR_BACKWARD_SLASH,CHAR_COMMA,CHAR_DOT,CHAR_EXCLAMATION_MARK,CHAR_FORWARD_SLASH,CHAR_LEFT_CURLY_BRACE,CHAR_LEFT_PARENTHESES,CHAR_LEFT_SQUARE_BRACKET,CHAR_PLUS,CHAR_QUESTION_MARK,CHAR_RIGHT_CURLY_BRACE,CHAR_RIGHT_PARENTHESES,CHAR_RIGHT_SQUARE_BRACKET}=require_constants(),isPathSeparator=(code)=>{return code===CHAR_FORWARD_SLASH||code===CHAR_BACKWARD_SLASH},depth=(token)=>{if(token.isPrefix!==!0)token.depth=token.isGlobstar?1/0:1},scan=(input,options)=>{let opts=options||{},length=input.length-1,scanToEnd=opts.parts===!0||opts.scanToEnd===!0,slashes=[],tokens=[],parts=[],str=input,index=-1,start=0,lastIndex=0,isBrace=!1,isBracket=!1,isGlob=!1,isExtglob=!1,isGlobstar=!1,braceEscaped=!1,backslashes=!1,negated=!1,negatedExtglob=!1,finished=!1,braces=0,prev,code,token={value:"",depth:0,isGlob:!1},eos=()=>index>=length,peek=()=>str.charCodeAt(index+1),advance=()=>{return prev=code,str.charCodeAt(++index)};while(index<length){code=advance();let next;if(code===CHAR_BACKWARD_SLASH){if(backslashes=token.backslashes=!0,code=advance(),code===CHAR_LEFT_CURLY_BRACE)braceEscaped=!0;continue}if(braceEscaped===!0||code===CHAR_LEFT_CURLY_BRACE){braces++;while(eos()!==!0&&(code=advance())){if(code===CHAR_BACKWARD_SLASH){backslashes=token.backslashes=!0,advance();continue}if(code===CHAR_LEFT_CURLY_BRACE){braces++;continue}if(braceEscaped!==!0&&code===CHAR_DOT&&(code=advance())===CHAR_DOT){if(isBrace=token.isBrace=!0,isGlob=token.isGlob=!0,finished=!0,scanToEnd===!0)continue;break}if(braceEscaped!==!0&&code===CHAR_COMMA){if(isBrace=token.isBrace=!0,isGlob=token.isGlob=!0,finished=!0,scanToEnd===!0)continue;break}if(code===CHAR_RIGHT_CURLY_BRACE){if(braces--,braces===0){braceEscaped=!1,isBrace=token.isBrace=!0,finished=!0;break}}}if(scanToEnd===!0)continue;break}if(code===CHAR_FORWARD_SLASH){if(slashes.push(index),tokens.push(token),token={value:"",depth:0,isGlob:!1},finished===!0)continue;if(prev===CHAR_DOT&&index===start+1){start+=2;continue}lastIndex=index+1;continue}if(opts.noext!==!0){if((code===CHAR_PLUS||code===CHAR_AT||code===CHAR_ASTERISK||code===CHAR_QUESTION_MARK||code===CHAR_EXCLAMATION_MARK)===!0&&peek()===CHAR_LEFT_PARENTHESES){if(isGlob=token.isGlob=!0,isExtglob=token.isExtglob=!0,finished=!0,code===CHAR_EXCLAMATION_MARK&&index===start)negatedExtglob=!0;if(scanToEnd===!0){while(eos()!==!0&&(code=advance())){if(code===CHAR_BACKWARD_SLASH){backslashes=token.backslashes=!0,code=advance();continue}if(code===CHAR_RIGHT_PARENTHESES){isGlob=token.isGlob=!0,finished=!0;break}}continue}break}}if(code===CHAR_ASTERISK){if(prev===CHAR_ASTERISK)isGlobstar=token.isGlobstar=!0;if(isGlob=token.isGlob=!0,finished=!0,scanToEnd===!0)continue;break}if(code===CHAR_QUESTION_MARK){if(isGlob=token.isGlob=!0,finished=!0,scanToEnd===!0)continue;break}if(code===CHAR_LEFT_SQUARE_BRACKET){while(eos()!==!0&&(next=advance())){if(next===CHAR_BACKWARD_SLASH){backslashes=token.backslashes=!0,advance();continue}if(next===CHAR_RIGHT_SQUARE_BRACKET){isBracket=token.isBracket=!0,isGlob=token.isGlob=!0,finished=!0;break}}if(scanToEnd===!0)continue;break}if(opts.nonegate!==!0&&code===CHAR_EXCLAMATION_MARK&&index===start){negated=token.negated=!0,start++;continue}if(opts.noparen!==!0&&code===CHAR_LEFT_PARENTHESES){if(isGlob=token.isGlob=!0,scanToEnd===!0){while(eos()!==!0&&(code=advance())){if(code===CHAR_LEFT_PARENTHESES){backslashes=token.backslashes=!0,code=advance();continue}if(code===CHAR_RIGHT_PARENTHESES){finished=!0;break}}continue}break}if(isGlob===!0){if(finished=!0,scanToEnd===!0)continue;break}}if(opts.noext===!0)isExtglob=!1,isGlob=!1;let base=str,prefix="",glob="";if(start>0)prefix=str.slice(0,start),str=str.slice(start),lastIndex-=start;if(base&&isGlob===!0&&lastIndex>0)base=str.slice(0,lastIndex),glob=str.slice(lastIndex);else if(isGlob===!0)base="",glob=str;else base=str;if(base&&base!==""&&base!=="/"&&base!==str){if(isPathSeparator(base.charCodeAt(base.length-1)))base=base.slice(0,-1)}if(opts.unescape===!0){if(glob)glob=utils.removeBackslashes(glob);if(base&&backslashes===!0)base=utils.removeBackslashes(base)}let state={prefix,input,start,base,glob,isBrace,isBracket,isGlob,isExtglob,isGlobstar,negated,negatedExtglob};if(opts.tokens===!0){if(state.maxDepth=0,!isPathSeparator(code))tokens.push(token);state.tokens=tokens}if(opts.parts===!0||opts.tokens===!0){let prevIndex;for(let idx=0;idx<slashes.length;idx++){let n=prevIndex?prevIndex+1:start,i=slashes[idx],value=input.slice(n,i);if(opts.tokens){if(idx===0&&start!==0)tokens[idx].isPrefix=!0,tokens[idx].value=prefix;else tokens[idx].value=value;depth(tokens[idx]),state.maxDepth+=tokens[idx].depth}if(idx!==0||value!=="")parts.push(value);prevIndex=i}if(prevIndex&&prevIndex+1<input.length){let value=input.slice(prevIndex+1);if(parts.push(value),opts.tokens)tokens[tokens.length-1].value=value,depth(tokens[tokens.length-1]),state.maxDepth+=tokens[tokens.length-1].depth}state.slashes=slashes,state.parts=parts}return state};module.exports=scan});var require_parse=__commonJS((exports,module)=>{var constants2=require_constants(),utils=require_utils(),{MAX_LENGTH,POSIX_REGEX_SOURCE,REGEX_NON_SPECIAL_CHARS,REGEX_SPECIAL_CHARS_BACKREF,REPLACEMENTS}=constants2,expandRange=(args2,options)=>{if(typeof options.expandRange==="function")return options.expandRange(...args2,options);args2.sort();let value=`[${args2.join("-")}]`;try{new RegExp(value)}catch(ex){return args2.map((v)=>utils.escapeRegex(v)).join("..")}return value},syntaxError=(type,char)=>{return`Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`},splitTopLevel=(input)=>{let parts=[],bracket=0,paren=0,quote=0,value="",escaped=!1;for(let ch of input){if(escaped===!0){value+=ch,escaped=!1;continue}if(ch==="\\"){value+=ch,escaped=!0;continue}if(ch==='"'){quote=quote===1?0:1,value+=ch;continue}if(quote===0){if(ch==="[")bracket++;else if(ch==="]"&&bracket>0)bracket--;else if(bracket===0){if(ch==="(")paren++;else if(ch===")"&&paren>0)paren--;else if(ch==="|"&&paren===0){parts.push(value),value="";continue}}}value+=ch}return parts.push(value),parts},isPlainBranch=(branch)=>{let escaped=!1;for(let ch of branch){if(escaped===!0){escaped=!1;continue}if(ch==="\\"){escaped=!0;continue}if(/[?*+@!()[\]{}]/.test(ch))return!1}return!0},normalizeSimpleBranch=(branch)=>{let value=branch.trim(),changed=!0;while(changed===!0)if(changed=!1,/^@\([^\\()[\]{}|]+\)$/.test(value))value=value.slice(2,-1),changed=!0;if(!isPlainBranch(value))return;return value.replace(/\\(.)/g,"$1")},hasRepeatedCharPrefixOverlap=(branches)=>{let values=branches.map(normalizeSimpleBranch).filter(Boolean);for(let i=0;i<values.length;i++)for(let j=i+1;j<values.length;j++){let a=values[i],b=values[j],char=a[0];if(!char||a!==char.repeat(a.length)||b!==char.repeat(b.length))continue;if(a===b||a.startsWith(b)||b.startsWith(a))return!0}return!1},parseRepeatedExtglob=(pattern,requireEnd=!0)=>{if(pattern[0]!=="+"&&pattern[0]!=="*"||pattern[1]!=="(")return;let bracket=0,paren=0,quote=0,escaped=!1;for(let i=1;i<pattern.length;i++){let ch=pattern[i];if(escaped===!0){escaped=!1;continue}if(ch==="\\"){escaped=!0;continue}if(ch==='"'){quote=quote===1?0:1;continue}if(quote===1)continue;if(ch==="["){bracket++;continue}if(ch==="]"&&bracket>0){bracket--;continue}if(bracket>0)continue;if(ch==="("){paren++;continue}if(ch===")"){if(paren--,paren===0){if(requireEnd===!0&&i!==pattern.length-1)return;return{type:pattern[0],body:pattern.slice(2,i),end:i}}}}},getStarExtglobSequenceOutput=(pattern)=>{let index=0,chars=[];while(index<pattern.length){let match=parseRepeatedExtglob(pattern.slice(index),!1);if(!match||match.type!=="*")return;let branches=splitTopLevel(match.body).map((branch2)=>branch2.trim());if(branches.length!==1)return;let branch=normalizeSimpleBranch(branches[0]);if(!branch||branch.length!==1)return;chars.push(branch),index+=match.end+1}if(chars.length<1)return;return`${chars.length===1?utils.escapeRegex(chars[0]):`[${chars.map((ch)=>utils.escapeRegex(ch)).join("")}]`}*`},repeatedExtglobRecursion=(pattern)=>{let depth=0,value=pattern.trim(),match=parseRepeatedExtglob(value);while(match)depth++,value=match.body.trim(),match=parseRepeatedExtglob(value);return depth},analyzeRepeatedExtglob=(body,options)=>{if(options.maxExtglobRecursion===!1)return{risky:!1};let max=typeof options.maxExtglobRecursion==="number"?options.maxExtglobRecursion:constants2.DEFAULT_MAX_EXTGLOB_RECURSION,branches=splitTopLevel(body).map((branch)=>branch.trim());if(branches.length>1){if(branches.some((branch)=>branch==="")||branches.some((branch)=>/^[*?]+$/.test(branch))||hasRepeatedCharPrefixOverlap(branches))return{risky:!0}}for(let branch of branches){let safeOutput=getStarExtglobSequenceOutput(branch);if(safeOutput)return{risky:!0,safeOutput};if(repeatedExtglobRecursion(branch)>max)return{risky:!0}}return{risky:!1}},parse5=(input,options)=>{if(typeof input!=="string")throw TypeError("Expected a string");input=REPLACEMENTS[input]||input;let opts={...options},max=typeof opts.maxLength==="number"?Math.min(MAX_LENGTH,opts.maxLength):MAX_LENGTH,len=input.length;if(len>max)throw SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`);let bos={type:"bos",value:"",output:opts.prepend||""},tokens=[bos],capture=opts.capture?"":"?:",PLATFORM_CHARS=constants2.globChars(opts.windows),EXTGLOB_CHARS=constants2.extglobChars(PLATFORM_CHARS),{DOT_LITERAL,PLUS_LITERAL,SLASH_LITERAL,ONE_CHAR,DOTS_SLASH,NO_DOT,NO_DOT_SLASH,NO_DOTS_SLASH,QMARK,QMARK_NO_DOT,STAR,START_ANCHOR}=PLATFORM_CHARS,globstar=(opts2)=>{return`(${capture}(?:(?!${START_ANCHOR}${opts2.dot?DOTS_SLASH:DOT_LITERAL}).)*?)`},nodot=opts.dot?"":NO_DOT,qmarkNoDot=opts.dot?QMARK:QMARK_NO_DOT,star=opts.bash===!0?globstar(opts):STAR;if(opts.capture)star=`(${star})`;if(typeof opts.noext==="boolean")opts.noextglob=opts.noext;let state={input,index:-1,start:0,dot:opts.dot===!0,consumed:"",output:"",prefix:"",backtrack:!1,negated:!1,brackets:0,braces:0,parens:0,quotes:0,globstar:!1,tokens};input=utils.removePrefix(input,state),len=input.length;let extglobs=[],braces=[],stack=[],prev=bos,value,eos=()=>state.index===len-1,peek=state.peek=(n=1)=>input[state.index+n],advance=state.advance=()=>input[++state.index]||"",remaining=()=>input.slice(state.index+1),consume=(value2="",num=0)=>{state.consumed+=value2,state.index+=num},append=(token)=>{state.output+=token.output!=null?token.output:token.value,consume(token.value)},negate=()=>{let count=1;while(peek()==="!"&&(peek(2)!=="("||peek(3)==="?"))advance(),state.start++,count++;if(count%2===0)return!1;return state.negated=!0,state.start++,!0},increment=(type)=>{state[type]++,stack.push(type)},decrement=(type)=>{state[type]--,stack.pop()},push=(tok)=>{if(prev.type==="globstar"){let isBrace=state.braces>0&&(tok.type==="comma"||tok.type==="brace"),isExtglob=tok.extglob===!0||extglobs.length&&(tok.type==="pipe"||tok.type==="paren");if(tok.type!=="slash"&&tok.type!=="paren"&&!isBrace&&!isExtglob)state.output=state.output.slice(0,-prev.output.length),prev.type="star",prev.value="*",prev.output=star,state.output+=prev.output}if(extglobs.length&&tok.type!=="paren")extglobs[extglobs.length-1].inner+=tok.value;if(tok.value||tok.output)append(tok);if(prev&&prev.type==="text"&&tok.type==="text"){prev.output=(prev.output||prev.value)+tok.value,prev.value+=tok.value;return}tok.prev=prev,tokens.push(tok),prev=tok},extglobOpen=(type,value2)=>{let token={...EXTGLOB_CHARS[value2],conditions:1,inner:""};token.prev=prev,token.parens=state.parens,token.output=state.output,token.startIndex=state.index,token.tokensIndex=tokens.length;let output=(opts.capture?"(":"")+token.open;increment("parens"),push({type,value:value2,output:state.output?"":ONE_CHAR}),push({type:"paren",extglob:!0,value:advance(),output}),extglobs.push(token)},extglobClose=(token)=>{let literal2=input.slice(token.startIndex,state.index+1),body=input.slice(token.startIndex+2,state.index),analysis=analyzeRepeatedExtglob(body,opts);if((token.type==="plus"||token.type==="star")&&analysis.risky){let safeOutput=analysis.safeOutput?(token.output?"":ONE_CHAR)+(opts.capture?`(${analysis.safeOutput})`:analysis.safeOutput):void 0,open2=tokens[token.tokensIndex];open2.type="text",open2.value=literal2,open2.output=safeOutput||utils.escapeRegex(literal2);for(let i=token.tokensIndex+1;i<tokens.length;i++)tokens[i].value="",tokens[i].output="",delete tokens[i].suffix;state.output=token.output+open2.output,state.backtrack=!0,push({type:"paren",extglob:!0,value,output:""}),decrement("parens");return}let output=token.close+(opts.capture?")":""),rest;if(token.type==="negate"){let extglobStar=star;if(token.inner&&token.inner.length>1&&token.inner.includes("/"))extglobStar=globstar(opts);if(extglobStar!==star||eos()||/^\)+$/.test(remaining()))output=token.close=`)$))${extglobStar}`;if(token.inner.includes("*")&&(rest=remaining())&&/^\.[^\\/.]+$/.test(rest)){let expression=parse5(rest,{...options,fastpaths:!1}).output;output=token.close=`)${expression})${extglobStar})`}if(token.prev.type==="bos")state.negatedExtglob=!0}push({type:"paren",extglob:!0,value,output}),decrement("parens")};if(opts.fastpaths!==!1&&!/(^[*!]|[/()[\]{}"])/.test(input)){let backslashes=!1,output=input.replace(REGEX_SPECIAL_CHARS_BACKREF,(m,esc2,chars,first,rest,index)=>{if(first==="\\")return backslashes=!0,m;if(first==="?"){if(esc2)return esc2+first+(rest?QMARK.repeat(rest.length):"");if(index===0)return qmarkNoDot+(rest?QMARK.repeat(rest.length):"");return QMARK.repeat(chars.length)}if(first===".")return DOT_LITERAL.repeat(chars.length);if(first==="*"){if(esc2)return esc2+first+(rest?star:"");return star}return esc2?m:`\\${m}`});if(backslashes===!0)if(opts.unescape===!0)output=output.replace(/\\/g,"");else output=output.replace(/\\+/g,(m)=>{return m.length%2===0?"\\\\":m?"\\":""});if(output===input&&opts.contains===!0)return state.output=input,state;return state.output=utils.wrapOutput(output,state,options),state}while(!eos()){if(value=advance(),value==="\x00")continue;if(value==="\\"){let next=peek();if(next==="/"&&opts.bash!==!0)continue;if(next==="."||next===";")continue;if(!next){value+="\\",push({type:"text",value});continue}let match=/^\\+/.exec(remaining()),slashes=0;if(match&&match[0].length>2){if(slashes=match[0].length,state.index+=slashes,slashes%2!==0)value+="\\"}if(opts.unescape===!0)value=advance();else value+=advance();if(state.brackets===0){push({type:"text",value});continue}}if(state.brackets>0&&(value!=="]"||prev.value==="["||prev.value==="[^")){if(opts.posix!==!1&&value===":"){let inner=prev.value.slice(1);if(inner.includes("[")){if(prev.posix=!0,inner.includes(":")){let idx=prev.value.lastIndexOf("["),pre=prev.value.slice(0,idx),rest2=prev.value.slice(idx+2),posix=POSIX_REGEX_SOURCE[rest2];if(posix){if(prev.value=pre+posix,state.backtrack=!0,advance(),!bos.output&&tokens.indexOf(prev)===1)bos.output=ONE_CHAR;continue}}}}if(value==="["&&peek()!==":"||value==="-"&&peek()==="]")value=`\\${value}`;if(value==="]"&&(prev.value==="["||prev.value==="[^"))value=`\\${value}`;if(opts.posix===!0&&value==="!"&&prev.value==="[")value="^";prev.value+=value,append({value});continue}if(state.quotes===1&&value!=='"'){value=utils.escapeRegex(value),prev.value+=value,append({value});continue}if(value==='"'){if(state.quotes=state.quotes===1?0:1,opts.keepQuotes===!0)push({type:"text",value});continue}if(value==="("){increment("parens"),push({type:"paren",value});continue}if(value===")"){if(state.parens===0&&opts.strictBrackets===!0)throw SyntaxError(syntaxError("opening","("));let extglob=extglobs[extglobs.length-1];if(extglob&&state.parens===extglob.parens+1){extglobClose(extglobs.pop());continue}push({type:"paren",value,output:state.parens?")":"\\)"}),decrement("parens");continue}if(value==="["){if(opts.nobracket===!0||!remaining().includes("]")){if(opts.nobracket!==!0&&opts.strictBrackets===!0)throw SyntaxError(syntaxError("closing","]"));value=`\\${value}`}else increment("brackets");push({type:"bracket",value});continue}if(value==="]"){if(opts.nobracket===!0||prev&&prev.type==="bracket"&&prev.value.length===1){push({type:"text",value,output:`\\${value}`});continue}if(state.brackets===0){if(opts.strictBrackets===!0)throw SyntaxError(syntaxError("opening","["));push({type:"text",value,output:`\\${value}`});continue}decrement("brackets");let prevValue=prev.value.slice(1);if(prev.posix!==!0&&prevValue[0]==="^"&&!prevValue.includes("/"))value=`/${value}`;if(prev.value+=value,append({value}),opts.literalBrackets===!1||utils.hasRegexChars(prevValue))continue;let escaped=utils.escapeRegex(prev.value);if(state.output=state.output.slice(0,-prev.value.length),opts.literalBrackets===!0){state.output+=escaped,prev.value=escaped;continue}prev.value=`(${capture}${escaped}|${prev.value})`,state.output+=prev.value;continue}if(value==="{"&&opts.nobrace!==!0){increment("braces");let open2={type:"brace",value,output:"(",outputIndex:state.output.length,tokensIndex:state.tokens.length};braces.push(open2),push(open2);continue}if(value==="}"){let brace=braces[braces.length-1];if(opts.nobrace===!0||!brace){push({type:"text",value,output:value});continue}let output=")";if(brace.dots===!0){let arr=tokens.slice(),range=[];for(let i=arr.length-1;i>=0;i--){if(tokens.pop(),arr[i].type==="brace")break;if(arr[i].type!=="dots")range.unshift(arr[i].value)}output=expandRange(range,opts),state.backtrack=!0}if(brace.comma!==!0&&brace.dots!==!0){let out=state.output.slice(0,brace.outputIndex),toks=state.tokens.slice(brace.tokensIndex);brace.value=brace.output="\\{",value=output="\\}",state.output=out;for(let t of toks)state.output+=t.output||t.value}push({type:"brace",value,output}),decrement("braces"),braces.pop();continue}if(value==="|"){if(extglobs.length>0)extglobs[extglobs.length-1].conditions++;push({type:"text",value});continue}if(value===","){let output=value,brace=braces[braces.length-1];if(brace&&stack[stack.length-1]==="braces")brace.comma=!0,output="|";push({type:"comma",value,output});continue}if(value==="/"){if(prev.type==="dot"&&state.index===state.start+1){state.start=state.index+1,state.consumed="",state.output="",tokens.pop(),prev=bos;continue}push({type:"slash",value,output:SLASH_LITERAL});continue}if(value==="."){if(state.braces>0&&prev.type==="dot"){if(prev.value===".")prev.output=DOT_LITERAL;let brace=braces[braces.length-1];prev.type="dots",prev.output+=value,prev.value+=value,brace.dots=!0;continue}if(state.braces+state.parens===0&&prev.type!=="bos"&&prev.type!=="slash"){push({type:"text",value,output:DOT_LITERAL});continue}push({type:"dot",value,output:DOT_LITERAL});continue}if(value==="?"){if(!(prev&&prev.value==="(")&&opts.noextglob!==!0&&peek()==="("&&peek(2)!=="?"){extglobOpen("qmark",value);continue}if(prev&&prev.type==="paren"){let next=peek(),output=value;if(prev.value==="("&&!/[!=<:]/.test(next)||next==="<"&&!/<([!=]|\w+>)/.test(remaining()))output=`\\${value}`;push({type:"text",value,output});continue}if(opts.dot!==!0&&(prev.type==="slash"||prev.type==="bos")){push({type:"qmark",value,output:QMARK_NO_DOT});continue}push({type:"qmark",value,output:QMARK});continue}if(value==="!"){if(opts.noextglob!==!0&&peek()==="("){if(peek(2)!=="?"||!/[!=<:]/.test(peek(3))){extglobOpen("negate",value);continue}}if(opts.nonegate!==!0&&state.index===0){negate();continue}}if(value==="+"){if(opts.noextglob!==!0&&peek()==="("&&peek(2)!=="?"){extglobOpen("plus",value);continue}if(prev&&prev.value==="("||opts.regex===!1){push({type:"plus",value,output:PLUS_LITERAL});continue}if(prev&&(prev.type==="bracket"||prev.type==="paren"||prev.type==="brace")||state.parens>0){push({type:"plus",value});continue}push({type:"plus",value:PLUS_LITERAL});continue}if(value==="@"){if(opts.noextglob!==!0&&peek()==="("&&peek(2)!=="?"){push({type:"at",extglob:!0,value,output:""});continue}push({type:"text",value});continue}if(value!=="*"){if(value==="$"||value==="^")value=`\\${value}`;let match=REGEX_NON_SPECIAL_CHARS.exec(remaining());if(match)value+=match[0],state.index+=match[0].length;push({type:"text",value});continue}if(prev&&(prev.type==="globstar"||prev.star===!0)){prev.type="star",prev.star=!0,prev.value+=value,prev.output=star,state.backtrack=!0,state.globstar=!0,consume(value);continue}let rest=remaining();if(opts.noextglob!==!0&&/^\([^?]/.test(rest)){extglobOpen("star",value);continue}if(prev.type==="star"){if(opts.noglobstar===!0){consume(value);continue}let prior=prev.prev,before=prior.prev,isStart=prior.type==="slash"||prior.type==="bos",afterStar=before&&(before.type==="star"||before.type==="globstar");if(opts.bash===!0&&(!isStart||rest[0]&&rest[0]!=="/")){push({type:"star",value,output:""});continue}let isBrace=state.braces>0&&(prior.type==="comma"||prior.type==="brace"),isExtglob=extglobs.length&&(prior.type==="pipe"||prior.type==="paren");if(!isStart&&prior.type!=="paren"&&!isBrace&&!isExtglob){push({type:"star",value,output:""});continue}while(rest.slice(0,3)==="/**"){let after=input[state.index+4];if(after&&after!=="/")break;rest=rest.slice(3),consume("/**",3)}if(prior.type==="bos"&&eos()){prev.type="globstar",prev.value+=value,prev.output=globstar(opts),state.output=prev.output,state.globstar=!0,consume(value);continue}if(prior.type==="slash"&&prior.prev.type!=="bos"&&!afterStar&&eos()){state.output=state.output.slice(0,-(prior.output+prev.output).length),prior.output=`(?:${prior.output}`,prev.type="globstar",prev.output=globstar(opts)+(opts.strictSlashes?")":"|$)"),prev.value+=value,state.globstar=!0,state.output+=prior.output+prev.output,consume(value);continue}if(prior.type==="slash"&&prior.prev.type!=="bos"&&rest[0]==="/"){let end=rest[1]!==void 0?"|$":"";state.output=state.output.slice(0,-(prior.output+prev.output).length),prior.output=`(?:${prior.output}`,prev.type="globstar",prev.output=`${globstar(opts)}${SLASH_LITERAL}|${SLASH_LITERAL}${end})`,prev.value+=value,state.output+=prior.output+prev.output,state.globstar=!0,consume(value+advance()),push({type:"slash",value:"/",output:""});continue}if(prior.type==="bos"&&rest[0]==="/"){prev.type="globstar",prev.value+=value,prev.output=`(?:^|${SLASH_LITERAL}|${globstar(opts)}${SLASH_LITERAL})`,state.output=prev.output,state.globstar=!0,consume(value+advance()),push({type:"slash",value:"/",output:""});continue}state.output=state.output.slice(0,-prev.output.length),prev.type="globstar",prev.output=globstar(opts),prev.value+=value,state.output+=prev.output,state.globstar=!0,consume(value);continue}let token={type:"star",value,output:star};if(opts.bash===!0){if(token.output=".*?",prev.type==="bos"||prev.type==="slash")token.output=nodot+token.output;push(token);continue}if(prev&&(prev.type==="bracket"||prev.type==="paren")&&opts.regex===!0){token.output=value,push(token);continue}if(state.index===state.start||prev.type==="slash"||prev.type==="dot"){if(prev.type==="dot")state.output+=NO_DOT_SLASH,prev.output+=NO_DOT_SLASH;else if(opts.dot===!0)state.output+=NO_DOTS_SLASH,prev.output+=NO_DOTS_SLASH;else state.output+=nodot,prev.output+=nodot;if(peek()!=="*")state.output+=ONE_CHAR,prev.output+=ONE_CHAR}push(token)}while(state.brackets>0){if(opts.strictBrackets===!0)throw SyntaxError(syntaxError("closing","]"));state.output=utils.escapeLast(state.output,"["),decrement("brackets")}while(state.parens>0){if(opts.strictBrackets===!0)throw SyntaxError(syntaxError("closing",")"));state.output=utils.escapeLast(state.output,"("),decrement("parens")}while(state.braces>0){if(opts.strictBrackets===!0)throw SyntaxError(syntaxError("closing","}"));state.output=utils.escapeLast(state.output,"{"),decrement("braces")}if(opts.strictSlashes!==!0&&(prev.type==="star"||prev.type==="bracket"))push({type:"maybe_slash",value:"",output:`${SLASH_LITERAL}?`});if(state.backtrack===!0){state.output="";for(let token of state.tokens)if(state.output+=token.output!=null?token.output:token.value,token.suffix)state.output+=token.suffix}return state};parse5.fastpaths=(input,options)=>{let opts={...options},max=typeof opts.maxLength==="number"?Math.min(MAX_LENGTH,opts.maxLength):MAX_LENGTH,len=input.length;if(len>max)throw SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`);input=REPLACEMENTS[input]||input;let{DOT_LITERAL,SLASH_LITERAL,ONE_CHAR,DOTS_SLASH,NO_DOT,NO_DOTS,NO_DOTS_SLASH,STAR,START_ANCHOR}=constants2.globChars(opts.windows),nodot=opts.dot?NO_DOTS:NO_DOT,slashDot=opts.dot?NO_DOTS_SLASH:NO_DOT,capture=opts.capture?"":"?:",state={negated:!1,prefix:""},star=opts.bash===!0?".*?":STAR;if(opts.capture)star=`(${star})`;let globstar=(opts2)=>{if(opts2.noglobstar===!0)return star;return`(${capture}(?:(?!${START_ANCHOR}${opts2.dot?DOTS_SLASH:DOT_LITERAL}).)*?)`},create=(str)=>{switch(str){case"*":return`${nodot}${ONE_CHAR}${star}`;case".*":return`${DOT_LITERAL}${ONE_CHAR}${star}`;case"*.*":return`${nodot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`;case"*/*":return`${nodot}${star}${SLASH_LITERAL}${ONE_CHAR}${slashDot}${star}`;case"**":return nodot+globstar(opts);case"**/*":return`(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${ONE_CHAR}${star}`;case"**/*.*":return`(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`;case"**/.*":return`(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${DOT_LITERAL}${ONE_CHAR}${star}`;default:{let match=/^(.*?)\.(\w+)$/.exec(str);if(!match)return;let source2=create(match[1]);if(!source2)return;return source2+DOT_LITERAL+match[2]}}},output=utils.removePrefix(input,state),source=create(output);if(source&&opts.strictSlashes!==!0)source+=`${SLASH_LITERAL}?`;return source};module.exports=parse5});var require_picomatch=__commonJS((exports,module)=>{var scan=require_scan(),parse5=require_parse(),utils=require_utils(),constants2=require_constants(),isObject2=(val)=>val&&typeof val==="object"&&!Array.isArray(val),picomatch=(glob,options,returnState=!1)=>{if(Array.isArray(glob)){let fns=glob.map((input)=>picomatch(input,options,returnState));return(str)=>{for(let isMatch of fns){let state2=isMatch(str);if(state2)return state2}return!1}}let isState=isObject2(glob)&&glob.tokens&&glob.input;if(glob===""||typeof glob!=="string"&&!isState)throw TypeError("Expected pattern to be a non-empty string");let opts=options||{},posix=opts.windows,regex=isState?picomatch.compileRe(glob,options):picomatch.makeRe(glob,options,!1,!0),state=regex.state;delete regex.state;let isIgnored=()=>!1;if(opts.ignore){let ignoreOpts={...options,ignore:null,onMatch:null,onResult:null};isIgnored=picomatch(opts.ignore,ignoreOpts,returnState)}let matcher=(input,returnObject=!1)=>{let{isMatch,match,output}=picomatch.test(input,regex,options,{glob,posix}),result={glob,state,regex,posix,input,output,match,isMatch};if(typeof opts.onResult==="function")opts.onResult(result);if(isMatch===!1)return result.isMatch=!1,returnObject?result:!1;if(isIgnored(input)){if(typeof opts.onIgnore==="function")opts.onIgnore(result);return result.isMatch=!1,returnObject?result:!1}if(typeof opts.onMatch==="function")opts.onMatch(result);return returnObject?result:!0};if(returnState)matcher.state=state;return matcher};picomatch.test=(input,regex,options,{glob,posix}={})=>{if(typeof input!=="string")throw TypeError("Expected input to be a string");if(input==="")return{isMatch:!1,output:""};let opts=options||{},format=opts.format||(posix?utils.toPosixSlashes:null),match=input===glob,output=match&&format?format(input):input;if(match===!1)output=format?format(input):input,match=output===glob;if(match===!1||opts.capture===!0)if(opts.matchBase===!0||opts.basename===!0)match=picomatch.matchBase(input,regex,options,posix);else match=regex.exec(output);return{isMatch:Boolean(match),match,output}};picomatch.matchBase=(input,glob,options)=>{return(glob instanceof RegExp?glob:picomatch.makeRe(glob,options)).test(utils.basename(input))};picomatch.isMatch=(str,patterns,options)=>picomatch(patterns,options)(str);picomatch.parse=(pattern,options)=>{if(Array.isArray(pattern))return pattern.map((p)=>picomatch.parse(p,options));return parse5(pattern,{...options,fastpaths:!1})};picomatch.scan=(input,options)=>scan(input,options);picomatch.compileRe=(state,options,returnOutput=!1,returnState=!1)=>{if(returnOutput===!0)return state.output;let opts=options||{},prepend=opts.contains?"":"^",append=opts.contains?"":"$",source=`${prepend}(?:${state.output})${append}`;if(state&&state.negated===!0)source=`^(?!${source}).*$`;let regex=picomatch.toRegex(source,options);if(returnState===!0)regex.state=state;return regex};picomatch.makeRe=(input,options={},returnOutput=!1,returnState=!1)=>{if(!input||typeof input!=="string")throw TypeError("Expected a non-empty string");let parsed={negated:!1,fastpaths:!0};if(options.fastpaths!==!1&&(input[0]==="."||input[0]==="*"))parsed.output=parse5.fastpaths(input,options);if(!parsed.output)parsed=parse5(input,options);return picomatch.compileRe(parsed,options,returnOutput,returnState)};picomatch.toRegex=(source,options)=>{try{let opts=options||{};return new RegExp(source,opts.flags||(opts.nocase?"i":""))}catch(err){if(options&&options.debug===!0)throw err;return/$^/}};picomatch.constants=constants2;module.exports=picomatch});var require_picomatch2=__commonJS((exports,module)=>{var pico=require_picomatch(),utils=require_utils();function picomatch(glob,options,returnState=!1){if(options&&(options.windows===null||options.windows===void 0))options={...options,windows:utils.isWindows()};return pico(glob,options,returnState)}Object.assign(picomatch,pico);module.exports=picomatch});var QuickLRU;var init_quick_lru=__esm(()=>{QuickLRU=class QuickLRU extends Map{#size=0;#cache=new Map;#oldCache=new Map;#maxSize;#maxAge;#onEviction;constructor(options={}){super();if(!(options.maxSize&&options.maxSize>0))throw TypeError("`maxSize` must be a number greater than 0");if(typeof options.maxAge==="number"&&options.maxAge===0)throw TypeError("`maxAge` must be a number greater than 0");this.#maxSize=options.maxSize,this.#maxAge=options.maxAge||Number.POSITIVE_INFINITY,this.#onEviction=options.onEviction}get __oldCache(){return this.#oldCache}#emitEvictions(cache){if(typeof this.#onEviction!=="function")return;for(let[key,item]of cache)this.#onEviction(key,item.value)}#deleteIfExpired(key,item){if(typeof item.expiry==="number"&&item.expiry<=Date.now()){if(typeof this.#onEviction==="function")this.#onEviction(key,item.value);return this.delete(key)}return!1}#getOrDeleteIfExpired(key,item){if(this.#deleteIfExpired(key,item)===!1)return item.value}#getItemValue(key,item){return item.expiry?this.#getOrDeleteIfExpired(key,item):item.value}#peek(key,cache){let item=cache.get(key);return this.#getItemValue(key,item)}#set(key,value){if(this.#cache.set(key,value),this.#size++,this.#size>=this.#maxSize)this.#size=0,this.#emitEvictions(this.#oldCache),this.#oldCache=this.#cache,this.#cache=new Map}#moveToRecent(key,item){this.#oldCache.delete(key),this.#set(key,item)}*#entriesAscending(){for(let item of this.#oldCache){let[key,value]=item;if(!this.#cache.has(key)){if(this.#deleteIfExpired(key,value)===!1)yield item}}for(let item of this.#cache){let[key,value]=item;if(this.#deleteIfExpired(key,value)===!1)yield item}}get(key){if(this.#cache.has(key)){let item=this.#cache.get(key);return this.#getItemValue(key,item)}if(this.#oldCache.has(key)){let item=this.#oldCache.get(key);if(this.#deleteIfExpired(key,item)===!1)return this.#moveToRecent(key,item),item.value}}set(key,value,{maxAge=this.#maxAge}={}){let expiry=typeof maxAge==="number"&&maxAge!==Number.POSITIVE_INFINITY?Date.now()+maxAge:void 0;if(this.#cache.has(key))this.#cache.set(key,{value,expiry});else this.#set(key,{value,expiry});return this}has(key){if(this.#cache.has(key))return!this.#deleteIfExpired(key,this.#cache.get(key));if(this.#oldCache.has(key))return!this.#deleteIfExpired(key,this.#oldCache.get(key));return!1}peek(key){if(this.#cache.has(key))return this.#peek(key,this.#cache);if(this.#oldCache.has(key))return this.#peek(key,this.#oldCache)}expiresIn(key){let item=this.#cache.get(key)??this.#oldCache.get(key);if(item)return item.expiry?item.expiry-Date.now():Number.POSITIVE_INFINITY}delete(key){let deleted=this.#cache.delete(key);if(deleted)this.#size--;return this.#oldCache.delete(key)||deleted}clear(){this.#cache.clear(),this.#oldCache.clear(),this.#size=0}resize(newSize){if(!(newSize&&newSize>0))throw TypeError("`maxSize` must be a number greater than 0");let items=[...this.#entriesAscending()],removeCount=items.length-newSize;if(removeCount<0)this.#cache=new Map(items),this.#oldCache=new Map,this.#size=items.length;else{if(removeCount>0)this.#emitEvictions(items.slice(0,removeCount));this.#oldCache=new Map(items.slice(removeCount)),this.#cache=new Map,this.#size=0}this.#maxSize=newSize}evict(count=1){let requested=Number(count);if(!requested||requested<=0)return;let items=[...this.#entriesAscending()],evictCount=Math.trunc(Math.min(requested,Math.max(items.length-1,0)));if(evictCount<=0)return;this.#emitEvictions(items.slice(0,evictCount)),this.#oldCache=new Map(items.slice(evictCount)),this.#cache=new Map,this.#size=0}*keys(){for(let[key]of this)yield key}*values(){for(let[,value]of this)yield value}*[Symbol.iterator](){for(let item of this.#cache){let[key,value]=item;if(this.#deleteIfExpired(key,value)===!1)yield[key,value.value]}for(let item of this.#oldCache){let[key,value]=item;if(!this.#cache.has(key)){if(this.#deleteIfExpired(key,value)===!1)yield[key,value.value]}}}*entriesDescending(){let items=[...this.#cache];for(let i=items.length-1;i>=0;--i){let item=items[i],[key,value]=item;if(this.#deleteIfExpired(key,value)===!1)yield[key,value.value]}items=[...this.#oldCache];for(let i=items.length-1;i>=0;--i){let item=items[i],[key,value]=item;if(!this.#cache.has(key)){if(this.#deleteIfExpired(key,value)===!1)yield[key,value.value]}}}*entriesAscending(){for(let[key,value]of this.#entriesAscending())yield[key,value.value]}get size(){if(!this.#size)return this.#oldCache.size;let oldCacheSize=0;for(let key of this.#oldCache.keys())if(!this.#cache.has(key))oldCacheSize++;return Math.min(this.#size+oldCacheSize,this.#maxSize)}get maxSize(){return this.#maxSize}get maxAge(){return this.#maxAge}entries(){return this.entriesAscending()}forEach(callbackFunction,thisArgument=this){for(let[key,value]of this.entriesAscending())callbackFunction.call(thisArgument,value,key,this)}get[Symbol.toStringTag](){return"QuickLRU"}toString(){return`QuickLRU(${this.size}/${this.maxSize})`}[Symbol.for("nodejs.util.inspect.custom")](){return this.toString()}}});function classifyFile(filePath){let normalized=filePath.toLowerCase().replace(/\\/g,"/");if(normalized.endsWith(".wasm")||normalized.startsWith("dist/")||normalized.includes("/dist/")||normalized.startsWith("build/")||normalized.includes("/build/")||normalized.includes(".swarm/checkpoints/"))return{filePath,zone:"generated",confidence:"high",reason:"path matches generated file patterns"};if(normalized.includes("/test/")||normalized.includes("/tests/")||normalized.includes("/__tests__/")||normalized.includes(".test.")||normalized.includes(".spec.")||normalized.includes("/mocks/"))return{filePath,zone:"test",confidence:"high",reason:"path matches test/**, tests/**, __tests__/**, *.test.*, *.spec.*, or **/mocks/**"};if(normalized.includes("/scripts/")||normalized.includes("makefile")||normalized.includes("dockerfile")||normalized.includes(".github/"))return{filePath,zone:"build",confidence:"high",reason:"path matches build scripts or CI configuration"};if(normalized.endsWith(".json")&&!normalized.includes(".github/")||normalized.endsWith(".yaml")&&!normalized.includes(".github/")||normalized.endsWith(".yml")&&!normalized.includes(".github/")||normalized.endsWith(".toml")||normalized.includes(".env")||normalized.endsWith("biome.json")||normalized.endsWith("tsconfig.json"))return{filePath,zone:"config",confidence:"high",reason:"extension is config file type"};if(normalized.includes("/docs/")||normalized.endsWith(".md")&&!normalized.includes("/")||normalized.includes("readme")||normalized.includes("changelog")||normalized.includes("license"))return{filePath,zone:"docs",confidence:"high",reason:"path matches docs/** or documentation files"};if(normalized.includes("/src/")||normalized.includes("/lib/"))return{filePath,zone:"production",confidence:"high",reason:"path matches src/** or lib/**"};return{filePath,zone:"production",confidence:"medium",reason:"default classification"}}import*as fsSync4 from"node:fs";import*as path25 from"node:path";function hashArgs(args2){try{if(typeof args2!=="object"||args2===null)return 0;let sortedKeys=Object.keys(args2).sort();return Number(bunHash(JSON.stringify(args2,sortedKeys)))}catch(error49){return log("[Guardrails] hashArgs failed",{error:error49 instanceof Error?error49.message:String(error49)}),0}}function normalizePathWithCache(filePath,cwd){let cacheKey=`${cwd}:${filePath}`,cached2=pathNormalizationCache.get(cacheKey);if(cached2!==void 0)return cached2;try{let absolutePath=path25.isAbsolute(filePath)?filePath:path25.resolve(cwd,filePath),normalized=fsSync4.realpathSync(absolutePath);return pathNormalizationCache.set(cacheKey,normalized),normalized}catch{let fallback=path25.isAbsolute(filePath)?filePath:path25.resolve(cwd,filePath);return pathNormalizationCache.set(cacheKey,fallback),fallback}}function getGlobMatcher(pattern,caseInsensitive=!0){let cacheKey=`${caseInsensitive?"nocase":"case"}\x00${pattern}`,cached2=globMatcherCache.get(cacheKey);if(cached2!==void 0)return cached2;try{let matcher=import_picomatch.default(pattern,{dot:!0,nocase:caseInsensitive});return globMatcherCache.set(cacheKey,matcher),matcher}catch(err){return warn(`picomatch error for pattern "${pattern}": ${err}`),()=>!1}}function checkWriteTargetForSymlink(targetPath,cwd){let normalizedCwd=path25.resolve(cwd),normalizedTarget=path25.resolve(cwd,targetPath),ancestors=[],current=normalizedTarget;while(!0){let rel=path25.relative(normalizedCwd,current);if(rel===""||rel.startsWith(".."))break;ancestors.push(current);let parent=path25.dirname(current);if(parent===current)break;current=parent}for(let ancestor of ancestors){let stat6=null;try{stat6=fsSync4.lstatSync(ancestor)}catch(err){if(err.code==="ENOENT")continue;return`WRITE BLOCKED: lstat failed on "${ancestor}": ${String(err)} — refusing write on unverifiable path`}if(stat6.isSymbolicLink())return`WRITE BLOCKED: "${ancestor}" is a symlink — writing through a symlink could redirect the write outside the working directory`}return null}function buildEffectiveRules(authorityConfig){if(authorityConfig?.enabled===!1||!authorityConfig?.rules)return{...DEFAULT_AGENT_AUTHORITY_RULES};let entries=Object.entries(authorityConfig.rules);if(entries.length===0)return{...DEFAULT_AGENT_AUTHORITY_RULES};let merged={...DEFAULT_AGENT_AUTHORITY_RULES};for(let[agent,userRule]of entries){let normalizedRuleKey=agent.toLowerCase(),existing=merged[normalizedRuleKey]??{};merged[normalizedRuleKey]={...existing,...userRule,readOnly:userRule.readOnly??existing.readOnly,blockedExact:userRule.blockedExact??existing.blockedExact,allowedExact:userRule.allowedExact??existing.allowedExact,blockedPrefix:userRule.blockedPrefix??existing.blockedPrefix,allowedPrefix:userRule.allowedPrefix??existing.allowedPrefix,blockedZones:userRule.blockedZones??existing.blockedZones,blockedGlobs:userRule.blockedGlobs??existing.blockedGlobs,allowedGlobs:userRule.allowedGlobs??existing.allowedGlobs,allowedCaseSensitiveGlobs:userRule.allowedCaseSensitiveGlobs??existing.allowedCaseSensitiveGlobs}}return merged}function isOnDifferentFilesystemRoot(targetAbsolute,cwdAbsolute,pathLib=path25){return pathLib.parse(targetAbsolute).root!==pathLib.parse(cwdAbsolute).root}function isInDeclaredScope(filePath,scopeEntries,cwd){let dir=cwd??process.cwd(),caseInsensitive=process.platform==="win32",resolvedFileRaw=path25.resolve(dir,filePath),resolvedFile=caseInsensitive?resolvedFileRaw.toLowerCase():resolvedFileRaw;return scopeEntries.some((scope)=>{let resolvedScopeRaw=path25.resolve(dir,scope),resolvedScope=caseInsensitive?resolvedScopeRaw.toLowerCase():resolvedScopeRaw;if(resolvedFile===resolvedScope)return!0;let rel=path25.relative(resolvedScope,resolvedFile);return rel.length>0&&!rel.startsWith("..")&&!path25.isAbsolute(rel)})}function checkFileAuthorityWithRules(agentName,filePath,cwd,effectiveRules,options){let normalizedAgent=agentName.toLowerCase(),strippedAgent=stripKnownSwarmPrefix(agentName).toLowerCase(),dir=cwd||process.cwd(),normalizedPath,resolvedTarget;try{let normalizedWithSymlinks=normalizePathWithCache(filePath,dir);resolvedTarget=path25.resolve(dir,normalizedWithSymlinks),normalizedPath=path25.relative(dir,resolvedTarget).replace(/\\/g,"/")}catch{resolvedTarget=path25.resolve(dir,filePath),normalizedPath=path25.relative(dir,resolvedTarget).replace(/\\/g,"/")}if(isOnDifferentFilesystemRoot(resolvedTarget,dir))return{allowed:!1,reason:`Path blocked: ${filePath} is on a different drive/root than the working directory`};if(normalizedPath===".."||normalizedPath.startsWith("../"))return{allowed:!1,reason:`Path blocked: ${normalizedPath} resolves outside the working directory`};let rules=effectiveRules[normalizedAgent]??effectiveRules[strippedAgent];if(!rules)return{allowed:!1,reason:`Unknown agent: ${agentName}`};if(rules.readOnly)return{allowed:!1,reason:`Path blocked: ${normalizedPath} (agent ${normalizedAgent} is read-only)`};if(rules.blockedExact){for(let blocked of rules.blockedExact)if(normalizedPath===blocked)return{allowed:!1,reason:`Path blocked (exact): ${normalizedPath}`}}if(rules.blockedGlobs&&rules.blockedGlobs.length>0){for(let glob of rules.blockedGlobs)if(getGlobMatcher(glob)(normalizedPath))return{allowed:!1,reason:`Path blocked (glob ${glob}): ${normalizedPath}`}}if(rules.allowedExact&&rules.allowedExact.length>0){if(rules.allowedExact.some((allowed)=>normalizedPath===allowed))return{allowed:!0}}if(rules.blockedZones&&rules.blockedZones.length>0){let{zone}=classifyFile(normalizedPath);if(rules.blockedZones.includes(zone))return{allowed:!1,reason:`Path blocked: ${normalizedPath} is in ${zone} zone`,zone}}if(rules.allowedGlobs&&rules.allowedGlobs.length>0){if(rules.allowedGlobs.some((glob)=>{return getGlobMatcher(glob)(normalizedPath)}))return{allowed:!0}}if(rules.allowedCaseSensitiveGlobs&&rules.allowedCaseSensitiveGlobs.length>0){if(rules.allowedCaseSensitiveGlobs.some((glob)=>{return getGlobMatcher(glob,!1)(normalizedPath)}))return{allowed:!0}}if(rules.blockedPrefix&&rules.blockedPrefix.length>0){for(let prefix of rules.blockedPrefix)if(normalizedPath.startsWith(prefix))return{allowed:!1,reason:`Path blocked: ${normalizedPath} is under ${prefix}`}}if(!((normalizedAgent==="coder"||strippedAgent==="coder")&&options?.declaredScope!=null&&options.declaredScope.length>0&&isInDeclaredScope(normalizedPath,options.declaredScope,dir))){if(rules.allowedPrefix!=null&&rules.allowedPrefix.length>0){if(!rules.allowedPrefix.some((prefix)=>normalizedPath.startsWith(prefix)))return{allowed:!1,reason:`Path ${normalizedPath} not in allowed list for ${normalizedAgent}`}}else if(rules.allowedPrefix!=null&&rules.allowedPrefix.length===0)return{allowed:!1,reason:`Path ${normalizedPath} not in allowed list for ${normalizedAgent}`}}return{allowed:!0}}function checkFileAuthority(agentName,filePath,cwd,authorityConfig,options){return checkFileAuthorityWithRules(agentName,filePath,cwd,buildEffectiveRules(authorityConfig),options)}var import_picomatch,pathNormalizationCache,globMatcherCache,DEFAULT_AGENT_AUTHORITY_RULES;var init_file_authority=__esm(()=>{init_quick_lru();init_schema();init_utils();init_bun_compat();import_picomatch=__toESM(require_picomatch2(),1);pathNormalizationCache=new QuickLRU({maxSize:500}),globMatcherCache=new QuickLRU({maxSize:200});DEFAULT_AGENT_AUTHORITY_RULES={build:{},plan:{},general:{},explore:{},architect:{blockedExact:[".swarm/plan.md",".swarm/plan.json"],blockedZones:["generated","config"],blockedGlobs:["**/oxlintrc*","**/.oxlintrc*","**/.eslintrc*","**/eslint.config.*","**/.prettierrc*","**/prettier.config.*","**/biome.jsonc","**/.secretscanignore","**/.golangci*"]},coder:{blockedPrefix:[".swarm/"],blockedZones:["generated","config"]},reviewer:{blockedExact:[".swarm/plan.md",".swarm/plan.json"],blockedPrefix:["src/"],allowedPrefix:[".swarm/evidence/",".swarm/outputs/"],blockedZones:["generated"]},explorer:{readOnly:!0},sme:{readOnly:!0},test_engineer:{blockedExact:[".swarm/plan.md",".swarm/plan.json"],blockedPrefix:["src/"],allowedPrefix:["tests/","test/",".swarm/evidence/"],allowedGlobs:["**/tests/**","**/test/**","**/__tests__/**","**/*.test.*","**/*.spec.*","test_*.py","**/test_*.py","*_test.py","**/*_test.py","*_test.go","**/*_test.go","*_spec.rb","**/*_spec.rb","*.Tests.ps1","**/*.Tests.ps1"],allowedCaseSensitiveGlobs:["*Test.java","**/*Test.java","*Test.kt","**/*Test.kt","*Tests.cs","**/*Tests.cs"],blockedZones:["generated"]},docs:{allowedPrefix:["docs/",".swarm/outputs/"],allowedGlobs:["**/docs/**","**/*.md","**/*.mdx","**/*.rst"],blockedZones:["generated"]},docs_design:{allowedPrefix:["docs/",".swarm/outputs/"],blockedGlobs:["src/**","lib/**"],allowedGlobs:["**/docs/**","**/*.md","**/*.mdx","**/*.rst","**/reference/traceability.json"],blockedZones:["generated"]},designer:{allowedPrefix:["docs/",".swarm/outputs/"],allowedGlobs:["**/docs/**","**/*.md","**/*.mdx","**/*.rst"],blockedZones:["generated"]},critic:{allowedPrefix:[".swarm/evidence/"],blockedZones:["generated"]}}});function resolveAgentConflict(input){let session=swarmState.agentSessions.get(input.sessionID);if(!session)return;session.pendingAdvisoryMessages??=[];let rejections=input.rejectionCount??0,resolutionPath;if(rejections>=3)resolutionPath="soundingboard",session.pendingAdvisoryMessages.push(`CONFLICT ESCALATION: ${input.sourceAgent} vs ${input.targetAgent} on task ${input.taskId??"unknown"}. Three or more failed cycles detected. Route to Critic in SOUNDING_BOARD mode, then simplify before any user escalation.`);else resolutionPath="self_resolve",session.pendingAdvisoryMessages.push(`CONFLICT DETECTED: ${input.sourceAgent} disagrees with ${input.targetAgent} on task ${input.taskId??"unknown"}. Attempt self-resolution using .swarm/plan.md, .swarm/spec.md, and .swarm/context.md before escalation.`);let event={type:"agent_conflict_detected",timestamp:new Date().toISOString(),sessionId:input.sessionID,phase:input.phase,taskId:input.taskId,sourceAgent:input.sourceAgent,targetAgent:input.targetAgent,conflictType:input.conflictType,resolutionPath,summary:input.summary};emit("agent_conflict_detected",event)}var init_conflict_resolution=__esm(()=>{init_state2();init_telemetry()});function extractCurrentPhase(planContent){if(!planContent)return null;let lines=planContent.split(`
|
|
428
|
+
`}];FTS_STOP_WORDS=new Set(["a","an","and","are","as","at","be","by","for","from","goal","how","in","into","is","it","of","on","or","role","task","that","the","this","to","user","what","when","with"])});import{realpathSync as realpathSync4}from"node:fs";import*as path23 from"node:path";function markAsPooled(provider){let originalClose=provider.close;if(provider.close=()=>{return releaseProvider(provider),Promise.resolve()},provider[POOLED_MARKER]=!0,originalClose)provider[REAL_CLOSE]=originalClose}function callRealClose(provider){let realClose=provider[REAL_CLOSE];try{realClose?.call(provider)}catch(err){let msg=err instanceof Error?err.message:String(err);if(process.env.OPENCODE_SWARM_DEBUG==="1")console.debug(`[provider-pool] real close failed: ${msg}`)}}function isPooledProvider(provider){return POOLED_MARKER in provider}function getOrCreateProvider(directory,config2){let key=resolvePoolKey(directory),existing=entriesByKey.get(key);if(existing)return moveToHead(existing),existing.refCount++,existing.provider;for(let deferred of deferredEntries)if(deferred.key===key){if(deferredEntries.delete(deferred),entriesByKey.size>=MAX_POOL_SIZE)evictLru();if(deferred.prev=null,deferred.next=head,head)head.prev=deferred;if(head=deferred,!tail)tail=deferred;return entriesByKey.set(key,deferred),deferred.refCount++,deferred.provider}let provider=new SQLiteMemoryProvider(directory,config2);if(markAsPooled(provider),entriesByKey.size>=MAX_POOL_SIZE)evictLru();let entry={key,provider,refCount:1,prev:null,next:head};if(head)head.prev=entry;if(head=entry,!tail)tail=entry;return entriesByKey.set(key,entry),provider}function releaseProvider(provider){for(let[_key,entry]of entriesByKey)if(entry.provider===provider){entry.refCount=Math.max(0,entry.refCount-1);return}for(let entry of deferredEntries)if(entry.provider===provider){if(entry.refCount--,entry.refCount<=0)deferredEntries.delete(entry),callRealClose(provider);return}if(isPooledProvider(provider))callRealClose(provider)}function evictLru(){if(!tail)return;let evicted=tail;if(entriesByKey.delete(evicted.key),unlinkEntry(evicted),evicted.refCount>0)deferredEntries.add(evicted);else callRealClose(evicted.provider)}function moveToHead(entry){if(head===entry)return;if(unlinkEntry(entry),entry.prev=null,entry.next=head,head)head.prev=entry;if(head=entry,!tail)tail=entry}function unlinkEntry(entry){if(entry.prev)entry.prev.next=entry.next;if(entry.next)entry.next.prev=entry.prev;if(head===entry)head=entry.next;if(tail===entry)tail=entry.prev}function resolvePoolKey(directory){try{return realpathSync4(directory)}catch{return path23.resolve(directory)}}function evictAndClose(directory){let key=resolvePoolKey(directory),active=entriesByKey.get(key);if(active)entriesByKey.delete(key),unlinkEntry(active),callRealClose(active.provider);for(let deferred of[...deferredEntries])if(deferred.key===key)deferredEntries.delete(deferred),callRealClose(deferred.provider)}var MAX_POOL_SIZE=16,POOLED_MARKER,REAL_CLOSE,head=null,tail=null,entriesByKey,deferredEntries;var init_provider_pool=__esm(()=>{init_sqlite_provider();POOLED_MARKER=Symbol("opencode-swarm-pooled-provider"),REAL_CLOSE=Symbol("opencode-swarm-real-close"),entriesByKey=new Map,deferredEntries=new Set});import{createHash as createHash7}from"node:crypto";import{existsSync as existsSync14,readFileSync as readFileSync9}from"node:fs";import*as path24 from"node:path";class MemoryGateway{context;config;provider;now;disposed=!1;constructor(context,options={}){this.context=context;this.config=resolveMemoryConfig(options.config??DEFAULT_MEMORY_CONFIG),this.provider=options.provider??createConfiguredMemoryProvider(context.directory,this.config),this.now=options.now??(()=>new Date)}isEnabled(){return this.config.enabled}async dispose(){if(this.disposed)return;this.disposed=!0,await this.provider.close?.()}deriveAllowedScopes(){let resolvedRoot=path24.resolve(this.context.directory),repoId=createStableId(readGitRemoteUrl(resolvedRoot)??path24.basename(resolvedRoot)),scopes=[{type:"workspace",workspaceId:createStableId(path24.dirname(resolvedRoot))},{type:"repository",repoId,repoRoot:resolvedRoot}];if(this.context.runId||this.context.sessionID)scopes.push({type:"run",runId:this.context.runId??this.context.sessionID});if(this.context.agentId||this.context.agentRole)scopes.push({type:"agent",agentId:this.context.agentId??this.context.agentRole,runId:this.context.runId??this.context.sessionID});return scopes}async recall(input){this.assertEnabled();let query=normalizeMemoryText(input.query);if(query.length<3)throw new MemoryValidationError("query must be at least 3 characters");let maxItems=clampInt(input.maxItems??this.config.recall.defaultMaxItems,1,20),tokenBudget=clampInt(input.tokenBudget??this.config.recall.defaultTokenBudget,100,5000),generatedAt=this.now().toISOString(),allowedScopes=this.deriveAllowedScopes(),scopes=input.scopes?validateRequestedScopes(input.scopes,allowedScopes):allowedScopes,request={query,task:input.task,agentRole:this.context.agentRole,mode:input.mode??"manual",scopes,kinds:input.kinds,maxItems,tokenBudget,minScore:input.minScore??this.config.recall.minScore,requireQuerySignal:input.requireQuerySignal,includeExpired:input.includeExpired},recallResult=this.provider.recallWithDiagnostics?await this.provider.recallWithDiagnostics(request):{items:await this.provider.recall(request)},bundle=toRecallBundle({id:createBundleId(query,generatedAt),query,generatedAt,items:recallResult.items,tokenBudget,diagnostics:recallResult.diagnostics?{injectionSkipReason:input.mode==="injection"?resolveInjectionSkipReason(recallResult.diagnostics):void 0,candidateCount:recallResult.diagnostics.candidateCount,preScoredFilteredCount:recallResult.diagnostics.preScoredFilteredCount,noSignalCount:recallResult.diagnostics.noSignalCount,belowThresholdCount:recallResult.diagnostics.belowThresholdCount}:void 0});return await this.provider.recordRecallUsage?.({bundleId:bundle.id,query,scopes,kinds:input.kinds,memoryIds:bundle.items.map((item)=>item.record.id),scores:bundle.items.map((item)=>item.score),tokenEstimate:bundle.tokenEstimate,agentRole:this.context.agentRole,runId:this.context.runId??this.context.sessionID,unitId:this.context.unitId,timestamp:generatedAt}),bundle}async propose(input){if(this.assertEnabled(),!this.provider.createProposal)throw new MemoryValidationError("memory provider does not support proposals");let redactedFields=new Set,redactProposalField=(field,value)=>{let redacted=redactSecrets(value);if(redacted!==value)redactedFields.add(field);return redacted},rationale=redactProposalField("rationale",normalizeMemoryText(input.rationale));if(!rationale)throw new MemoryValidationError("rationale is required");let evidenceRefs=(input.evidenceRefs??[]).map((ref)=>normalizeMemoryText(ref)).filter(Boolean).map((ref)=>redactProposalField("evidenceRefs",ref)).slice(0,20),needsRecord=input.operation==="add"||input.operation==="update"||input.operation==="supersede",proposedRecord,status="pending",reviewer,reviewedAt,rejectionReason,targetMemoryId=input.targetMemoryId===void 0?void 0:redactProposalField("targetMemoryId",normalizeMemoryText(input.targetMemoryId)),relatedMemoryIds=input.relatedMemoryIds?.map((id)=>redactProposalField("relatedMemoryIds",normalizeMemoryText(id))),proposalText=`${input.operation}:${targetMemoryId??""}`;if(needsRecord){if(!input.kind)throw new MemoryValidationError("kind is required for this operation");if(!input.text)throw new MemoryValidationError("text is required for this operation");proposalText=input.text;let normalizedText=normalizeMemoryText(input.text),redactedText=redactProposalField("text",normalizedText),extractedPaths=extractFilePaths(evidenceRefs),extractedSymbols=extractSymbols(evidenceRefs),recordMetadata={};if(extractedPaths.length>0)recordMetadata.files=extractedPaths;if(extractedSymbols.length>0)recordMetadata.symbols=extractedSymbols;proposedRecord=this.createRecord({kind:input.kind,text:redactedText,evidenceRefs,source:sourceFromEvidence(evidenceRefs,this.context),metadata:recordMetadata}),validateMemoryRecordRules(proposedRecord,{rejectDurableSecrets:this.config.redaction.rejectDurableSecrets})}if(redactedFields.size>0)status="rejected",reviewer="auto_policy",reviewedAt=this.now().toISOString(),rejectionReason=`proposal field(s) contained a likely secret and were redacted: ${Array.from(redactedFields).join(", ")}`;if((input.operation==="update"||input.operation==="delete"||input.operation==="supersede")&&!targetMemoryId)throw new MemoryValidationError(`${input.operation} proposals require targetMemoryId`);if(input.operation==="merge"&&(relatedMemoryIds??[]).length<2)throw new MemoryValidationError("merge proposals require relatedMemoryIds");let createdAt=this.now().toISOString(),proposer=this.context.agentId??this.context.agentRole??this.context.sessionID??"unknown",proposal={id:createProposalId({createdAt,proposer,text:proposalText}),operation:input.operation,proposedRecord,targetMemoryId,relatedMemoryIds,proposedBy:{agentRole:this.context.agentRole,agentId:this.context.agentId,runId:this.context.runId??this.context.sessionID},rationale,evidenceRefs,status,reviewer,reviewedAt,rejectionReason,createdAt,metadata:{}};return this.provider.createProposal(proposal)}async listMemories(filter={}){return this.assertEnabled(),this.provider.list(filter)}async listProposals(filter){if(this.assertEnabled(),!this.provider.listProposals)throw new MemoryValidationError("memory provider does not support proposals");return this.provider.listProposals(filter)}async listRecallUsage(filter){if(this.assertEnabled(),!this.provider.listRecallUsage)return[];return this.provider.listRecallUsage(filter)}async upsertCurated(record2){this.assertEnabled();let parsed=validateMemoryRecordRules(record2,{rejectDurableSecrets:this.config.redaction.rejectDurableSecrets});return this.provider.upsert(parsed)}async applyCuratorDecision(decision){if(this.assertEnabled(),!this.provider.applyCuratorDecision)throw new MemoryValidationError("memory provider does not support curator decisions");let parsed=validateCuratorMemoryDecision(decision),resolved=this.resolveCuratorDecision(parsed);return this.provider.applyCuratorDecision(resolved)}createRecord(input){let now=this.now().toISOString(),text=normalizeMemoryText(input.text),scope=this.resolveRecordScope(input.scope),kind=input.kind,stability=input.stability??(kind==="scratch"?"ephemeral":"durable"),expiresAt=kind==="scratch"?new Date(this.now().getTime()+604800000).toISOString():void 0,recordBase={scope,kind,text};return{id:createMemoryId(recordBase),scope,kind,text,tags:normalizeTags2(input.tags??inferTags(text)),confidence:clamp(input.confidence??0.5,0,1),stability,source:input.source??sourceFromEvidence(input.evidenceRefs??[],this.context),createdAt:now,updatedAt:now,expiresAt,contentHash:computeMemoryContentHash(recordBase),metadata:input.metadata??{}}}resolveCuratorDecision(decision){switch(decision.action){case"add":return{action:"add",proposalId:decision.proposalId,memory:this.createRecordFromNew(decision.memory)};case"supersede":return{action:"supersede",proposalId:decision.proposalId,oldMemoryId:decision.oldMemoryId,replacement:this.createRecordFromNew(decision.replacement),reason:normalizeMemoryText(decision.reason)};case"update":{let patch=normalizeMemoryPatch(decision.patch);if(patch.scope)patch.scope=this.resolveRecordScope(patch.scope);return{action:"update",proposalId:decision.proposalId,targetMemoryId:decision.targetMemoryId,patch,reason:normalizeMemoryText(decision.reason)}}case"reject":case"noop":return{action:decision.action,proposalId:decision.proposalId,reason:normalizeMemoryText(decision.reason)}}}createRecordFromNew(input){let record2=this.createRecord({kind:input.kind,text:input.text,scope:input.scope,tags:input.tags,confidence:input.confidence,stability:input.stability,source:input.source,metadata:input.metadata}),next=input.expiresAt?{...record2,expiresAt:input.expiresAt}:record2;return validateMemoryRecordRules(next,{rejectDurableSecrets:this.config.redaction.rejectDurableSecrets})}resolveRecordScope(scope){let allowedScopes=this.deriveAllowedScopes();if(!scope){let defaultScope=allowedScopes[1]??allowedScopes[0];if(!defaultScope)throw new MemoryValidationError("memory scope is not available for this context");return defaultScope}return validateRequestedScopes([scope],allowedScopes,"memory scope is not allowed for this context"),scope}assertEnabled(){if(!this.config.enabled)throw new MemoryDisabledError}}function createMemoryGateway(context,options={}){return new MemoryGateway(context,options)}function createConfiguredMemoryProvider(directory,config2){if(config2.provider==="sqlite")return getOrCreateProvider(directory,config2);return new LocalJsonlMemoryProvider(directory,config2)}function sourceFromEvidence(evidenceRefs,context){let first=evidenceRefs[0];if(!first)return{type:"agent",createdBy:context.agentId??context.agentRole};if(/^https?:\/\//i.test(first))return{type:"web",url:first};if(/^[a-f0-9]{40}$/i.test(first))return{type:"commit",commitSha:first};let filePath=extractFilePaths(evidenceRefs)[0]??first;if(filePath!==first&&(filePath.includes("/")||filePath.includes("\\")||filePath.includes(".")))return{type:"file",filePath};if(first.includes("/")||first.includes("\\")||first.includes("."))return{type:"file",filePath:first};return{type:"manual",ref:first}}function createStableId(value){return createHash7("sha256").update(value.toLowerCase()).digest("hex").slice(0,16)}function readGitRemoteUrl(directory){if(gitRemoteUrlCache.has(directory))return gitRemoteUrlCache.get(directory);let gitConfigPath=path24.join(directory,".git","config");if(!existsSync14(gitConfigPath)){gitRemoteUrlCache.set(directory,void 0);return}try{let remoteUrl=readFileSync9(gitConfigPath,"utf-8").match(/\[remote "origin"\][\s\S]*?\n\s*url\s*=\s*(.+)/)?.[1]?.trim();return gitRemoteUrlCache.set(directory,remoteUrl),remoteUrl}catch{gitRemoteUrlCache.set(directory,void 0);return}}function validateRequestedScopes(requested,allowed,disallowedMessage="recall scope is not allowed for this context"){if(requested.length===0)throw new MemoryValidationError("recall scopes must not be empty");let allowedKeys=new Set(allowed.map(scopeKey));for(let scope of requested)if(!allowedKeys.has(scopeKey(scope)))throw new MemoryValidationError(disallowedMessage);return requested}function resolveInjectionSkipReason(diagnostics){if(diagnostics.returnedCount>0)return;if(diagnostics.candidateCount===0)return"no_results";let signalEligibleCount=diagnostics.candidateCount-diagnostics.preScoredFilteredCount-diagnostics.suppressedLowQCount;if(signalEligibleCount>0&&diagnostics.noSignalCount>0&&diagnostics.noSignalCount>=signalEligibleCount)return"no_signal";if(diagnostics.belowThresholdCount>0)return"below_threshold";return"no_results"}function scopeKey(scope){return JSON.stringify({type:scope.type,userId:scope.userId,workspaceId:scope.workspaceId,projectId:scope.projectId,repoId:scope.repoId,repoRoot:scope.repoRoot?path24.resolve(scope.repoRoot):void 0,runId:scope.runId,agentId:scope.agentId})}function clamp(value,min,max){return Math.min(max,Math.max(min,value))}function clampInt(value,min,max){return Math.trunc(clamp(value,min,max))}function normalizeTags2(tags){return Array.from(new Set(tags.map((tag)=>tag.toLowerCase().replace(/[^\w-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")).filter(Boolean))).slice(0,32)}function normalizeMemoryPatch(patch){return{...patch,text:patch.text===void 0?void 0:normalizeMemoryText(patch.text),tags:patch.tags===void 0?void 0:normalizeTags2(patch.tags)}}function inferTags(text){let lower=text.toLowerCase(),tags=[];for(let[tag,pattern]of[["testing",/\b(test|spec|bun|jest|vitest)\b/],["tooling",/\b(pnpm|npm|yarn|bun|biome|eslint|typescript)\b/],["security",/\b(security|auth|token|secret|password|csp)\b/],["api",/\b(api|endpoint|graphql|rest|sdk)\b/],["architecture",/\b(architecture|decision|adr|pattern)\b/],["failure",/\b(fail|failure|regression|flaky|timeout)\b/]])if(pattern.test(lower))tags.push(tag);return tags}function extractFilePaths(refs){let seen=new Set,paths=[];for(let ref of refs){FILE_PATH_REGEX.lastIndex=0;let matches=ref.match(FILE_PATH_REGEX);if(!matches)continue;for(let m of matches)if(!seen.has(m)){if(seen.add(m),paths.push(m),paths.length>=20)return paths}}return paths}function extractSymbols(refs){let seen=new Set,symbols=[],identRegex=/\b[a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*\b/g;for(let ref of refs){identRegex.lastIndex=0;let matches=ref.match(identRegex);if(!matches)continue;for(let m of matches)if(m.length>=3&&!seen.has(m)&&!RESERVED_IDENTIFIERS.has(m)){if(seen.add(m),symbols.push(m),symbols.length>=20)return symbols}}return symbols}var gitRemoteUrlCache,FILE_PATH_REGEX,RESERVED_IDENTIFIERS;var init_gateway=__esm(()=>{init_config2();init_errors4();init_local_jsonl_provider();init_prompt_block();init_provider_pool();init_redaction();init_schema2();gitRemoteUrlCache=new Map;FILE_PATH_REGEX=/\b(?:src|tests|test|docs|scripts|packages|lib|config|examples|internal|cmd|pkg|bin|tools|cli|api|server|client|app|core|utils|hooks|services|commands|agents|memory)\/[A-Za-z0-9._/@+-]+/g,RESERVED_IDENTIFIERS=new Set(["const","let","var","function","class","interface","type","async","await","return","if","else","for","while","do","switch","case","break","continue","new","this","super","extends","implements","import","export","from","default","try","catch","finally","throw","typeof","instanceof","in","of","as","yield","static","get","set","readonly","public","private","protected"])});async function applyCouncilReward(provider,opts){let bundles=await provider.listRecallUsage?.({runId:opts.runId})??[];if(bundles.length===0)return{memoriesRewarded:0};let attributedBundles=bundles.filter((bundle)=>bundle.unitId==null||opts.unitId==null||bundle.unitId===opts.unitId),distinctIds=new Set;for(let bundle of attributedBundles)for(let id of bundle.memoryIds)distinctIds.add(id);let result=await(provider.withTransaction?provider.withTransaction(async()=>{let updates=new Map;for(let id of distinctIds){let rec=await provider.get(id);if(!rec)continue;let qBefore=getQValue(rec,opts.initialQValue),qAfter=applyEmaUpdate(qBefore,opts.reward,opts.eta);updates.set(id,{rec,qBefore,qAfter})}for(let[id,{rec,qBefore,qAfter}]of updates)await provider.upsert(setQValue(rec,qAfter)),await provider.appendRewardEvent?.({memoryId:id,runId:opts.runId,unitId:opts.unitId,verdict:opts.verdictLabel??"APPROVE",reward:opts.reward,qBefore,qAfter,verdictSynthesisJson:opts.verdictSynthesisJson,timestamp:opts.timestamp});return updates}):(async()=>{let updates=new Map;for(let id of distinctIds){let rec=await provider.get(id);if(!rec)continue;let qBefore=getQValue(rec,opts.initialQValue),qAfter=applyEmaUpdate(qBefore,opts.reward,opts.eta);updates.set(id,{rec,qBefore,qAfter})}for(let[id,{rec,qBefore,qAfter}]of updates)await provider.upsert(setQValue(rec,qAfter)),await provider.appendRewardEvent?.({memoryId:id,runId:opts.runId,unitId:opts.unitId,verdict:opts.verdictLabel??"APPROVE",reward:opts.reward,qBefore,qAfter,verdictSynthesisJson:opts.verdictSynthesisJson,timestamp:opts.timestamp});return updates})()),memoriesRewarded=result.size,rewardedRecords=[...result.values()].map(({rec})=>rec);try{await propagateReward(provider,opts,rewardedRecords,distinctIds)}catch(err){log(`[memory:propagation] skipped after error: ${err instanceof Error?err.message:String(err)}`)}return{memoriesRewarded}}async function propagateReward(provider,opts,sources,directlyRewardedIds){if(sources.length===0)return;let qConfig=opts.qLearning??DEFAULT_QLEARNING_CONFIG,fraction=qConfig.propagationFraction,fanoutCap=qConfig.propagationFanoutCap,windowDays=qConfig.propagationWindowDays,relatednessThreshold=qConfig.propagationRelatednessThreshold;if(!Number.isFinite(fraction)||fraction<=0)return;if(!Number.isFinite(fanoutCap)||fanoutCap<=0)return;if(!Number.isFinite(windowDays)||windowDays<=0)return;if(!Number.isFinite(relatednessThreshold))return;if(typeof provider.list!=="function")return;let nowMs=Date.parse(opts.timestamp);if(!Number.isFinite(nowMs))return;let windowMs=windowDays*MS_PER_DAY2,recencyById=await buildRetrievalRecency(provider);if(!recencyById)return;let orderedSources=[...sources].sort((a,b)=>a.id.localeCompare(b.id)),scheduled=new Map,listCache=new Map;for(let source of orderedSources){let scopeKey2=stableScopeKey(source.scope),cacheKey=`${scopeKey2}::${source.kind}`,candidates=listCache.get(cacheKey);if(!candidates)candidates=await provider.list({scopes:[source.scope],kinds:[source.kind]}),listCache.set(cacheKey,candidates);let sourceTokens=tokenize(source.text),qualified=[];for(let cand of candidates){if(cand.id===source.id)continue;if(directlyRewardedIds.has(cand.id))continue;if(stableScopeKey(cand.scope)!==scopeKey2)continue;if(cand.kind!==source.kind)continue;let retrievedAt=recencyById.get(cand.id);if(retrievedAt===void 0)continue;if(nowMs-retrievedAt>windowMs)continue;let overlap2=jaccard(sourceTokens,tokenize(cand.text));if(overlap2<relatednessThreshold)continue;qualified.push({record:cand,overlap:overlap2})}qualified.sort((a,b)=>b.overlap-a.overlap||a.record.id.localeCompare(b.record.id));let cap=Math.trunc(fanoutCap),selected=qualified.slice(0,cap),dropped=qualified.length-selected.length;if(dropped>0)log(`[memory:propagation] fan-out cap reached for source ${source.id}: ${qualified.length} qualified, ${selected.length} propagated, ${dropped} dropped by cap ${cap}`);for(let{record:record2}of selected)if(!scheduled.has(record2.id))scheduled.set(record2.id,record2)}for(let record2 of scheduled.values()){let qBefore=getQValue(record2,opts.initialQValue),qAfter=applyPropagatedEmaUpdate(qBefore,opts.reward,opts.eta,fraction);await provider.upsert(setQValue(record2,qAfter)),await provider.appendRewardEvent?.({memoryId:record2.id,runId:opts.runId,unitId:opts.unitId,verdict:`${opts.verdictLabel??"APPROVE"}${PROPAGATED_VERDICT_SUFFIX}`,reward:opts.reward,qBefore,qAfter,verdictSynthesisJson:opts.verdictSynthesisJson,timestamp:opts.timestamp})}}function truncateObjectForJson(obj,capBytes){let asIs=JSON.stringify(obj);if(asIs.length<=capBytes)return obj;if(JSON.stringify({...obj,__truncated__:!0}).length<=capBytes)return{...obj,__truncated__:!0};return{__truncated__:!0,originalSize:asIs.length,cap:capBytes}}async function buildRetrievalRecency(provider){if(typeof provider.listRecallUsage!=="function")return null;let since=new Date(Date.now()-RECENCY_WINDOW_MS).toISOString(),usage=await provider.listRecallUsage({since,limit:RECENCY_EVENT_LIMIT})??[],recency=new Map;for(let event of usage){let ts=Date.parse(event.timestamp);if(!Number.isFinite(ts))continue;for(let id of event.memoryIds){let prev=recency.get(id);if(prev===void 0||ts>prev)recency.set(id,ts)}}return recency}var PROPAGATED_VERDICT_SUFFIX="_PROPAGATED",MS_PER_DAY2=86400000,RECENCY_WINDOW_MS,RECENCY_EVENT_LIMIT=1000;var init_reward_capture=__esm(()=>{init_logger();init_config2();init_schema2();init_scoring();RECENCY_WINDOW_MS=30*MS_PER_DAY2});var require_constants=__commonJS((exports,module)=>{var POSIX_CHARS={DOT_LITERAL:"\\.",PLUS_LITERAL:"\\+",QMARK_LITERAL:"\\?",SLASH_LITERAL:"\\/",ONE_CHAR:"(?=.)",QMARK:"[^/]",END_ANCHOR:"(?:\\/|$)",DOTS_SLASH:"\\.{1,2}(?:\\/|$)",NO_DOT:"(?!\\.)",NO_DOTS:"(?!(?:^|\\/)\\.{1,2}(?:\\/|$))",NO_DOT_SLASH:"(?!\\.{0,1}(?:\\/|$))",NO_DOTS_SLASH:"(?!\\.{1,2}(?:\\/|$))",QMARK_NO_DOT:"[^.\\/]",STAR:"[^/]*?",START_ANCHOR:"(?:^|\\/)",SEP:"/"},WINDOWS_CHARS={...POSIX_CHARS,SLASH_LITERAL:"[\\\\/]",QMARK:"[^\\\\/]",STAR:"[^\\\\/]*?",DOTS_SLASH:"\\.{1,2}(?:[\\\\/]|$)",NO_DOT:"(?!\\.)",NO_DOTS:"(?!(?:^|[\\\\/])\\.{1,2}(?:[\\\\/]|$))",NO_DOT_SLASH:"(?!\\.{0,1}(?:[\\\\/]|$))",NO_DOTS_SLASH:"(?!\\.{1,2}(?:[\\\\/]|$))",QMARK_NO_DOT:"[^.\\\\/]",START_ANCHOR:"(?:^|[\\\\/])",END_ANCHOR:"(?:[\\\\/]|$)",SEP:"\\"},POSIX_REGEX_SOURCE={__proto__:null,alnum:"a-zA-Z0-9",alpha:"a-zA-Z",ascii:"\\x00-\\x7F",blank:" \\t",cntrl:"\\x00-\\x1F\\x7F",digit:"0-9",graph:"\\x21-\\x7E",lower:"a-z",print:"\\x20-\\x7E ",punct:"\\-!\"#$%&'()\\*+,./:;<=>?@[\\]^_`{|}~",space:" \\t\\r\\n\\v\\f",upper:"A-Z",word:"A-Za-z0-9_",xdigit:"A-Fa-f0-9"};module.exports={DEFAULT_MAX_EXTGLOB_RECURSION:0,MAX_LENGTH:65536,POSIX_REGEX_SOURCE,REGEX_BACKSLASH:/\\(?![*+?^${}(|)[\]])/g,REGEX_NON_SPECIAL_CHARS:/^[^@![\].,$*+?^{}()|\\/]+/,REGEX_SPECIAL_CHARS:/[-*+?.^${}(|)[\]]/,REGEX_SPECIAL_CHARS_BACKREF:/(\\?)((\W)(\3*))/g,REGEX_SPECIAL_CHARS_GLOBAL:/([-*+?.^${}(|)[\]])/g,REGEX_REMOVE_BACKSLASH:/(?:\[.*?[^\\]\]|\\(?=.))/g,REPLACEMENTS:{__proto__:null,"***":"*","**/**":"**","**/**/**":"**"},CHAR_0:48,CHAR_9:57,CHAR_UPPERCASE_A:65,CHAR_LOWERCASE_A:97,CHAR_UPPERCASE_Z:90,CHAR_LOWERCASE_Z:122,CHAR_LEFT_PARENTHESES:40,CHAR_RIGHT_PARENTHESES:41,CHAR_ASTERISK:42,CHAR_AMPERSAND:38,CHAR_AT:64,CHAR_BACKWARD_SLASH:92,CHAR_CARRIAGE_RETURN:13,CHAR_CIRCUMFLEX_ACCENT:94,CHAR_COLON:58,CHAR_COMMA:44,CHAR_DOT:46,CHAR_DOUBLE_QUOTE:34,CHAR_EQUAL:61,CHAR_EXCLAMATION_MARK:33,CHAR_FORM_FEED:12,CHAR_FORWARD_SLASH:47,CHAR_GRAVE_ACCENT:96,CHAR_HASH:35,CHAR_HYPHEN_MINUS:45,CHAR_LEFT_ANGLE_BRACKET:60,CHAR_LEFT_CURLY_BRACE:123,CHAR_LEFT_SQUARE_BRACKET:91,CHAR_LINE_FEED:10,CHAR_NO_BREAK_SPACE:160,CHAR_PERCENT:37,CHAR_PLUS:43,CHAR_QUESTION_MARK:63,CHAR_RIGHT_ANGLE_BRACKET:62,CHAR_RIGHT_CURLY_BRACE:125,CHAR_RIGHT_SQUARE_BRACKET:93,CHAR_SEMICOLON:59,CHAR_SINGLE_QUOTE:39,CHAR_SPACE:32,CHAR_TAB:9,CHAR_UNDERSCORE:95,CHAR_VERTICAL_LINE:124,CHAR_ZERO_WIDTH_NOBREAK_SPACE:65279,extglobChars(chars){return{"!":{type:"negate",open:"(?:(?!(?:",close:`))${chars.STAR})`},"?":{type:"qmark",open:"(?:",close:")?"},"+":{type:"plus",open:"(?:",close:")+"},"*":{type:"star",open:"(?:",close:")*"},"@":{type:"at",open:"(?:",close:")"}}},globChars(win32){return win32===!0?WINDOWS_CHARS:POSIX_CHARS}}});var require_utils=__commonJS((exports)=>{var{REGEX_BACKSLASH,REGEX_REMOVE_BACKSLASH,REGEX_SPECIAL_CHARS,REGEX_SPECIAL_CHARS_GLOBAL}=require_constants();exports.isObject=(val)=>val!==null&&typeof val==="object"&&!Array.isArray(val);exports.hasRegexChars=(str)=>REGEX_SPECIAL_CHARS.test(str);exports.isRegexChar=(str)=>str.length===1&&exports.hasRegexChars(str);exports.escapeRegex=(str)=>str.replace(REGEX_SPECIAL_CHARS_GLOBAL,"\\$1");exports.toPosixSlashes=(str)=>str.replace(REGEX_BACKSLASH,"/");exports.isWindows=()=>{if(typeof navigator<"u"&&navigator.platform){let platform=navigator.platform.toLowerCase();return platform==="win32"||platform==="windows"}if(typeof process<"u"&&process.platform)return process.platform==="win32";return!1};exports.removeBackslashes=(str)=>{return str.replace(REGEX_REMOVE_BACKSLASH,(match)=>{return match==="\\"?"":match})};exports.escapeLast=(input,char,lastIdx)=>{let idx=input.lastIndexOf(char,lastIdx);if(idx===-1)return input;if(input[idx-1]==="\\")return exports.escapeLast(input,char,idx-1);return`${input.slice(0,idx)}\\${input.slice(idx)}`};exports.removePrefix=(input,state={})=>{let output=input;if(output.startsWith("./"))output=output.slice(2),state.prefix="./";return output};exports.wrapOutput=(input,state={},options={})=>{let prepend=options.contains?"":"^",append=options.contains?"":"$",output=`${prepend}(?:${input})${append}`;if(state.negated===!0)output=`(?:^(?!${output}).*$)`;return output};exports.basename=(path25,{windows}={})=>{let segs=path25.split(windows?/[\\/]/:"/"),last=segs[segs.length-1];if(last==="")return segs[segs.length-2];return last}});var require_scan=__commonJS((exports,module)=>{var utils=require_utils(),{CHAR_ASTERISK,CHAR_AT,CHAR_BACKWARD_SLASH,CHAR_COMMA,CHAR_DOT,CHAR_EXCLAMATION_MARK,CHAR_FORWARD_SLASH,CHAR_LEFT_CURLY_BRACE,CHAR_LEFT_PARENTHESES,CHAR_LEFT_SQUARE_BRACKET,CHAR_PLUS,CHAR_QUESTION_MARK,CHAR_RIGHT_CURLY_BRACE,CHAR_RIGHT_PARENTHESES,CHAR_RIGHT_SQUARE_BRACKET}=require_constants(),isPathSeparator=(code)=>{return code===CHAR_FORWARD_SLASH||code===CHAR_BACKWARD_SLASH},depth=(token)=>{if(token.isPrefix!==!0)token.depth=token.isGlobstar?1/0:1},scan=(input,options)=>{let opts=options||{},length=input.length-1,scanToEnd=opts.parts===!0||opts.scanToEnd===!0,slashes=[],tokens=[],parts=[],str=input,index=-1,start=0,lastIndex=0,isBrace=!1,isBracket=!1,isGlob=!1,isExtglob=!1,isGlobstar=!1,braceEscaped=!1,backslashes=!1,negated=!1,negatedExtglob=!1,finished=!1,braces=0,prev,code,token={value:"",depth:0,isGlob:!1},eos=()=>index>=length,peek=()=>str.charCodeAt(index+1),advance=()=>{return prev=code,str.charCodeAt(++index)};while(index<length){code=advance();let next;if(code===CHAR_BACKWARD_SLASH){if(backslashes=token.backslashes=!0,code=advance(),code===CHAR_LEFT_CURLY_BRACE)braceEscaped=!0;continue}if(braceEscaped===!0||code===CHAR_LEFT_CURLY_BRACE){braces++;while(eos()!==!0&&(code=advance())){if(code===CHAR_BACKWARD_SLASH){backslashes=token.backslashes=!0,advance();continue}if(code===CHAR_LEFT_CURLY_BRACE){braces++;continue}if(braceEscaped!==!0&&code===CHAR_DOT&&(code=advance())===CHAR_DOT){if(isBrace=token.isBrace=!0,isGlob=token.isGlob=!0,finished=!0,scanToEnd===!0)continue;break}if(braceEscaped!==!0&&code===CHAR_COMMA){if(isBrace=token.isBrace=!0,isGlob=token.isGlob=!0,finished=!0,scanToEnd===!0)continue;break}if(code===CHAR_RIGHT_CURLY_BRACE){if(braces--,braces===0){braceEscaped=!1,isBrace=token.isBrace=!0,finished=!0;break}}}if(scanToEnd===!0)continue;break}if(code===CHAR_FORWARD_SLASH){if(slashes.push(index),tokens.push(token),token={value:"",depth:0,isGlob:!1},finished===!0)continue;if(prev===CHAR_DOT&&index===start+1){start+=2;continue}lastIndex=index+1;continue}if(opts.noext!==!0){if((code===CHAR_PLUS||code===CHAR_AT||code===CHAR_ASTERISK||code===CHAR_QUESTION_MARK||code===CHAR_EXCLAMATION_MARK)===!0&&peek()===CHAR_LEFT_PARENTHESES){if(isGlob=token.isGlob=!0,isExtglob=token.isExtglob=!0,finished=!0,code===CHAR_EXCLAMATION_MARK&&index===start)negatedExtglob=!0;if(scanToEnd===!0){while(eos()!==!0&&(code=advance())){if(code===CHAR_BACKWARD_SLASH){backslashes=token.backslashes=!0,code=advance();continue}if(code===CHAR_RIGHT_PARENTHESES){isGlob=token.isGlob=!0,finished=!0;break}}continue}break}}if(code===CHAR_ASTERISK){if(prev===CHAR_ASTERISK)isGlobstar=token.isGlobstar=!0;if(isGlob=token.isGlob=!0,finished=!0,scanToEnd===!0)continue;break}if(code===CHAR_QUESTION_MARK){if(isGlob=token.isGlob=!0,finished=!0,scanToEnd===!0)continue;break}if(code===CHAR_LEFT_SQUARE_BRACKET){while(eos()!==!0&&(next=advance())){if(next===CHAR_BACKWARD_SLASH){backslashes=token.backslashes=!0,advance();continue}if(next===CHAR_RIGHT_SQUARE_BRACKET){isBracket=token.isBracket=!0,isGlob=token.isGlob=!0,finished=!0;break}}if(scanToEnd===!0)continue;break}if(opts.nonegate!==!0&&code===CHAR_EXCLAMATION_MARK&&index===start){negated=token.negated=!0,start++;continue}if(opts.noparen!==!0&&code===CHAR_LEFT_PARENTHESES){if(isGlob=token.isGlob=!0,scanToEnd===!0){while(eos()!==!0&&(code=advance())){if(code===CHAR_LEFT_PARENTHESES){backslashes=token.backslashes=!0,code=advance();continue}if(code===CHAR_RIGHT_PARENTHESES){finished=!0;break}}continue}break}if(isGlob===!0){if(finished=!0,scanToEnd===!0)continue;break}}if(opts.noext===!0)isExtglob=!1,isGlob=!1;let base=str,prefix="",glob="";if(start>0)prefix=str.slice(0,start),str=str.slice(start),lastIndex-=start;if(base&&isGlob===!0&&lastIndex>0)base=str.slice(0,lastIndex),glob=str.slice(lastIndex);else if(isGlob===!0)base="",glob=str;else base=str;if(base&&base!==""&&base!=="/"&&base!==str){if(isPathSeparator(base.charCodeAt(base.length-1)))base=base.slice(0,-1)}if(opts.unescape===!0){if(glob)glob=utils.removeBackslashes(glob);if(base&&backslashes===!0)base=utils.removeBackslashes(base)}let state={prefix,input,start,base,glob,isBrace,isBracket,isGlob,isExtglob,isGlobstar,negated,negatedExtglob};if(opts.tokens===!0){if(state.maxDepth=0,!isPathSeparator(code))tokens.push(token);state.tokens=tokens}if(opts.parts===!0||opts.tokens===!0){let prevIndex;for(let idx=0;idx<slashes.length;idx++){let n=prevIndex?prevIndex+1:start,i=slashes[idx],value=input.slice(n,i);if(opts.tokens){if(idx===0&&start!==0)tokens[idx].isPrefix=!0,tokens[idx].value=prefix;else tokens[idx].value=value;depth(tokens[idx]),state.maxDepth+=tokens[idx].depth}if(idx!==0||value!=="")parts.push(value);prevIndex=i}if(prevIndex&&prevIndex+1<input.length){let value=input.slice(prevIndex+1);if(parts.push(value),opts.tokens)tokens[tokens.length-1].value=value,depth(tokens[tokens.length-1]),state.maxDepth+=tokens[tokens.length-1].depth}state.slashes=slashes,state.parts=parts}return state};module.exports=scan});var require_parse=__commonJS((exports,module)=>{var constants2=require_constants(),utils=require_utils(),{MAX_LENGTH,POSIX_REGEX_SOURCE,REGEX_NON_SPECIAL_CHARS,REGEX_SPECIAL_CHARS_BACKREF,REPLACEMENTS}=constants2,expandRange=(args2,options)=>{if(typeof options.expandRange==="function")return options.expandRange(...args2,options);args2.sort();let value=`[${args2.join("-")}]`;try{new RegExp(value)}catch(ex){return args2.map((v)=>utils.escapeRegex(v)).join("..")}return value},syntaxError=(type,char)=>{return`Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`},splitTopLevel=(input)=>{let parts=[],bracket=0,paren=0,quote=0,value="",escaped=!1;for(let ch of input){if(escaped===!0){value+=ch,escaped=!1;continue}if(ch==="\\"){value+=ch,escaped=!0;continue}if(ch==='"'){quote=quote===1?0:1,value+=ch;continue}if(quote===0){if(ch==="[")bracket++;else if(ch==="]"&&bracket>0)bracket--;else if(bracket===0){if(ch==="(")paren++;else if(ch===")"&&paren>0)paren--;else if(ch==="|"&&paren===0){parts.push(value),value="";continue}}}value+=ch}return parts.push(value),parts},isPlainBranch=(branch)=>{let escaped=!1;for(let ch of branch){if(escaped===!0){escaped=!1;continue}if(ch==="\\"){escaped=!0;continue}if(/[?*+@!()[\]{}]/.test(ch))return!1}return!0},normalizeSimpleBranch=(branch)=>{let value=branch.trim(),changed=!0;while(changed===!0)if(changed=!1,/^@\([^\\()[\]{}|]+\)$/.test(value))value=value.slice(2,-1),changed=!0;if(!isPlainBranch(value))return;return value.replace(/\\(.)/g,"$1")},hasRepeatedCharPrefixOverlap=(branches)=>{let values=branches.map(normalizeSimpleBranch).filter(Boolean);for(let i=0;i<values.length;i++)for(let j=i+1;j<values.length;j++){let a=values[i],b=values[j],char=a[0];if(!char||a!==char.repeat(a.length)||b!==char.repeat(b.length))continue;if(a===b||a.startsWith(b)||b.startsWith(a))return!0}return!1},parseRepeatedExtglob=(pattern,requireEnd=!0)=>{if(pattern[0]!=="+"&&pattern[0]!=="*"||pattern[1]!=="(")return;let bracket=0,paren=0,quote=0,escaped=!1;for(let i=1;i<pattern.length;i++){let ch=pattern[i];if(escaped===!0){escaped=!1;continue}if(ch==="\\"){escaped=!0;continue}if(ch==='"'){quote=quote===1?0:1;continue}if(quote===1)continue;if(ch==="["){bracket++;continue}if(ch==="]"&&bracket>0){bracket--;continue}if(bracket>0)continue;if(ch==="("){paren++;continue}if(ch===")"){if(paren--,paren===0){if(requireEnd===!0&&i!==pattern.length-1)return;return{type:pattern[0],body:pattern.slice(2,i),end:i}}}}},getStarExtglobSequenceOutput=(pattern)=>{let index=0,chars=[];while(index<pattern.length){let match=parseRepeatedExtglob(pattern.slice(index),!1);if(!match||match.type!=="*")return;let branches=splitTopLevel(match.body).map((branch2)=>branch2.trim());if(branches.length!==1)return;let branch=normalizeSimpleBranch(branches[0]);if(!branch||branch.length!==1)return;chars.push(branch),index+=match.end+1}if(chars.length<1)return;return`${chars.length===1?utils.escapeRegex(chars[0]):`[${chars.map((ch)=>utils.escapeRegex(ch)).join("")}]`}*`},repeatedExtglobRecursion=(pattern)=>{let depth=0,value=pattern.trim(),match=parseRepeatedExtglob(value);while(match)depth++,value=match.body.trim(),match=parseRepeatedExtglob(value);return depth},analyzeRepeatedExtglob=(body,options)=>{if(options.maxExtglobRecursion===!1)return{risky:!1};let max=typeof options.maxExtglobRecursion==="number"?options.maxExtglobRecursion:constants2.DEFAULT_MAX_EXTGLOB_RECURSION,branches=splitTopLevel(body).map((branch)=>branch.trim());if(branches.length>1){if(branches.some((branch)=>branch==="")||branches.some((branch)=>/^[*?]+$/.test(branch))||hasRepeatedCharPrefixOverlap(branches))return{risky:!0}}for(let branch of branches){let safeOutput=getStarExtglobSequenceOutput(branch);if(safeOutput)return{risky:!0,safeOutput};if(repeatedExtglobRecursion(branch)>max)return{risky:!0}}return{risky:!1}},parse5=(input,options)=>{if(typeof input!=="string")throw TypeError("Expected a string");input=REPLACEMENTS[input]||input;let opts={...options},max=typeof opts.maxLength==="number"?Math.min(MAX_LENGTH,opts.maxLength):MAX_LENGTH,len=input.length;if(len>max)throw SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`);let bos={type:"bos",value:"",output:opts.prepend||""},tokens=[bos],capture=opts.capture?"":"?:",PLATFORM_CHARS=constants2.globChars(opts.windows),EXTGLOB_CHARS=constants2.extglobChars(PLATFORM_CHARS),{DOT_LITERAL,PLUS_LITERAL,SLASH_LITERAL,ONE_CHAR,DOTS_SLASH,NO_DOT,NO_DOT_SLASH,NO_DOTS_SLASH,QMARK,QMARK_NO_DOT,STAR,START_ANCHOR}=PLATFORM_CHARS,globstar=(opts2)=>{return`(${capture}(?:(?!${START_ANCHOR}${opts2.dot?DOTS_SLASH:DOT_LITERAL}).)*?)`},nodot=opts.dot?"":NO_DOT,qmarkNoDot=opts.dot?QMARK:QMARK_NO_DOT,star=opts.bash===!0?globstar(opts):STAR;if(opts.capture)star=`(${star})`;if(typeof opts.noext==="boolean")opts.noextglob=opts.noext;let state={input,index:-1,start:0,dot:opts.dot===!0,consumed:"",output:"",prefix:"",backtrack:!1,negated:!1,brackets:0,braces:0,parens:0,quotes:0,globstar:!1,tokens};input=utils.removePrefix(input,state),len=input.length;let extglobs=[],braces=[],stack=[],prev=bos,value,eos=()=>state.index===len-1,peek=state.peek=(n=1)=>input[state.index+n],advance=state.advance=()=>input[++state.index]||"",remaining=()=>input.slice(state.index+1),consume=(value2="",num=0)=>{state.consumed+=value2,state.index+=num},append=(token)=>{state.output+=token.output!=null?token.output:token.value,consume(token.value)},negate=()=>{let count=1;while(peek()==="!"&&(peek(2)!=="("||peek(3)==="?"))advance(),state.start++,count++;if(count%2===0)return!1;return state.negated=!0,state.start++,!0},increment=(type)=>{state[type]++,stack.push(type)},decrement=(type)=>{state[type]--,stack.pop()},push=(tok)=>{if(prev.type==="globstar"){let isBrace=state.braces>0&&(tok.type==="comma"||tok.type==="brace"),isExtglob=tok.extglob===!0||extglobs.length&&(tok.type==="pipe"||tok.type==="paren");if(tok.type!=="slash"&&tok.type!=="paren"&&!isBrace&&!isExtglob)state.output=state.output.slice(0,-prev.output.length),prev.type="star",prev.value="*",prev.output=star,state.output+=prev.output}if(extglobs.length&&tok.type!=="paren")extglobs[extglobs.length-1].inner+=tok.value;if(tok.value||tok.output)append(tok);if(prev&&prev.type==="text"&&tok.type==="text"){prev.output=(prev.output||prev.value)+tok.value,prev.value+=tok.value;return}tok.prev=prev,tokens.push(tok),prev=tok},extglobOpen=(type,value2)=>{let token={...EXTGLOB_CHARS[value2],conditions:1,inner:""};token.prev=prev,token.parens=state.parens,token.output=state.output,token.startIndex=state.index,token.tokensIndex=tokens.length;let output=(opts.capture?"(":"")+token.open;increment("parens"),push({type,value:value2,output:state.output?"":ONE_CHAR}),push({type:"paren",extglob:!0,value:advance(),output}),extglobs.push(token)},extglobClose=(token)=>{let literal2=input.slice(token.startIndex,state.index+1),body=input.slice(token.startIndex+2,state.index),analysis=analyzeRepeatedExtglob(body,opts);if((token.type==="plus"||token.type==="star")&&analysis.risky){let safeOutput=analysis.safeOutput?(token.output?"":ONE_CHAR)+(opts.capture?`(${analysis.safeOutput})`:analysis.safeOutput):void 0,open2=tokens[token.tokensIndex];open2.type="text",open2.value=literal2,open2.output=safeOutput||utils.escapeRegex(literal2);for(let i=token.tokensIndex+1;i<tokens.length;i++)tokens[i].value="",tokens[i].output="",delete tokens[i].suffix;state.output=token.output+open2.output,state.backtrack=!0,push({type:"paren",extglob:!0,value,output:""}),decrement("parens");return}let output=token.close+(opts.capture?")":""),rest;if(token.type==="negate"){let extglobStar=star;if(token.inner&&token.inner.length>1&&token.inner.includes("/"))extglobStar=globstar(opts);if(extglobStar!==star||eos()||/^\)+$/.test(remaining()))output=token.close=`)$))${extglobStar}`;if(token.inner.includes("*")&&(rest=remaining())&&/^\.[^\\/.]+$/.test(rest)){let expression=parse5(rest,{...options,fastpaths:!1}).output;output=token.close=`)${expression})${extglobStar})`}if(token.prev.type==="bos")state.negatedExtglob=!0}push({type:"paren",extglob:!0,value,output}),decrement("parens")};if(opts.fastpaths!==!1&&!/(^[*!]|[/()[\]{}"])/.test(input)){let backslashes=!1,output=input.replace(REGEX_SPECIAL_CHARS_BACKREF,(m,esc2,chars,first,rest,index)=>{if(first==="\\")return backslashes=!0,m;if(first==="?"){if(esc2)return esc2+first+(rest?QMARK.repeat(rest.length):"");if(index===0)return qmarkNoDot+(rest?QMARK.repeat(rest.length):"");return QMARK.repeat(chars.length)}if(first===".")return DOT_LITERAL.repeat(chars.length);if(first==="*"){if(esc2)return esc2+first+(rest?star:"");return star}return esc2?m:`\\${m}`});if(backslashes===!0)if(opts.unescape===!0)output=output.replace(/\\/g,"");else output=output.replace(/\\+/g,(m)=>{return m.length%2===0?"\\\\":m?"\\":""});if(output===input&&opts.contains===!0)return state.output=input,state;return state.output=utils.wrapOutput(output,state,options),state}while(!eos()){if(value=advance(),value==="\x00")continue;if(value==="\\"){let next=peek();if(next==="/"&&opts.bash!==!0)continue;if(next==="."||next===";")continue;if(!next){value+="\\",push({type:"text",value});continue}let match=/^\\+/.exec(remaining()),slashes=0;if(match&&match[0].length>2){if(slashes=match[0].length,state.index+=slashes,slashes%2!==0)value+="\\"}if(opts.unescape===!0)value=advance();else value+=advance();if(state.brackets===0){push({type:"text",value});continue}}if(state.brackets>0&&(value!=="]"||prev.value==="["||prev.value==="[^")){if(opts.posix!==!1&&value===":"){let inner=prev.value.slice(1);if(inner.includes("[")){if(prev.posix=!0,inner.includes(":")){let idx=prev.value.lastIndexOf("["),pre=prev.value.slice(0,idx),rest2=prev.value.slice(idx+2),posix=POSIX_REGEX_SOURCE[rest2];if(posix){if(prev.value=pre+posix,state.backtrack=!0,advance(),!bos.output&&tokens.indexOf(prev)===1)bos.output=ONE_CHAR;continue}}}}if(value==="["&&peek()!==":"||value==="-"&&peek()==="]")value=`\\${value}`;if(value==="]"&&(prev.value==="["||prev.value==="[^"))value=`\\${value}`;if(opts.posix===!0&&value==="!"&&prev.value==="[")value="^";prev.value+=value,append({value});continue}if(state.quotes===1&&value!=='"'){value=utils.escapeRegex(value),prev.value+=value,append({value});continue}if(value==='"'){if(state.quotes=state.quotes===1?0:1,opts.keepQuotes===!0)push({type:"text",value});continue}if(value==="("){increment("parens"),push({type:"paren",value});continue}if(value===")"){if(state.parens===0&&opts.strictBrackets===!0)throw SyntaxError(syntaxError("opening","("));let extglob=extglobs[extglobs.length-1];if(extglob&&state.parens===extglob.parens+1){extglobClose(extglobs.pop());continue}push({type:"paren",value,output:state.parens?")":"\\)"}),decrement("parens");continue}if(value==="["){if(opts.nobracket===!0||!remaining().includes("]")){if(opts.nobracket!==!0&&opts.strictBrackets===!0)throw SyntaxError(syntaxError("closing","]"));value=`\\${value}`}else increment("brackets");push({type:"bracket",value});continue}if(value==="]"){if(opts.nobracket===!0||prev&&prev.type==="bracket"&&prev.value.length===1){push({type:"text",value,output:`\\${value}`});continue}if(state.brackets===0){if(opts.strictBrackets===!0)throw SyntaxError(syntaxError("opening","["));push({type:"text",value,output:`\\${value}`});continue}decrement("brackets");let prevValue=prev.value.slice(1);if(prev.posix!==!0&&prevValue[0]==="^"&&!prevValue.includes("/"))value=`/${value}`;if(prev.value+=value,append({value}),opts.literalBrackets===!1||utils.hasRegexChars(prevValue))continue;let escaped=utils.escapeRegex(prev.value);if(state.output=state.output.slice(0,-prev.value.length),opts.literalBrackets===!0){state.output+=escaped,prev.value=escaped;continue}prev.value=`(${capture}${escaped}|${prev.value})`,state.output+=prev.value;continue}if(value==="{"&&opts.nobrace!==!0){increment("braces");let open2={type:"brace",value,output:"(",outputIndex:state.output.length,tokensIndex:state.tokens.length};braces.push(open2),push(open2);continue}if(value==="}"){let brace=braces[braces.length-1];if(opts.nobrace===!0||!brace){push({type:"text",value,output:value});continue}let output=")";if(brace.dots===!0){let arr=tokens.slice(),range=[];for(let i=arr.length-1;i>=0;i--){if(tokens.pop(),arr[i].type==="brace")break;if(arr[i].type!=="dots")range.unshift(arr[i].value)}output=expandRange(range,opts),state.backtrack=!0}if(brace.comma!==!0&&brace.dots!==!0){let out=state.output.slice(0,brace.outputIndex),toks=state.tokens.slice(brace.tokensIndex);brace.value=brace.output="\\{",value=output="\\}",state.output=out;for(let t of toks)state.output+=t.output||t.value}push({type:"brace",value,output}),decrement("braces"),braces.pop();continue}if(value==="|"){if(extglobs.length>0)extglobs[extglobs.length-1].conditions++;push({type:"text",value});continue}if(value===","){let output=value,brace=braces[braces.length-1];if(brace&&stack[stack.length-1]==="braces")brace.comma=!0,output="|";push({type:"comma",value,output});continue}if(value==="/"){if(prev.type==="dot"&&state.index===state.start+1){state.start=state.index+1,state.consumed="",state.output="",tokens.pop(),prev=bos;continue}push({type:"slash",value,output:SLASH_LITERAL});continue}if(value==="."){if(state.braces>0&&prev.type==="dot"){if(prev.value===".")prev.output=DOT_LITERAL;let brace=braces[braces.length-1];prev.type="dots",prev.output+=value,prev.value+=value,brace.dots=!0;continue}if(state.braces+state.parens===0&&prev.type!=="bos"&&prev.type!=="slash"){push({type:"text",value,output:DOT_LITERAL});continue}push({type:"dot",value,output:DOT_LITERAL});continue}if(value==="?"){if(!(prev&&prev.value==="(")&&opts.noextglob!==!0&&peek()==="("&&peek(2)!=="?"){extglobOpen("qmark",value);continue}if(prev&&prev.type==="paren"){let next=peek(),output=value;if(prev.value==="("&&!/[!=<:]/.test(next)||next==="<"&&!/<([!=]|\w+>)/.test(remaining()))output=`\\${value}`;push({type:"text",value,output});continue}if(opts.dot!==!0&&(prev.type==="slash"||prev.type==="bos")){push({type:"qmark",value,output:QMARK_NO_DOT});continue}push({type:"qmark",value,output:QMARK});continue}if(value==="!"){if(opts.noextglob!==!0&&peek()==="("){if(peek(2)!=="?"||!/[!=<:]/.test(peek(3))){extglobOpen("negate",value);continue}}if(opts.nonegate!==!0&&state.index===0){negate();continue}}if(value==="+"){if(opts.noextglob!==!0&&peek()==="("&&peek(2)!=="?"){extglobOpen("plus",value);continue}if(prev&&prev.value==="("||opts.regex===!1){push({type:"plus",value,output:PLUS_LITERAL});continue}if(prev&&(prev.type==="bracket"||prev.type==="paren"||prev.type==="brace")||state.parens>0){push({type:"plus",value});continue}push({type:"plus",value:PLUS_LITERAL});continue}if(value==="@"){if(opts.noextglob!==!0&&peek()==="("&&peek(2)!=="?"){push({type:"at",extglob:!0,value,output:""});continue}push({type:"text",value});continue}if(value!=="*"){if(value==="$"||value==="^")value=`\\${value}`;let match=REGEX_NON_SPECIAL_CHARS.exec(remaining());if(match)value+=match[0],state.index+=match[0].length;push({type:"text",value});continue}if(prev&&(prev.type==="globstar"||prev.star===!0)){prev.type="star",prev.star=!0,prev.value+=value,prev.output=star,state.backtrack=!0,state.globstar=!0,consume(value);continue}let rest=remaining();if(opts.noextglob!==!0&&/^\([^?]/.test(rest)){extglobOpen("star",value);continue}if(prev.type==="star"){if(opts.noglobstar===!0){consume(value);continue}let prior=prev.prev,before=prior.prev,isStart=prior.type==="slash"||prior.type==="bos",afterStar=before&&(before.type==="star"||before.type==="globstar");if(opts.bash===!0&&(!isStart||rest[0]&&rest[0]!=="/")){push({type:"star",value,output:""});continue}let isBrace=state.braces>0&&(prior.type==="comma"||prior.type==="brace"),isExtglob=extglobs.length&&(prior.type==="pipe"||prior.type==="paren");if(!isStart&&prior.type!=="paren"&&!isBrace&&!isExtglob){push({type:"star",value,output:""});continue}while(rest.slice(0,3)==="/**"){let after=input[state.index+4];if(after&&after!=="/")break;rest=rest.slice(3),consume("/**",3)}if(prior.type==="bos"&&eos()){prev.type="globstar",prev.value+=value,prev.output=globstar(opts),state.output=prev.output,state.globstar=!0,consume(value);continue}if(prior.type==="slash"&&prior.prev.type!=="bos"&&!afterStar&&eos()){state.output=state.output.slice(0,-(prior.output+prev.output).length),prior.output=`(?:${prior.output}`,prev.type="globstar",prev.output=globstar(opts)+(opts.strictSlashes?")":"|$)"),prev.value+=value,state.globstar=!0,state.output+=prior.output+prev.output,consume(value);continue}if(prior.type==="slash"&&prior.prev.type!=="bos"&&rest[0]==="/"){let end=rest[1]!==void 0?"|$":"";state.output=state.output.slice(0,-(prior.output+prev.output).length),prior.output=`(?:${prior.output}`,prev.type="globstar",prev.output=`${globstar(opts)}${SLASH_LITERAL}|${SLASH_LITERAL}${end})`,prev.value+=value,state.output+=prior.output+prev.output,state.globstar=!0,consume(value+advance()),push({type:"slash",value:"/",output:""});continue}if(prior.type==="bos"&&rest[0]==="/"){prev.type="globstar",prev.value+=value,prev.output=`(?:^|${SLASH_LITERAL}|${globstar(opts)}${SLASH_LITERAL})`,state.output=prev.output,state.globstar=!0,consume(value+advance()),push({type:"slash",value:"/",output:""});continue}state.output=state.output.slice(0,-prev.output.length),prev.type="globstar",prev.output=globstar(opts),prev.value+=value,state.output+=prev.output,state.globstar=!0,consume(value);continue}let token={type:"star",value,output:star};if(opts.bash===!0){if(token.output=".*?",prev.type==="bos"||prev.type==="slash")token.output=nodot+token.output;push(token);continue}if(prev&&(prev.type==="bracket"||prev.type==="paren")&&opts.regex===!0){token.output=value,push(token);continue}if(state.index===state.start||prev.type==="slash"||prev.type==="dot"){if(prev.type==="dot")state.output+=NO_DOT_SLASH,prev.output+=NO_DOT_SLASH;else if(opts.dot===!0)state.output+=NO_DOTS_SLASH,prev.output+=NO_DOTS_SLASH;else state.output+=nodot,prev.output+=nodot;if(peek()!=="*")state.output+=ONE_CHAR,prev.output+=ONE_CHAR}push(token)}while(state.brackets>0){if(opts.strictBrackets===!0)throw SyntaxError(syntaxError("closing","]"));state.output=utils.escapeLast(state.output,"["),decrement("brackets")}while(state.parens>0){if(opts.strictBrackets===!0)throw SyntaxError(syntaxError("closing",")"));state.output=utils.escapeLast(state.output,"("),decrement("parens")}while(state.braces>0){if(opts.strictBrackets===!0)throw SyntaxError(syntaxError("closing","}"));state.output=utils.escapeLast(state.output,"{"),decrement("braces")}if(opts.strictSlashes!==!0&&(prev.type==="star"||prev.type==="bracket"))push({type:"maybe_slash",value:"",output:`${SLASH_LITERAL}?`});if(state.backtrack===!0){state.output="";for(let token of state.tokens)if(state.output+=token.output!=null?token.output:token.value,token.suffix)state.output+=token.suffix}return state};parse5.fastpaths=(input,options)=>{let opts={...options},max=typeof opts.maxLength==="number"?Math.min(MAX_LENGTH,opts.maxLength):MAX_LENGTH,len=input.length;if(len>max)throw SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`);input=REPLACEMENTS[input]||input;let{DOT_LITERAL,SLASH_LITERAL,ONE_CHAR,DOTS_SLASH,NO_DOT,NO_DOTS,NO_DOTS_SLASH,STAR,START_ANCHOR}=constants2.globChars(opts.windows),nodot=opts.dot?NO_DOTS:NO_DOT,slashDot=opts.dot?NO_DOTS_SLASH:NO_DOT,capture=opts.capture?"":"?:",state={negated:!1,prefix:""},star=opts.bash===!0?".*?":STAR;if(opts.capture)star=`(${star})`;let globstar=(opts2)=>{if(opts2.noglobstar===!0)return star;return`(${capture}(?:(?!${START_ANCHOR}${opts2.dot?DOTS_SLASH:DOT_LITERAL}).)*?)`},create=(str)=>{switch(str){case"*":return`${nodot}${ONE_CHAR}${star}`;case".*":return`${DOT_LITERAL}${ONE_CHAR}${star}`;case"*.*":return`${nodot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`;case"*/*":return`${nodot}${star}${SLASH_LITERAL}${ONE_CHAR}${slashDot}${star}`;case"**":return nodot+globstar(opts);case"**/*":return`(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${ONE_CHAR}${star}`;case"**/*.*":return`(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`;case"**/.*":return`(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${DOT_LITERAL}${ONE_CHAR}${star}`;default:{let match=/^(.*?)\.(\w+)$/.exec(str);if(!match)return;let source2=create(match[1]);if(!source2)return;return source2+DOT_LITERAL+match[2]}}},output=utils.removePrefix(input,state),source=create(output);if(source&&opts.strictSlashes!==!0)source+=`${SLASH_LITERAL}?`;return source};module.exports=parse5});var require_picomatch=__commonJS((exports,module)=>{var scan=require_scan(),parse5=require_parse(),utils=require_utils(),constants2=require_constants(),isObject2=(val)=>val&&typeof val==="object"&&!Array.isArray(val),picomatch=(glob,options,returnState=!1)=>{if(Array.isArray(glob)){let fns=glob.map((input)=>picomatch(input,options,returnState));return(str)=>{for(let isMatch of fns){let state2=isMatch(str);if(state2)return state2}return!1}}let isState=isObject2(glob)&&glob.tokens&&glob.input;if(glob===""||typeof glob!=="string"&&!isState)throw TypeError("Expected pattern to be a non-empty string");let opts=options||{},posix=opts.windows,regex=isState?picomatch.compileRe(glob,options):picomatch.makeRe(glob,options,!1,!0),state=regex.state;delete regex.state;let isIgnored=()=>!1;if(opts.ignore){let ignoreOpts={...options,ignore:null,onMatch:null,onResult:null};isIgnored=picomatch(opts.ignore,ignoreOpts,returnState)}let matcher=(input,returnObject=!1)=>{let{isMatch,match,output}=picomatch.test(input,regex,options,{glob,posix}),result={glob,state,regex,posix,input,output,match,isMatch};if(typeof opts.onResult==="function")opts.onResult(result);if(isMatch===!1)return result.isMatch=!1,returnObject?result:!1;if(isIgnored(input)){if(typeof opts.onIgnore==="function")opts.onIgnore(result);return result.isMatch=!1,returnObject?result:!1}if(typeof opts.onMatch==="function")opts.onMatch(result);return returnObject?result:!0};if(returnState)matcher.state=state;return matcher};picomatch.test=(input,regex,options,{glob,posix}={})=>{if(typeof input!=="string")throw TypeError("Expected input to be a string");if(input==="")return{isMatch:!1,output:""};let opts=options||{},format=opts.format||(posix?utils.toPosixSlashes:null),match=input===glob,output=match&&format?format(input):input;if(match===!1)output=format?format(input):input,match=output===glob;if(match===!1||opts.capture===!0)if(opts.matchBase===!0||opts.basename===!0)match=picomatch.matchBase(input,regex,options,posix);else match=regex.exec(output);return{isMatch:Boolean(match),match,output}};picomatch.matchBase=(input,glob,options)=>{return(glob instanceof RegExp?glob:picomatch.makeRe(glob,options)).test(utils.basename(input))};picomatch.isMatch=(str,patterns,options)=>picomatch(patterns,options)(str);picomatch.parse=(pattern,options)=>{if(Array.isArray(pattern))return pattern.map((p)=>picomatch.parse(p,options));return parse5(pattern,{...options,fastpaths:!1})};picomatch.scan=(input,options)=>scan(input,options);picomatch.compileRe=(state,options,returnOutput=!1,returnState=!1)=>{if(returnOutput===!0)return state.output;let opts=options||{},prepend=opts.contains?"":"^",append=opts.contains?"":"$",source=`${prepend}(?:${state.output})${append}`;if(state&&state.negated===!0)source=`^(?!${source}).*$`;let regex=picomatch.toRegex(source,options);if(returnState===!0)regex.state=state;return regex};picomatch.makeRe=(input,options={},returnOutput=!1,returnState=!1)=>{if(!input||typeof input!=="string")throw TypeError("Expected a non-empty string");let parsed={negated:!1,fastpaths:!0};if(options.fastpaths!==!1&&(input[0]==="."||input[0]==="*"))parsed.output=parse5.fastpaths(input,options);if(!parsed.output)parsed=parse5(input,options);return picomatch.compileRe(parsed,options,returnOutput,returnState)};picomatch.toRegex=(source,options)=>{try{let opts=options||{};return new RegExp(source,opts.flags||(opts.nocase?"i":""))}catch(err){if(options&&options.debug===!0)throw err;return/$^/}};picomatch.constants=constants2;module.exports=picomatch});var require_picomatch2=__commonJS((exports,module)=>{var pico=require_picomatch(),utils=require_utils();function picomatch(glob,options,returnState=!1){if(options&&(options.windows===null||options.windows===void 0))options={...options,windows:utils.isWindows()};return pico(glob,options,returnState)}Object.assign(picomatch,pico);module.exports=picomatch});var QuickLRU;var init_quick_lru=__esm(()=>{QuickLRU=class QuickLRU extends Map{#size=0;#cache=new Map;#oldCache=new Map;#maxSize;#maxAge;#onEviction;constructor(options={}){super();if(!(options.maxSize&&options.maxSize>0))throw TypeError("`maxSize` must be a number greater than 0");if(typeof options.maxAge==="number"&&options.maxAge===0)throw TypeError("`maxAge` must be a number greater than 0");this.#maxSize=options.maxSize,this.#maxAge=options.maxAge||Number.POSITIVE_INFINITY,this.#onEviction=options.onEviction}get __oldCache(){return this.#oldCache}#emitEvictions(cache){if(typeof this.#onEviction!=="function")return;for(let[key,item]of cache)this.#onEviction(key,item.value)}#deleteIfExpired(key,item){if(typeof item.expiry==="number"&&item.expiry<=Date.now()){if(typeof this.#onEviction==="function")this.#onEviction(key,item.value);return this.delete(key)}return!1}#getOrDeleteIfExpired(key,item){if(this.#deleteIfExpired(key,item)===!1)return item.value}#getItemValue(key,item){return item.expiry?this.#getOrDeleteIfExpired(key,item):item.value}#peek(key,cache){let item=cache.get(key);return this.#getItemValue(key,item)}#set(key,value){if(this.#cache.set(key,value),this.#size++,this.#size>=this.#maxSize)this.#size=0,this.#emitEvictions(this.#oldCache),this.#oldCache=this.#cache,this.#cache=new Map}#moveToRecent(key,item){this.#oldCache.delete(key),this.#set(key,item)}*#entriesAscending(){for(let item of this.#oldCache){let[key,value]=item;if(!this.#cache.has(key)){if(this.#deleteIfExpired(key,value)===!1)yield item}}for(let item of this.#cache){let[key,value]=item;if(this.#deleteIfExpired(key,value)===!1)yield item}}get(key){if(this.#cache.has(key)){let item=this.#cache.get(key);return this.#getItemValue(key,item)}if(this.#oldCache.has(key)){let item=this.#oldCache.get(key);if(this.#deleteIfExpired(key,item)===!1)return this.#moveToRecent(key,item),item.value}}set(key,value,{maxAge=this.#maxAge}={}){let expiry=typeof maxAge==="number"&&maxAge!==Number.POSITIVE_INFINITY?Date.now()+maxAge:void 0;if(this.#cache.has(key))this.#cache.set(key,{value,expiry});else this.#set(key,{value,expiry});return this}has(key){if(this.#cache.has(key))return!this.#deleteIfExpired(key,this.#cache.get(key));if(this.#oldCache.has(key))return!this.#deleteIfExpired(key,this.#oldCache.get(key));return!1}peek(key){if(this.#cache.has(key))return this.#peek(key,this.#cache);if(this.#oldCache.has(key))return this.#peek(key,this.#oldCache)}expiresIn(key){let item=this.#cache.get(key)??this.#oldCache.get(key);if(item)return item.expiry?item.expiry-Date.now():Number.POSITIVE_INFINITY}delete(key){let deleted=this.#cache.delete(key);if(deleted)this.#size--;return this.#oldCache.delete(key)||deleted}clear(){this.#cache.clear(),this.#oldCache.clear(),this.#size=0}resize(newSize){if(!(newSize&&newSize>0))throw TypeError("`maxSize` must be a number greater than 0");let items=[...this.#entriesAscending()],removeCount=items.length-newSize;if(removeCount<0)this.#cache=new Map(items),this.#oldCache=new Map,this.#size=items.length;else{if(removeCount>0)this.#emitEvictions(items.slice(0,removeCount));this.#oldCache=new Map(items.slice(removeCount)),this.#cache=new Map,this.#size=0}this.#maxSize=newSize}evict(count=1){let requested=Number(count);if(!requested||requested<=0)return;let items=[...this.#entriesAscending()],evictCount=Math.trunc(Math.min(requested,Math.max(items.length-1,0)));if(evictCount<=0)return;this.#emitEvictions(items.slice(0,evictCount)),this.#oldCache=new Map(items.slice(evictCount)),this.#cache=new Map,this.#size=0}*keys(){for(let[key]of this)yield key}*values(){for(let[,value]of this)yield value}*[Symbol.iterator](){for(let item of this.#cache){let[key,value]=item;if(this.#deleteIfExpired(key,value)===!1)yield[key,value.value]}for(let item of this.#oldCache){let[key,value]=item;if(!this.#cache.has(key)){if(this.#deleteIfExpired(key,value)===!1)yield[key,value.value]}}}*entriesDescending(){let items=[...this.#cache];for(let i=items.length-1;i>=0;--i){let item=items[i],[key,value]=item;if(this.#deleteIfExpired(key,value)===!1)yield[key,value.value]}items=[...this.#oldCache];for(let i=items.length-1;i>=0;--i){let item=items[i],[key,value]=item;if(!this.#cache.has(key)){if(this.#deleteIfExpired(key,value)===!1)yield[key,value.value]}}}*entriesAscending(){for(let[key,value]of this.#entriesAscending())yield[key,value.value]}get size(){if(!this.#size)return this.#oldCache.size;let oldCacheSize=0;for(let key of this.#oldCache.keys())if(!this.#cache.has(key))oldCacheSize++;return Math.min(this.#size+oldCacheSize,this.#maxSize)}get maxSize(){return this.#maxSize}get maxAge(){return this.#maxAge}entries(){return this.entriesAscending()}forEach(callbackFunction,thisArgument=this){for(let[key,value]of this.entriesAscending())callbackFunction.call(thisArgument,value,key,this)}get[Symbol.toStringTag](){return"QuickLRU"}toString(){return`QuickLRU(${this.size}/${this.maxSize})`}[Symbol.for("nodejs.util.inspect.custom")](){return this.toString()}}});function classifyFile(filePath){let normalized=filePath.toLowerCase().replace(/\\/g,"/");if(normalized.endsWith(".wasm")||normalized.startsWith("dist/")||normalized.includes("/dist/")||normalized.startsWith("build/")||normalized.includes("/build/")||normalized.includes(".swarm/checkpoints/"))return{filePath,zone:"generated",confidence:"high",reason:"path matches generated file patterns"};if(normalized.includes("/test/")||normalized.includes("/tests/")||normalized.includes("/__tests__/")||normalized.includes(".test.")||normalized.includes(".spec.")||normalized.includes("/mocks/"))return{filePath,zone:"test",confidence:"high",reason:"path matches test/**, tests/**, __tests__/**, *.test.*, *.spec.*, or **/mocks/**"};if(normalized.includes("/scripts/")||normalized.includes("makefile")||normalized.includes("dockerfile")||normalized.includes(".github/"))return{filePath,zone:"build",confidence:"high",reason:"path matches build scripts or CI configuration"};if(normalized.endsWith(".json")&&!normalized.includes(".github/")||normalized.endsWith(".yaml")&&!normalized.includes(".github/")||normalized.endsWith(".yml")&&!normalized.includes(".github/")||normalized.endsWith(".toml")||normalized.includes(".env")||normalized.endsWith("biome.json")||normalized.endsWith("tsconfig.json"))return{filePath,zone:"config",confidence:"high",reason:"extension is config file type"};if(normalized.includes("/docs/")||normalized.endsWith(".md")&&!normalized.includes("/")||normalized.includes("readme")||normalized.includes("changelog")||normalized.includes("license"))return{filePath,zone:"docs",confidence:"high",reason:"path matches docs/** or documentation files"};if(normalized.includes("/src/")||normalized.includes("/lib/"))return{filePath,zone:"production",confidence:"high",reason:"path matches src/** or lib/**"};return{filePath,zone:"production",confidence:"medium",reason:"default classification"}}import*as fsSync4 from"node:fs";import*as path25 from"node:path";function hashArgs(args2){try{if(typeof args2!=="object"||args2===null)return 0;let sortedKeys=Object.keys(args2).sort();return Number(bunHash(JSON.stringify(args2,sortedKeys)))}catch(error49){return log("[Guardrails] hashArgs failed",{error:error49 instanceof Error?error49.message:String(error49)}),0}}function normalizePathWithCache(filePath,cwd){let cacheKey=`${cwd}:${filePath}`,cached2=pathNormalizationCache.get(cacheKey);if(cached2!==void 0)return cached2;try{let absolutePath=path25.isAbsolute(filePath)?filePath:path25.resolve(cwd,filePath),normalized=fsSync4.realpathSync(absolutePath);return pathNormalizationCache.set(cacheKey,normalized),normalized}catch{let fallback=path25.isAbsolute(filePath)?filePath:path25.resolve(cwd,filePath);return pathNormalizationCache.set(cacheKey,fallback),fallback}}function getGlobMatcher(pattern,caseInsensitive=!0){let cacheKey=`${caseInsensitive?"nocase":"case"}\x00${pattern}`,cached2=globMatcherCache.get(cacheKey);if(cached2!==void 0)return cached2;try{let matcher=import_picomatch.default(pattern,{dot:!0,nocase:caseInsensitive});return globMatcherCache.set(cacheKey,matcher),matcher}catch(err){return warn(`picomatch error for pattern "${pattern}": ${err}`),()=>!1}}function checkWriteTargetForSymlink(targetPath,cwd){let normalizedCwd=path25.resolve(cwd),normalizedTarget=path25.resolve(cwd,targetPath),ancestors=[],current=normalizedTarget;while(!0){let rel=path25.relative(normalizedCwd,current);if(rel===""||rel.startsWith(".."))break;ancestors.push(current);let parent=path25.dirname(current);if(parent===current)break;current=parent}for(let ancestor of ancestors){let stat6=null;try{stat6=fsSync4.lstatSync(ancestor)}catch(err){if(err.code==="ENOENT")continue;return`WRITE BLOCKED: lstat failed on "${ancestor}": ${String(err)} — refusing write on unverifiable path`}if(stat6.isSymbolicLink())return`WRITE BLOCKED: "${ancestor}" is a symlink — writing through a symlink could redirect the write outside the working directory`}return null}function buildEffectiveRules(authorityConfig){if(authorityConfig?.enabled===!1||!authorityConfig?.rules)return{...DEFAULT_AGENT_AUTHORITY_RULES};let entries=Object.entries(authorityConfig.rules);if(entries.length===0)return{...DEFAULT_AGENT_AUTHORITY_RULES};let merged={...DEFAULT_AGENT_AUTHORITY_RULES};for(let[agent,userRule]of entries){let normalizedRuleKey=agent.toLowerCase(),existing=merged[normalizedRuleKey]??{};merged[normalizedRuleKey]={...existing,...userRule,readOnly:userRule.readOnly??existing.readOnly,blockedExact:userRule.blockedExact??existing.blockedExact,allowedExact:userRule.allowedExact??existing.allowedExact,blockedPrefix:userRule.blockedPrefix??existing.blockedPrefix,allowedPrefix:userRule.allowedPrefix??existing.allowedPrefix,blockedZones:userRule.blockedZones??existing.blockedZones,blockedGlobs:userRule.blockedGlobs??existing.blockedGlobs,allowedGlobs:userRule.allowedGlobs??existing.allowedGlobs,allowedCaseSensitiveGlobs:userRule.allowedCaseSensitiveGlobs??existing.allowedCaseSensitiveGlobs}}return merged}function isOnDifferentFilesystemRoot(targetAbsolute,cwdAbsolute,pathLib=path25){return pathLib.parse(targetAbsolute).root!==pathLib.parse(cwdAbsolute).root}function isInDeclaredScope(filePath,scopeEntries,cwd){let dir=cwd??process.cwd(),caseInsensitive=process.platform==="win32",resolvedFileRaw=path25.resolve(dir,filePath),resolvedFile=caseInsensitive?resolvedFileRaw.toLowerCase():resolvedFileRaw;return scopeEntries.some((scope)=>{let resolvedScopeRaw=path25.resolve(dir,scope),resolvedScope=caseInsensitive?resolvedScopeRaw.toLowerCase():resolvedScopeRaw;if(resolvedFile===resolvedScope)return!0;let rel=path25.relative(resolvedScope,resolvedFile);return rel.length>0&&!rel.startsWith("..")&&!path25.isAbsolute(rel)})}function checkFileAuthorityWithRules(agentName,filePath,cwd,effectiveRules,options){let normalizedAgent=agentName.toLowerCase(),strippedAgent=stripKnownSwarmPrefix(agentName).toLowerCase(),dir=cwd||process.cwd(),normalizedPath,resolvedTarget;try{let normalizedWithSymlinks=normalizePathWithCache(filePath,dir);resolvedTarget=path25.resolve(dir,normalizedWithSymlinks),normalizedPath=path25.relative(dir,resolvedTarget).replace(/\\/g,"/")}catch{resolvedTarget=path25.resolve(dir,filePath),normalizedPath=path25.relative(dir,resolvedTarget).replace(/\\/g,"/")}if(isOnDifferentFilesystemRoot(resolvedTarget,dir))return{allowed:!1,reason:`Path blocked: ${filePath} is on a different drive/root than the working directory`};if(normalizedPath===".."||normalizedPath.startsWith("../"))return{allowed:!1,reason:`Path blocked: ${normalizedPath} resolves outside the working directory`};let rules=effectiveRules[normalizedAgent]??effectiveRules[strippedAgent];if(!rules)return{allowed:!1,reason:`Unknown agent: ${agentName}`};if(rules.readOnly)return{allowed:!1,reason:`Path blocked: ${normalizedPath} (agent ${normalizedAgent} is read-only)`};if(rules.blockedExact){for(let blocked of rules.blockedExact)if(normalizedPath===blocked)return{allowed:!1,reason:`Path blocked (exact): ${normalizedPath}`}}if(rules.blockedGlobs&&rules.blockedGlobs.length>0){for(let glob of rules.blockedGlobs)if(getGlobMatcher(glob)(normalizedPath))return{allowed:!1,reason:`Path blocked (glob ${glob}): ${normalizedPath}`}}if(rules.allowedExact&&rules.allowedExact.length>0){if(rules.allowedExact.some((allowed)=>normalizedPath===allowed))return{allowed:!0}}if(rules.blockedZones&&rules.blockedZones.length>0){let{zone}=classifyFile(normalizedPath);if(rules.blockedZones.includes(zone))return{allowed:!1,reason:`Path blocked: ${normalizedPath} is in ${zone} zone`,zone}}if(rules.allowedGlobs&&rules.allowedGlobs.length>0){if(rules.allowedGlobs.some((glob)=>{return getGlobMatcher(glob)(normalizedPath)}))return{allowed:!0}}if(rules.allowedCaseSensitiveGlobs&&rules.allowedCaseSensitiveGlobs.length>0){if(rules.allowedCaseSensitiveGlobs.some((glob)=>{return getGlobMatcher(glob,!1)(normalizedPath)}))return{allowed:!0}}if(rules.blockedPrefix&&rules.blockedPrefix.length>0){for(let prefix of rules.blockedPrefix)if(normalizedPath.startsWith(prefix))return{allowed:!1,reason:`Path blocked: ${normalizedPath} is under ${prefix}`}}if(!((normalizedAgent==="coder"||strippedAgent==="coder")&&options?.declaredScope!=null&&options.declaredScope.length>0&&isInDeclaredScope(normalizedPath,options.declaredScope,dir))){if(rules.allowedPrefix!=null&&rules.allowedPrefix.length>0){if(!rules.allowedPrefix.some((prefix)=>normalizedPath.startsWith(prefix)))return{allowed:!1,reason:`Path ${normalizedPath} not in allowed list for ${normalizedAgent}`}}else if(rules.allowedPrefix!=null&&rules.allowedPrefix.length===0)return{allowed:!1,reason:`Path ${normalizedPath} not in allowed list for ${normalizedAgent}`}}return{allowed:!0}}function checkFileAuthority(agentName,filePath,cwd,authorityConfig,options){return checkFileAuthorityWithRules(agentName,filePath,cwd,buildEffectiveRules(authorityConfig),options)}var import_picomatch,pathNormalizationCache,globMatcherCache,DEFAULT_AGENT_AUTHORITY_RULES;var init_file_authority=__esm(()=>{init_quick_lru();init_schema();init_utils();init_bun_compat();import_picomatch=__toESM(require_picomatch2(),1);pathNormalizationCache=new QuickLRU({maxSize:500}),globMatcherCache=new QuickLRU({maxSize:200});DEFAULT_AGENT_AUTHORITY_RULES={build:{},plan:{},general:{},explore:{},architect:{blockedExact:[".swarm/plan.md",".swarm/plan.json"],blockedZones:["generated","config"],blockedGlobs:["**/oxlintrc*","**/.oxlintrc*","**/.eslintrc*","**/eslint.config.*","**/.prettierrc*","**/prettier.config.*","**/biome.jsonc","**/.secretscanignore","**/.golangci*"]},coder:{blockedPrefix:[".swarm/"],blockedZones:["generated","config"]},reviewer:{blockedExact:[".swarm/plan.md",".swarm/plan.json"],blockedPrefix:["src/"],allowedPrefix:[".swarm/evidence/",".swarm/outputs/"],blockedZones:["generated"]},explorer:{readOnly:!0},sme:{readOnly:!0},test_engineer:{blockedExact:[".swarm/plan.md",".swarm/plan.json"],blockedPrefix:["src/"],allowedPrefix:["tests/","test/",".swarm/evidence/"],allowedGlobs:["**/tests/**","**/test/**","**/__tests__/**","**/*.test.*","**/*.spec.*","test_*.py","**/test_*.py","*_test.py","**/*_test.py","*_test.go","**/*_test.go","*_spec.rb","**/*_spec.rb","*.Tests.ps1","**/*.Tests.ps1"],allowedCaseSensitiveGlobs:["*Test.java","**/*Test.java","*Test.kt","**/*Test.kt","*Tests.cs","**/*Tests.cs"],blockedZones:["generated"]},docs:{allowedPrefix:["docs/",".swarm/outputs/"],allowedGlobs:["**/docs/**","**/*.md","**/*.mdx","**/*.rst"],blockedZones:["generated"]},docs_design:{allowedPrefix:["docs/",".swarm/outputs/"],blockedGlobs:["src/**","lib/**"],allowedGlobs:["**/docs/**","**/*.md","**/*.mdx","**/*.rst","**/reference/traceability.json"],blockedZones:["generated"]},designer:{allowedPrefix:["docs/",".swarm/outputs/"],allowedGlobs:["**/docs/**","**/*.md","**/*.mdx","**/*.rst"],blockedZones:["generated"]},critic:{allowedPrefix:[".swarm/evidence/"],blockedZones:["generated"]}}});function resolveAgentConflict(input){let session=swarmState.agentSessions.get(input.sessionID);if(!session)return;session.pendingAdvisoryMessages??=[];let rejections=input.rejectionCount??0,resolutionPath;if(rejections>=3)resolutionPath="soundingboard",session.pendingAdvisoryMessages.push(`CONFLICT ESCALATION: ${input.sourceAgent} vs ${input.targetAgent} on task ${input.taskId??"unknown"}. Three or more failed cycles detected. Route to Critic in SOUNDING_BOARD mode, then simplify before any user escalation.`);else resolutionPath="self_resolve",session.pendingAdvisoryMessages.push(`CONFLICT DETECTED: ${input.sourceAgent} disagrees with ${input.targetAgent} on task ${input.taskId??"unknown"}. Attempt self-resolution using .swarm/plan.md, .swarm/spec.md, and .swarm/context.md before escalation.`);let event={type:"agent_conflict_detected",timestamp:new Date().toISOString(),sessionId:input.sessionID,phase:input.phase,taskId:input.taskId,sourceAgent:input.sourceAgent,targetAgent:input.targetAgent,conflictType:input.conflictType,resolutionPath,summary:input.summary};emit("agent_conflict_detected",event)}var init_conflict_resolution=__esm(()=>{init_state2();init_telemetry()});function extractCurrentPhase(planContent){if(!planContent)return null;let lines=planContent.split(`
|
|
429
429
|
`);for(let i=0;i<Math.min(20,lines.length);i++){let progressMatch=lines[i].trim().match(/^## Phase (\d+):?\s*(.*?)\s*\[IN PROGRESS\]/i);if(progressMatch){let phaseNum=progressMatch[1],description=progressMatch[2]?.trim()||"";return`Phase ${phaseNum}: ${description} [IN PROGRESS]`}}for(let i=0;i<Math.min(3,lines.length);i++){let phaseMatch=lines[i].trim().match(/Phase:\s*(\d+)/i);if(phaseMatch)return`Phase ${phaseMatch[1]} [PENDING]`}return null}function extractCurrentTask(planContent){if(!planContent)return null;let lines=planContent.split(`
|
|
430
430
|
`),inCurrentPhase=!1;for(let line of lines){if(line.startsWith("## ")&&/\[IN PROGRESS\]/i.test(line)){inCurrentPhase=!0;continue}if(inCurrentPhase){if(line.startsWith("## ")||line.trim()==="---")break;if(line.trim().startsWith("- [ ]"))return line.trim()}}return null}function extractDecisions(contextContent,maxChars=500){if(!contextContent)return null;let lines=contextContent.split(`
|
|
431
431
|
`),decisionsText="",inDecisionsSection=!1;for(let line of lines){if(line.trim()==="## Decisions"){inDecisionsSection=!0;continue}if(inDecisionsSection){if(line.startsWith("## "))break;if(line.startsWith("- "))decisionsText+=`${line}
|
|
@@ -614,7 +614,7 @@ Changed sections: ${diffInfo.changedSections.map((s)=>`## ${s}`).join(", ")}`:""
|
|
|
614
614
|
(no recorded snapshot to diff against)`;throw Error(message)}}function extractStatusCode2(errorMsg){let match=errorMsg.match(/\b(408|429|500|502|503|504|529)\b/);if(match)return parseInt(match[1],10);return null}function isPlainObject3(value){return typeof value==="object"&&value!==null&&(value.constructor===Object||Object.getPrototypeOf(value)===null)}function readSignalField(source,key){try{return source[key]}catch{return}}function pushSignalValue(parts,value){if(typeof value==="string"){parts.push(value);return}if(typeof value==="number"||typeof value==="boolean")parts.push(String(value))}function appendSelectedFields(parts,source,keys){for(let key of keys)pushSignalValue(parts,readSignalField(source,key))}function appendNestedErrorSignal(parts,value){if(typeof value==="string"){parts.push(value);return}if(value instanceof Error){parts.push(value.name,value.message),appendSelectedFields(parts,value,["code","status","statusCode"]);return}if(!isPlainObject3(value))return;appendSelectedFields(parts,value,["code","status","statusCode","message","error_type"])}function extractErrorSignal(errorContent){if(typeof errorContent==="string")return errorContent;if(errorContent==null)return"";let parts=[];try{if(errorContent instanceof Error)return parts.push(errorContent.name,errorContent.message),appendSelectedFields(parts,errorContent,["code","status","statusCode"]),parts.join(" ");if(!isPlainObject3(errorContent))return"";appendSelectedFields(parts,errorContent,["code","status","statusCode","message","error_type"]),appendNestedErrorSignal(parts,readSignalField(errorContent,"error"));let metadata=readSignalField(errorContent,"metadata");if(isPlainObject3(metadata))appendSelectedFields(parts,metadata,["code","status","statusCode","error_type"]);appendNestedErrorSignal(parts,readSignalField(errorContent,"cause"))}catch{return parts.join(" ")}return parts.join(" ")}function extractPhaseNumber2(phaseString){if(!phaseString)return 1;let match=phaseString.match(/^Phase (\d+):/);return match?parseInt(match[1],10):1}function isWriteTool2(toolName){let normalized=normalizeToolName(toolName);return WRITE_TOOL_NAMES.includes(normalized)}function isInDeclaredScope3(filePath,scopeEntries,cwd){let dir=cwd??process.cwd(),caseInsensitive=process.platform==="win32",resolvedFileRaw=path37.resolve(dir,filePath),resolvedFile=caseInsensitive?resolvedFileRaw.toLowerCase():resolvedFileRaw;return scopeEntries.some((scope)=>{let resolvedScopeRaw=path37.resolve(dir,scope),resolvedScope=caseInsensitive?resolvedScopeRaw.toLowerCase():resolvedScopeRaw;if(resolvedFile===resolvedScope)return!0;let rel=path37.relative(resolvedScope,resolvedFile);return rel.length>0&&!rel.startsWith("..")&&!path37.isAbsolute(rel)})}function isGateTool(toolName){let normalized=normalizeToolName(toolName);return["diff","syntax_check","placeholder_scan","imports","lint","build_check","pre_check_batch","secretscan","sast_scan","quality_budget"].includes(normalized)}function isAgentDelegation(toolName,args2){let normalized=normalizeToolName(toolName);if(normalized!=="Task"&&normalized!=="task")return{isDelegation:!1,targetAgent:null};let argsObj=args2;if(!argsObj)return{isDelegation:!1,targetAgent:null};let subagentType=argsObj.subagent_type;if(typeof subagentType==="string")return{isDelegation:!0,targetAgent:stripKnownSwarmPrefix(subagentType)};return{isDelegation:!1,targetAgent:null}}function getCurrentTaskId3(sessionId){return swarmState.agentSessions.get(sessionId)?.currentTaskId??`${sessionId}:unknown`}function createGuardrailsHooks(directory,directoryOrConfig,config2,authorityConfig){let guardrailsConfig;if(directory&&typeof directory==="object"&&"enabled"in directory)warn("[guardrails] Legacy call without directory, falling back to process.cwd()"),guardrailsConfig=directory;else if(directoryOrConfig&&typeof directoryOrConfig==="object"&&"enabled"in directoryOrConfig)guardrailsConfig=directoryOrConfig;else guardrailsConfig=config2;let effectiveDirectory=(()=>{if(typeof directory==="string")return directory;let cwd=process.cwd();return warn(`[guardrails] effectiveDirectory resolved to process.cwd() "${cwd}" — `+"pass an explicit directory string to createGuardrailsHooks to avoid .swarm artifacts in wrong locations"),cwd})();if(guardrailsConfig?.enabled===!1)return{toolBefore:async()=>{},toolAfter:async()=>{},messagesTransform:async()=>{}};let precomputedAuthorityRules=buildEffectiveRules(authorityConfig),verifierPaths=authorityConfig?.verifier_config_paths;if(verifierPaths&&verifierPaths.length>0){let existingArchitect=precomputedAuthorityRules.architect??{};precomputedAuthorityRules.architect={...existingArchitect,blockedGlobs:[...existingArchitect.blockedGlobs??[],...verifierPaths]}}let universalDenyPrefixes=authorityConfig?.universal_deny_prefixes??[],cfg=guardrailsConfig,requiredQaGates=cfg.qa_gates?.required_tools??["diff","syntax_check","placeholder_scan","lint","pre_check_batch"],requireReviewerAndTestEngineer=cfg.qa_gates?.require_reviewer_test_engineer??!0,interpreterAllowedAgents=cfg.interpreter_allowed_agents,shellAuditEnabled=cfg.shell_audit_log??!0,shellAuditPath=path37.join(effectiveDirectory,".swarm","session","shell-audit.jsonl"),consecutiveNoToolTurns=new Map,toolBefore=createToolBeforeHandler({effectiveDirectory,cfg,precomputedAuthorityRules,universalDenyPrefixes,shellAuditPath,shellAuditEnabled,interpreterAllowedAgents,authorityConfig,consecutiveNoToolTurns}),messagesTransform=createMessagesTransformHandler({effectiveDirectory,cfg,requiredQaGates,requireReviewerAndTestEngineer,consecutiveNoToolTurns});return{toolBefore,toolAfter:async(input,output)=>{let session=swarmState.agentSessions.get(input.sessionID);if(session){if(isGateTool(input.tool)){let taskId=getCurrentTaskId3(input.sessionID);if(!session.gateLog.has(taskId))session.gateLog.set(taskId,new Set);session.gateLog.get(taskId)?.add(input.tool);let outputStr=typeof output.output==="string"?output.output:"",isSkipCondition=!1;try{let result=JSON.parse(outputStr);if(result.lint?.ran===!1&&result.secretscan?.ran===!1&&result.sast_scan?.ran===!1&&result.quality_budget?.ran===!1)isSkipCondition=!0}catch{}if(!isSkipCondition&&(output.output===null||output.output===void 0||outputStr.includes("FAIL")||outputStr.includes("error")||outputStr.toLowerCase().includes("gates_passed: false")))session.lastGateFailure={tool:input.tool,taskId,timestamp:Date.now()};else if(session.lastGateFailure=null,input.tool==="pre_check_batch"){let successStr=typeof output.output==="string"?output.output:"",isPassed=!1;try{isPassed=JSON.parse(successStr).gates_passed===!0}catch(error49){log("[Guardrails] pre_check_batch JSON parse failed",{error:error49 instanceof Error?error49.message:String(error49)}),isPassed=!1}if(isPassed&&session.currentTaskId)try{advanceTaskState(session,session.currentTaskId,"pre_check_passed")}catch(err){warn("Failed to advance task state after pre_check_batch pass",{taskId:session.currentTaskId,error:String(err)})}}}let inputArgs=input.args??getStoredInputArgs(input.callID),delegation=isAgentDelegation(input.tool,inputArgs);if(delegation.isDelegation&&(delegation.targetAgent==="reviewer"||delegation.targetAgent==="test_engineer")){let currentPhase=1;try{let plan=await loadPlan(effectiveDirectory);if(plan){let phaseString=extractCurrentPhaseFromPlan(plan);currentPhase=extractPhaseNumber2(phaseString)}}catch(error49){log("[Guardrails] loadPlan failed during reviewer tracking",{error:error49 instanceof Error?error49.message:String(error49)})}let count=session.reviewerCallCount.get(currentPhase)??0;session.reviewerCallCount.set(currentPhase,count+1)}if(delegation.isDelegation&&delegation.targetAgent==="coder"&&session.lastCoderDelegationTaskId){if(session.currentTaskId=session.lastCoderDelegationTaskId,!session.revisionLimitHit){if(session.coderRevisions++,session.coderRevisions>1&&session.qaSkipCount===0){let conflictPhase=1;try{let plan=await loadPlan(effectiveDirectory);if(plan)conflictPhase=extractPhaseNumber2(extractCurrentPhaseFromPlan(plan))}catch{}resolveAgentConflict({sessionID:input.sessionID,phase:conflictPhase,taskId:session.currentTaskId??void 0,sourceAgent:"reviewer",targetAgent:"coder",conflictType:"feedback_rejection",rejectionCount:session.coderRevisions-1,summary:`Coder revision ${session.coderRevisions} for task ${session.currentTaskId??"unknown"}`}),session.lastDelegationReason="review_rejected"}let maxRevisions=cfg.max_coder_revisions??5;if(session.coderRevisions>=maxRevisions)session.revisionLimitHit=!0,telemetry.revisionLimitHit(input.sessionID,session.agentName),session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(`CODER REVISION LIMIT: Agent has been revised ${session.coderRevisions} times (max: ${maxRevisions}) for task ${session.currentTaskId??"unknown"}. Escalate to user or consider a fundamentally different approach.`),swarmState.pendingEvents++}if(session.partialGateWarningsIssuedForTask?.delete(session.currentTaskId),session.declaredCoderScope!==null){let undeclaredFiles=session.modifiedFilesThisCoderTask.map((f)=>f.replace(/[\r\n\t]/g,"_")).filter((f)=>!isInDeclaredScope3(f,session.declaredCoderScope,directory));if(undeclaredFiles.length>=1){let safeTaskId=String(session.currentTaskId??"").replace(/[\r\n\t]/g,"_");session.lastScopeViolation=`Scope violation for task ${safeTaskId}: ${undeclaredFiles.length} undeclared files modified: `+undeclaredFiles.join(", "),session.scopeViolationDetected=!0,telemetry.scopeViolation(input.sessionID,session.agentName,session.currentTaskId??"unknown","undeclared files modified")}}session.modifiedFilesThisCoderTask=[]}}let sessionId=input.sessionID,normalizedToolName=normalizeToolName(input.tool);if(isWriteTool2(normalizedToolName))toolCallsSinceLastWrite.set(sessionId,0),noOpWarningIssued.delete(sessionId);else{let count=(toolCallsSinceLastWrite.get(sessionId)??0)+1;toolCallsSinceLastWrite.set(sessionId,count);let threshold=cfg.no_op_warning_threshold??15;if(count>=threshold&&!noOpWarningIssued.has(sessionId)&&session?.pendingAdvisoryMessages)noOpWarningIssued.add(sessionId),session.pendingAdvisoryMessages.push(`WARNING: Agent has made ${count} tool calls with no file modifications. If you are stuck, use /swarm handoff to reset or /swarm turbo to reduce overhead.`)}let window2=getActiveWindow(input.sessionID);if(!window2)return;if(output.output===null||output.output===void 0){let outputStr=typeof output.output==="string"?output.output:"",errorContent=output.error??outputStr,errorSignal=extractErrorSignal(errorContent),extractedStatus=extractStatusCode2(errorSignal),isTransientStatusCode=extractedStatus!==null&&TRANSIENT_STATUS_CODES2.has(extractedStatus),isTransientPatternMatch=TRANSIENT_MODEL_ERROR_PATTERN2.test(errorSignal),isTransientMatch=isTransientStatusCode||isTransientPatternMatch,maxTransientRetries=cfg.max_transient_retries??5,isTransient=!!session&&isTransientMatch&&window2.transientRetryCount<maxTransientRetries,isDegraded=!isTransient&&DEGRADED_ERROR_PATTERN.test(errorSignal);if(isTransient)window2.transientRetryCount++;else if(isDegraded){let isContentFilter=CONTENT_FILTER_PATTERN.test(errorSignal);if(session&&!session.modelFallbackExhausted){session.model_fallback_index++;let swarmId=_internals22.extractSwarmIdFromAgentName(session.agentName),baseAgentName=session.agentName?session.agentName.replace(/^[^_]+[_]/,""):"",fallbackModels=_internals22.getSwarmAgents(swarmId)?.[baseAgentName]?.fallback_models;if(session.modelFallbackExhausted=!fallbackModels||session.model_fallback_index>fallbackModels.length,session.pendingAdvisoryMessages??=[],isContentFilter)session.pendingAdvisoryMessages.push(`DEGRADED: Content policy violation detected (content filter). Fallback model ${session.model_fallback_index}/${fallbackModels?.length??0} considered. The input may need content modification to comply with provider policies.`);else session.pendingAdvisoryMessages.push(`DEGRADED: Context-limit or token-limit error detected. Fallback model ${session.model_fallback_index}/${fallbackModels?.length??0} considered. Consider reducing input size or using /swarm handoff to switch models.`)}else if(session)if(session.pendingAdvisoryMessages??=[],isContentFilter)session.pendingAdvisoryMessages.push("DEGRADED: Content policy violation detected (content filter). No fallback models available. The input may need content modification to comply with provider policies.");else session.pendingAdvisoryMessages.push('DEGRADED: Context-limit or token-limit error detected. No fallback models available. Consider reducing input size or add "fallback_models" config.')}else window2.consecutiveErrors++;let modelFallbackAdvisoryEmitted=!1;if(session&&isTransientMatch&&!session.modelFallbackExhausted&&!isDegraded){session.model_fallback_index++;let swarmId=_internals22.extractSwarmIdFromAgentName(session.agentName),baseAgentName=session.agentName?session.agentName.replace(/^[^_]+[_]/,""):"",swarmAgents=_internals22.getSwarmAgents(swarmId),fallbackModels=swarmAgents?.[baseAgentName]?.fallback_models;session.modelFallbackExhausted=!fallbackModels||session.model_fallback_index>fallbackModels.length;let fallbackModel=_internals22.resolveFallbackModel(baseAgentName,session.model_fallback_index,swarmAgents),primaryModel=swarmAgents?.[baseAgentName]?.model??"default";if(fallbackModel){if(swarmAgents?.[baseAgentName])swarmAgents[baseAgentName].model=fallbackModel;session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(`MODEL FALLBACK: Applied fallback model "${fallbackModel}" (attempt ${session.model_fallback_index}). Using /swarm handoff to reset to primary model.`),modelFallbackAdvisoryEmitted=!0}else session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.push(`MODEL FALLBACK: Transient model error detected (attempt ${session.model_fallback_index}). No fallback models configured for this agent. Add "fallback_models": ["model-a", "model-b"] to the agent's config in opencode-swarm.json.`),modelFallbackAdvisoryEmitted=!0;telemetry.modelFallback(input.sessionID,session.agentName,primaryModel,fallbackModel??"none","transient_model_error"),swarmState.pendingEvents++}if(session&&isTransient&&isTransientMatch&&!modelFallbackAdvisoryEmitted){if(session.pendingAdvisoryMessages??=[],!session.pendingAdvisoryMessages.some((m)=>m.startsWith("TRANSIENT ERROR:")||m.startsWith("MODEL FALLBACK:")))session.pendingAdvisoryMessages.push(`TRANSIENT ERROR: Provider error detected (attempt ${window2.transientRetryCount}/${maxTransientRetries}). Retrying...`)}}else if(window2.consecutiveErrors=0,window2.transientRetryCount=0,window2.lastSuccessTimeMs=Date.now(),session){if(session.model_fallback_index>0)session.model_fallback_index=0,session.modelFallbackExhausted=!1}},messagesTransform}}var _internals22,SPEC_DRIFT_BLOCKED_TOOLS,TRANSIENT_STATUS_CODES2,TRANSIENT_MODEL_ERROR_PATTERN2,DEGRADED_ERROR_PATTERN,CONTENT_FILTER_PATTERN,toolCallsSinceLastWrite,noOpWarningIssued;var init_guardrails=__esm(()=>{init_agents2();init_constants();init_schema();init_manager();init_state2();init_telemetry();init_utils();init_logger();init_spec_hash();init_conflict_resolution();init_extractors();init_normalize_tool_name();init_destructive_command();init_file_authority();init_messages_transform();init_stored_input_args();init_tool_before();_internals22={extractSwarmIdFromAgentName,getSwarmAgents,getMostRecentAssistantText,getProviderFailureFingerprint,isTransientProviderFailureText,resolveFallbackModel,dcCheckJunctionCreation,extractErrorSignal},SPEC_DRIFT_BLOCKED_TOOLS=new Set(["save_plan","update_task_status","phase_complete","lean_turbo_run_phase","lean_turbo_acquire_locks"]);TRANSIENT_STATUS_CODES2=new Set([408,429,500,502,503,504,529]);TRANSIENT_MODEL_ERROR_PATTERN2=/rate.?limit|429|500|502|503|504|529|timeout|overloaded|model.?not.?found|temporarily.?unavailable|provider[_\s-]?unavailable|server.?error|network.?connection.?lost|connection.?(refused|reset|timeout|lost)|bad.?gateway|gateway.?timeout|internal.?server.?error|service.?unavailable|ECONNRESET|ECONNREFUSED|ETIMEDOUT|EPIPE|ENOTFOUND|broken.?pipe|dns(?:[\s_-]+(?:resolution)?)?[\s_-]+fail|name.?not.?resolved|EAI_AGAIN/i,DEGRADED_ERROR_PATTERN=/context.?length|token.?(limit|budget)|input.?too.?long|content.?filter|exceeds?.?(maximum.?)?tokens|maximum.?context|context.?window|too.?many.?tokens|prompt.?too.?long|message.?too.?long|request.?too.?large|max.?tokens/i,CONTENT_FILTER_PATTERN=/content.?filter/i,toolCallsSinceLastWrite=new Map,noOpWarningIssued=new Set});var init_guardrails2=__esm(()=>{init_file_authority();init_guardrails();init_stored_input_args()});var exports_task_envelope={};__export(exports_task_envelope,{parseTaskEnvelope:()=>parseTaskEnvelope,extractDispatchIds:()=>extractDispatchIds});function parseTaskEnvelope(text){if(typeof text!=="string"||text.length===0)return null;let match=text.match(TASK_ENVELOPE_RE);if(!match)return null;let sessionId=match[1],state=match[2];if(!sessionId)return null;let summary=extractTagText(text,"summary"),resultRaw=state==="error"?extractTagText(text,"task_error"):extractTagText(text,"task_result"),bounded=boundEnvelopeText(resultRaw);return{sessionId,state,...summary!==void 0?{summary}:{},...state==="error"&&bounded?{errorText:bounded.text,resultChars:bounded.chars,resultTruncated:bounded.truncated}:{},...state!=="error"&&bounded?{resultText:bounded.text,resultChars:bounded.chars,resultTruncated:bounded.truncated}:{}}}function extractTagText(text,tag){let re=new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`),match=text.match(re);if(!match)return;return match[1]}function boundEnvelopeText(text){if(text===void 0)return;if(text.length<=20000)return{text,chars:text.length,truncated:!1};let suffix=`
|
|
615
615
|
[... ${text.length-20000} chars truncated by task-envelope ...]`,maxContent=Math.max(0,20000-suffix.length);return{text:`${text.slice(0,maxContent)}${suffix}`,chars:text.length,truncated:!0}}function extractDispatchIds(output){let subagentSessionId=null,jobId=null;if(typeof output==="object"&&output!==null){let o=output,metadata=o.metadata;if(typeof metadata==="object"&&metadata!==null){let rawJobId=metadata.jobId;if(typeof rawJobId==="string"&&rawJobId.length>0)jobId=rawJobId}let rendered=o.output,envelope=parseTaskEnvelope(typeof rendered==="string"?rendered:void 0);if(envelope&&envelope.state==="running")subagentSessionId=envelope.sessionId}else if(typeof output==="string"){let envelope=parseTaskEnvelope(output);if(envelope&&envelope.state==="running")subagentSessionId=envelope.sessionId}if(!subagentSessionId&&jobId)subagentSessionId=jobId;return{subagentSessionId,jobId}}var TASK_ENVELOPE_RE;var init_task_envelope=__esm(()=>{TASK_ENVELOPE_RE=/<task\s+id="([^"]+)"\s+state="(running|completed|error)"\s*>/});var exports_pending_delegations={};__export(exports_pending_delegations,{sweepStaleDelegations:()=>sweepStaleDelegations,recordPendingDelegation:()=>recordPendingDelegation,readDelegations:()=>readDelegations,findOpenAsyncLaneBatches:()=>findOpenAsyncLaneBatches,findByCorrelationId:()=>findByCorrelationId,findByBatchId:()=>findByBatchId,buildPromptSnapshot:()=>buildPromptSnapshot,appendDelegationTransition:()=>appendDelegationTransition,BACKGROUND_DELEGATIONS_FILE:()=>BACKGROUND_DELEGATIONS_FILE});import{createHash as createHash8}from"node:crypto";import*as fs17 from"node:fs";import*as path38 from"node:path";function storePath(directory){return validateSwarmPath(directory,BACKGROUND_DELEGATIONS_FILE)}function ensureSwarmDir2(directory){fs17.mkdirSync(path38.resolve(directory,".swarm"),{recursive:!0})}function readDelegations(directory){let raw;try{raw=fs17.readFileSync(storePath(directory),"utf-8")}catch(err){if(err.code==="ENOENT")return[];return warn(`[background] readDelegations failed: ${err instanceof Error?err.message:String(err)}`),[]}let folded=new Map;for(let line of raw.split(`
|
|
616
616
|
`)){let trimmed=line.trim();if(trimmed.length===0)continue;let parsedJson;try{parsedJson=JSON.parse(trimmed)}catch{continue}let result=RecordSchema.safeParse(parsedJson);if(!result.success)continue;folded.set(result.data.correlationId,result.data)}return[...folded.values()]}function findByCorrelationId(directory,correlationId){if(!correlationId)return null;for(let record2 of readDelegations(directory))if(record2.correlationId===correlationId)return record2;return null}function appendRecord(directory,record2){ensureSwarmDir2(directory),fs17.appendFileSync(storePath(directory),`${JSON.stringify(record2)}
|
|
617
|
-
`,"utf-8")}async function recordPendingDelegation(directory,input,options={}){let now=Date.now(),record2={schemaVersion:input.batchId?2:1,correlationId:input.correlationId,jobId:input.jobId,subagentSessionId:input.subagentSessionId,parentSessionId:input.parentSessionId,callID:input.callID,normalizedAgent:input.normalizedAgent,swarmPrefixedAgent:input.swarmPrefixedAgent,planTaskId:input.planTaskId,evidenceTaskId:input.evidenceTaskId,status:"pending",createdAt:now,updatedAt:now,...input.batchId?{batchId:input.batchId}:{},...input.laneId?{laneId:input.laneId}:{},...input.mode?{mode:input.mode}:{},...input.promptHash?{promptHash:input.promptHash}:{},...input.workspace?{workspace:input.workspace}:{},...input.prompt?{prompt:input.prompt}:{},...input.generation!==void 0?{generation:input.generation}:{}};try{return await withEvidenceLock(directory,BACKGROUND_DELEGATIONS_FILE,STORE_LOCK_AGENT,STORE_LOCK_TASK,async()=>{if(options.staleTimeoutMs&&options.staleTimeoutMs>0)sweepStaleLocked(directory,options.staleTimeoutMs,now);appendRecord(directory,record2)}),record2}catch(err){return warn(`[background] recordPendingDelegation failed: ${err instanceof Error?err.message:String(err)}`),null}}function buildPromptSnapshot(text,maxChars){let boundedMax=Math.max(0,Math.min(maxChars,20000)),truncated=text.length>boundedMax;return{text:truncated?text.slice(0,boundedMax):text,chars:text.length,truncated,digest:createHash8("sha256").update(text).digest("hex")}}async function appendDelegationTransition(directory,correlationId,transition){let now=Date.now();try{let next=null;return await withEvidenceLock(directory,BACKGROUND_DELEGATIONS_FILE,STORE_LOCK_AGENT,STORE_LOCK_TASK,async()=>{let current=findByCorrelationId(directory,correlationId);if(!current)return;if(isTerminal(current.status)&&transition.status!=="consumed"&&transition.status!=="ingestion_error"){next=current;return}next={...current,schemaVersion:current.schemaVersion===1?2:current.schemaVersion,status:transition.status,updatedAt:now,...transition.completedAt!==void 0?{completedAt:transition.completedAt}:transition.status==="completed"||transition.status==="error"?{completedAt:now}:{},...transition.result?{result:transition.result}:{}},appendRecord(directory,next)}),next}catch(err){return warn(`[background] appendDelegationTransition failed: ${err instanceof Error?err.message:String(err)}`),null}}function findByBatchId(directory,batchId,opts){if(!batchId)return[];return readDelegations(directory).filter((record2)=>record2.batchId===batchId&&(opts?.parentSessionId===void 0||record2.parentSessionId===opts.parentSessionId))}function findOpenAsyncLaneBatches(directory){return readDelegations(directory).filter((record2)=>record2.batchId!==void 0&&(record2.status==="pending"||record2.status==="running"))}function isTerminal(status){return status==="completed"||status==="error"||status==="cancelled"||status==="stale"||status==="consumed"}function sweepStaleLocked(directory,timeoutMs,now){let swept=0;for(let record2 of readDelegations(directory)){if(record2.status!=="pending"&&record2.status!=="running"&&record2.status!=="ingestion_error")continue;if(now-record2.updatedAt<=timeoutMs)continue;appendRecord(directory,{...record2,status:"stale",updatedAt:now}),swept+=1}return swept}async function sweepStaleDelegations(directory,timeoutMs){if(!timeoutMs||timeoutMs<=0)return 0;try{return await withEvidenceLock(directory,BACKGROUND_DELEGATIONS_FILE,STORE_LOCK_AGENT,STORE_LOCK_TASK,async()=>sweepStaleLocked(directory,timeoutMs,Date.now()))}catch(err){return warn(`[background] sweepStaleDelegations failed: ${err instanceof Error?err.message:String(err)}`),0}}var BACKGROUND_DELEGATIONS_FILE="background-delegations.jsonl",STORE_LOCK_AGENT="background",STORE_LOCK_TASK="background-delegations",ResultSchema,WorkspaceSchema,PromptSchema,RecordSchema;var init_pending_delegations=__esm(()=>{init_zod();init_lock();init_utils2();init_logger();ResultSchema=exports_external.object({text:exports_external.string().optional(),error:exports_external.string().optional(),chars:exports_external.number(),truncated:exports_external.boolean(),digest:exports_external.string(),outputRef:exports_external.string().optional(),outputPreviewChars:exports_external.number().optional(),outputDegraded:exports_external.boolean().optional(),outputArtifactError:exports_external.string().optional(),transcriptIncomplete:exports_external.boolean().optional(),messageCount:exports_external.number().optional()}).strict(),WorkspaceSchema=exports_external.object({directory:exports_external.string(),gitHead:exports_external.string().nullable(),dirtyHash:exports_external.string().nullable(),prHeadSha:exports_external.string().nullable(),scope:exports_external.string().nullable()}).strict(),PromptSchema=exports_external.object({text:exports_external.string(),chars:exports_external.number(),truncated:exports_external.boolean(),digest:exports_external.string()}).strict(),RecordSchema=exports_external.object({schemaVersion:exports_external.union([exports_external.literal(1),exports_external.literal(2)]),correlationId:exports_external.string().min(1),jobId:exports_external.string().nullable(),subagentSessionId:exports_external.string().min(1),parentSessionId:exports_external.string().min(1),callID:exports_external.string(),normalizedAgent:exports_external.string(),swarmPrefixedAgent:exports_external.string(),planTaskId:exports_external.string().nullable(),evidenceTaskId:exports_external.string().nullable(),status:exports_external.enum(["pending","running","ingestion_error","completed","error","cancelled","stale","consumed"]),createdAt:exports_external.number(),updatedAt:exports_external.number(),batchId:exports_external.string().optional(),laneId:exports_external.string().optional(),mode:exports_external.string().optional(),promptHash:exports_external.string().optional(),workspace:WorkspaceSchema.optional(),prompt:PromptSchema.optional(),generation:exports_external.number().optional(),result:ResultSchema.optional(),completedAt:exports_external.number().optional()}).strict()});var exports_workspace_snapshot={};__export(exports_workspace_snapshot,{workspaceSnapshotMatches:()=>workspaceSnapshotMatches,digest:()=>digest,compareWorkspaceSnapshots:()=>compareWorkspaceSnapshots,compareWorkspaceSnapshot:()=>compareWorkspaceSnapshot,captureWorkspaceSnapshot:()=>captureWorkspaceSnapshot,_internals:()=>_internals23});import*as child_process2 from"node:child_process";import{createHash as createHash9}from"node:crypto";import*as path39 from"node:path";function runGit3(directory,args2){let result=_internals23.spawnSync("git",["-C",directory,...args2],{cwd:directory,encoding:"utf-8",timeout:GIT_SNAPSHOT_TIMEOUT_MS,maxBuffer:GIT_SNAPSHOT_MAX_BUFFER,stdio:["ignore","pipe","pipe"]});if(result.error||result.status!==0)return null;return typeof result.stdout==="string"?result.stdout.trimEnd():null}function captureWorkspaceSnapshot(directory,optionsOrScope=null,prHeadShaArg=null){let scope=typeof optionsOrScope==="object"&&optionsOrScope!==null?optionsOrScope.scope??null:optionsOrScope,prHeadSha=(()=>{if(typeof optionsOrScope!=="object"||optionsOrScope===null)return prHeadShaArg;if(optionsOrScope.resolveCurrentPrHeadSha)return runGit3(directory,["rev-parse","@{upstream}"]);return optionsOrScope.prHeadSha??null})(),gitHead=runGit3(directory,["rev-parse","HEAD"]),porcelain=runGit3(directory,["status","--porcelain=v1","--untracked-files=all"]);return{directory:path39.resolve(directory),gitHead,dirtyHash:porcelain===null?null:digest(porcelain),prHeadSha,scope}}function workspaceSnapshotMatches(expected,current){if(!expected)return{ok:!0};if(path39.resolve(expected.directory)!==path39.resolve(current.directory))return{ok:!1,reason:`directory changed: expected ${expected.directory}, got ${current.directory}`};let checks3=["gitHead","dirtyHash","prHeadSha"];for(let key of checks3){let expectedValue=expected[key];if(expectedValue===null)continue;if(current[key]!==expectedValue)return{ok:!1,reason:`${key} changed: expected ${expectedValue}, got ${current[key]??"unknown"}`}}return{ok:!0}}function compareWorkspaceSnapshots(expected,current){let result=workspaceSnapshotMatches(expected,current);if(result.ok)return{stale:!1};return{stale:!0,reason:result.reason}}function digest(text){return createHash9("sha256").update(text).digest("hex")}var GIT_SNAPSHOT_TIMEOUT_MS=3000,GIT_SNAPSHOT_MAX_BUFFER=524288,compareWorkspaceSnapshot,_internals23;var init_workspace_snapshot=__esm(()=>{compareWorkspaceSnapshot=workspaceSnapshotMatches;_internals23={spawnSync:child_process2.spawnSync}});import{renameSync as renameSync9,unlinkSync as unlinkSync7}from"node:fs";import*as path40 from"node:path";function taskEvidenceRelPath(taskId){return path40.join("evidence",`${taskId}.json`)}function taskEvidencePath(directory,taskId){return path40.join(directory,".swarm",taskEvidenceRelPath(taskId))}async function atomicWriteFile(targetPath,content){let tempPath=`${targetPath}.tmp.${Date.now()}.${Math.floor(Math.random()*1e9)}`;try{await bunWrite(tempPath,content),_internals24.renameSync(tempPath,targetPath)}finally{try{_internals24.unlinkSync(tempPath)}catch{}}}function withTaskEvidenceLock(directory,taskId,agent,fn2){return withEvidenceLock(directory,taskEvidenceRelPath(taskId),agent,taskId,fn2)}var _internals24;var init_task_file=__esm(()=>{init_bun_compat();init_lock();_internals24={renameSync:renameSync9,unlinkSync:unlinkSync7}});var exports_gate_evidence={};__export(exports_gate_evidence,{recordGateEvidence:()=>recordGateEvidence,recordAgentDispatch:()=>recordAgentDispatch,readTaskEvidenceRaw:()=>readTaskEvidenceRaw,readTaskEvidence:()=>readTaskEvidence,isValidTaskId:()=>isValidTaskId,hasPassedAllGates:()=>hasPassedAllGates,expandRequiredGates:()=>expandRequiredGates,deriveRequiredGates:()=>deriveRequiredGates,DEFAULT_REQUIRED_GATES:()=>DEFAULT_REQUIRED_GATES});import{mkdirSync as mkdirSync15,readFileSync as readFileSync12,realpathSync as realpathSync7}from"node:fs";import*as path41 from"node:path";function isValidTaskId(taskId){return isStrictTaskId(taskId)}function assertValidTaskId(taskId){assertStrictTaskId(taskId)}function deriveRequiredGates(agentType){switch(agentType){case"coder":return["reviewer","test_engineer"];case"docs":return["docs"];case"designer":return["designer","reviewer","test_engineer"];case"explorer":return["explorer"];case"sme":return["sme"];case"reviewer":return["reviewer"];case"test_engineer":return["test_engineer"];case"critic":return["critic"];case"critic_sounding_board":return["critic_sounding_board"];case"critic_drift_verifier":return["critic_drift_verifier"];case"critic_hallucination_verifier":return["critic_hallucination_verifier"];case"critic_architecture_supervisor":return["critic_architecture_supervisor"];default:return["reviewer","test_engineer"]}}function expandRequiredGates(existingGates,newAgentType){let newGates=deriveRequiredGates(newAgentType);return[...new Set([...existingGates??[],...newGates])].sort()}function getEvidenceDir(directory){let swarmDir=path41.resolve(directory,".swarm"),evidenceDir=path41.join(swarmDir,"evidence");mkdirSync15(evidenceDir,{recursive:!0});let resolvedSwarmDir,resolvedEvidenceDir;try{resolvedSwarmDir=path41.normalize(realpathSync7(swarmDir)),resolvedEvidenceDir=path41.normalize(realpathSync7(evidenceDir))}catch(error49){throw Error(`Unable to resolve evidence directory: ${error49.message}`)}let swarmPrefix=`${resolvedSwarmDir}${path41.sep}`;if(!(process.platform==="win32"?resolvedEvidenceDir.toLowerCase().startsWith(swarmPrefix.toLowerCase()):resolvedEvidenceDir.startsWith(swarmPrefix)))throw Error(`Evidence path escapes .swarm boundary: ${resolvedEvidenceDir}`);return resolvedEvidenceDir}function getEvidencePath(directory,taskId){return assertValidTaskId(taskId),taskEvidencePath(directory,taskId)}function readExisting(evidencePath,taskId){try{let raw=readFileSync12(evidencePath,"utf-8");return TaskEvidenceSchema.parse(JSON.parse(raw))}catch(error49){if(error49.code==="ENOENT")return null;throw telemetry.gateParseError(taskId,error49),error49}}async function recordGateEvidence(directory,taskId,gate,sessionId,turbo){assertValidTaskId(taskId),await withTaskEvidenceLock(directory,taskId,gate,async()=>{let resolvedEvidenceDir=getEvidenceDir(directory),evidencePath=path41.join(resolvedEvidenceDir,`${taskId}.json`),existing=null;try{existing=readExisting(evidencePath,taskId)}catch(error49){throw telemetry.gateParseError(taskId,error49),error49}let requiredGates=existing?expandRequiredGates(existing.required_gates,gate):deriveRequiredGates(gate),updated={taskId,required_gates:requiredGates,turbo:turbo===!0?!0:existing?.turbo,gates:{...existing?.gates??{},[gate]:{sessionId,timestamp:new Date().toISOString(),agent:gate}}};await atomicWriteFile(evidencePath,JSON.stringify(updated,null,2))}),telemetry.gatePassed(sessionId,gate,taskId)}async function recordAgentDispatch(directory,taskId,agentType,turbo){assertValidTaskId(taskId),await withTaskEvidenceLock(directory,taskId,agentType,async()=>{let resolvedEvidenceDir=getEvidenceDir(directory),evidencePath=path41.join(resolvedEvidenceDir,`${taskId}.json`),existing=null;try{existing=readExisting(evidencePath,taskId)}catch(error49){throw telemetry.gateParseError(taskId,error49),error49}let requiredGates=existing?expandRequiredGates(existing.required_gates,agentType):deriveRequiredGates(agentType),updated={taskId,required_gates:requiredGates,turbo:turbo===!0?!0:existing?.turbo,gates:existing?.gates??{}};await atomicWriteFile(evidencePath,JSON.stringify(updated,null,2))})}async function readTaskEvidence(directory,taskId){try{return assertValidTaskId(taskId),readExisting(getEvidencePath(directory,taskId),taskId)}catch{return null}}function readTaskEvidenceRaw(directory,taskId){assertValidTaskId(taskId);let evidencePath=getEvidencePath(directory,taskId);try{let raw=readFileSync12(evidencePath,"utf-8");return TaskEvidenceSchema.parse(JSON.parse(raw))}catch(error49){if(error49.code==="ENOENT")return null;throw error49}}async function hasPassedAllGates(directory,taskId){let evidence=await readTaskEvidence(directory,taskId);if(!evidence)return!1;if(!Array.isArray(evidence.required_gates)||evidence.required_gates.length===0)return!1;return evidence.required_gates.every((gate)=>evidence.gates[gate]!=null)}var GateEvidenceSchema,TaskEvidenceSchema,DEFAULT_REQUIRED_GATES;var init_gate_evidence=__esm(()=>{init_zod();init_task_file();init_telemetry();init_task_id();GateEvidenceSchema=exports_external.object({sessionId:exports_external.string(),timestamp:exports_external.string(),agent:exports_external.string()}).passthrough(),TaskEvidenceSchema=exports_external.object({taskId:exports_external.string(),required_gates:exports_external.array(exports_external.string()).default([]),gates:exports_external.record(exports_external.string(),GateEvidenceSchema),turbo:exports_external.boolean().optional()}),DEFAULT_REQUIRED_GATES=["reviewer","test_engineer"]});import*as fs18 from"node:fs";import*as path42 from"node:path";function clearPendingCoderScope(){pendingCoderScopeByTaskId.clear()}function isBackgroundTrue(value){return value===!0||value==="true"}function outputLooksLikeBackgroundRunning(output){if(typeof output!=="object"||output===null)return!1;let o=output;if(o.state==="running")return!0;let metadata=o.metadata;return typeof metadata==="object"&&metadata!==null&&metadata.background===!0}function extractTaskLine(text){let match=text.match(/TASK:\s*(.+?)(?:\n|$)/i);return match?match[1].trim():null}function extractPlanTaskId(text){let taskListMatch=text.match(/^[ \t]*-[ \t]*(?:\[[ x]\][ \t]+)?(\d+\.\d+(?:\.\d+)*)[:. ]/m);if(taskListMatch)return taskListMatch[1];let taskLineMatch=text.match(/TASK:\s*(?:.+?\s)?(\d+\.\d+(?:\.\d+)*)(?:\s|$|:)/i);if(taskLineMatch)return taskLineMatch[1];return null}function getSeedTaskId(session){return session.currentTaskId??session.lastCoderDelegationTaskId}function isTaskCompletedForParallelGuidance(task){let status=task.status??"pending";return status==="completed"||status==="closed"}function getPlanTaskStatus(plan,taskId){for(let phase of plan.phases){let task=phase.tasks.find((candidate)=>candidate.id===taskId);if(task)return task.status??"pending"}return null}function resolveDelegatedPlanTaskId(args2,knownPlanTaskIds){let rawTaskId=args2.task_id??args2.taskId;if(typeof rawTaskId==="string"){let trimmed=rawTaskId.trim();if(trimmed.length<=20&&isStrictTaskId(trimmed))return trimmed;return null}let candidateTextFields=[args2.prompt,args2.description,args2.task,args2.input],taskLineMatches=new Set;for(let field of candidateTextFields){if(typeof field!=="string")continue;let taskLine=extractTaskLine(field);if(!taskLine)continue;for(let m of taskLine.matchAll(/\b(\d+\.\d+(?:\.\d+)*)\b/g)){let candidate=m[1];if(!isStrictTaskId(candidate))continue;if(knownPlanTaskIds&&!knownPlanTaskIds.has(candidate))continue;taskLineMatches.add(candidate)}}if(taskLineMatches.size===1)return taskLineMatches.values().next().value;if(taskLineMatches.size>1)return null;let seen=new Set;for(let field of candidateTextFields){if(typeof field!=="string")continue;for(let m of field.matchAll(/\b(\d+\.\d+(?:\.\d+)*)\b/g)){let candidate=m[1];if(isStrictTaskId(candidate)){if(knownPlanTaskIds&&!knownPlanTaskIds.has(candidate))continue;seen.add(candidate)}}}if(seen.size===1)return seen.values().next().value;return null}async function findTaskAwaitingCompletion(directory,session,requestedTaskId){if(!directory)return null;let plan=null;try{plan=await loadPlanJsonOnly(directory)}catch{return null}if(!plan)return null;for(let[taskId,state]of session.taskWorkflowStates){if(state!=="tests_run")continue;if(requestedTaskId&&requestedTaskId===taskId)continue;let planStatus=getPlanTaskStatus(plan,taskId);if(!planStatus)continue;if(planStatus==="completed"||planStatus==="closed")continue;return taskId}return null}function completionGateViolationMessage(taskAwaitingCompletion){return`TASK_COMPLETION_GATE_VIOLATION: Task ${taskAwaitingCompletion} reached tests_run but is not marked completed in plan.json/plan.md. Call update_task_status with task_id="${taskAwaitingCompletion}" and status="completed" before starting another task.`}async function buildParallelExecutionGuidance(directory,sessionID,session){if(!directory)return null;let plan=await loadPlanJsonOnly(directory);if(!plan)return null;let profile=plan.execution_profile,enabled=profile?.parallelization_enabled===!0,maxConcurrent=profile?.max_concurrent_tasks??10,effectiveMaxConcurrent=session?.maxConcurrencyOverride??maxConcurrent,allTasks=plan.phases.flatMap((phase)=>phase.tasks),blockedTasks=allTasks.filter((task)=>{if(task.status!=="blocked")return!1;let reason=(task.blocked_reason??"").toLowerCase();return reason.includes("fail")||reason.includes("error")||reason.includes("exception")}),totalTasks=allTasks.length,backoffTriggered=!1;if(totalTasks>0&&blockedTasks.length>0){let failureRate=blockedTasks.length/totalTasks,FAILURE_RATE_THRESHOLD=0.2,BACKOFF_MULTIPLIER=0.5;if(failureRate>0.2&&blockedTasks.length>=2){let newConcurrency=Math.max(1,Math.floor(effectiveMaxConcurrent*0.5));if(newConcurrency<effectiveMaxConcurrent)effectiveMaxConcurrent=newConcurrency,session.maxConcurrencyOverride=newConcurrency,backoffTriggered=!0}}if(!enabled||effectiveMaxConcurrent<=1)return null;if(hasActiveLeanTurbo(sessionID))return"[NEXT] Lean Turbo is active; use lean_turbo_run_phase and Lean Turbo lane guidance instead of standard execution-profile slot filling.";let currentPhase=plan.current_phase!==void 0?plan.phases.find((phase)=>phase.id===plan.current_phase):plan.phases.find((phase)=>!isParallelGuidancePhaseComplete(phase));if(!currentPhase)return null;let tasks=currentPhase.tasks;if(tasks.length===0)return null;let completed=new Set;for(let task of allTasks){let taskId=task.id;if(isTaskCompletedForParallelGuidance(task))completed.add(taskId);if(getTaskState(session,taskId)==="complete")completed.add(taskId)}let occupied=new Set;for(let task of allTasks){let taskId=task.id;if(task.status==="in_progress")occupied.add(taskId);let state=getTaskState(session,taskId);if(ACTIVE_PARALLEL_TASK_STATES.has(state))occupied.add(taskId)}let availableSlots=Math.max(0,effectiveMaxConcurrent-occupied.size);if(availableSlots<=0)return`[PARALLEL EXECUTION PROFILE] parallelization_enabled=true max_concurrent_tasks=${effectiveMaxConcurrent}; all standard execution slots are occupied. Continue current active task gates before starting more coder work.`;let eligible=tasks.filter((task)=>{let taskId=task.id;if((task.status??"pending")!=="pending")return!1;if(occupied.has(taskId))return!1;return task.depends.every((dep)=>completed.has(dep))}).map((task)=>task.id).slice(0,availableSlots);if(eligible.length===0)return`[PARALLEL EXECUTION PROFILE] parallelization_enabled=true max_concurrent_tasks=${effectiveMaxConcurrent}; no dependency-ready pending tasks are available for a new coder slot. Continue the current task/gate.`;let failureWarning=backoffTriggered?` (${blockedTasks.length} blocked task(s) detected — concurrency auto-reduced due to failures)`:"";return`[PARALLEL EXECUTION PROFILE] parallelization_enabled=true max_concurrent_tasks=${effectiveMaxConcurrent}; ${occupied.size} slot(s) occupied. Eligible now: ${eligible.join(", ")}. [NEXT] dispatch up to ${availableSlots} eligible coder task(s) before waiting; preserve ONE task per coder call and call declare_scope for each task.${failureWarning}`}function isParallelGuidancePhaseComplete(phase){return phase.status==="complete"||phase.status==="completed"||phase.status==="closed"}async function getEvidenceTaskId(session,directory){let resolvedPlanPath,primary=session.currentTaskId??session.lastCoderDelegationTaskId;if(primary)return primary;if(session.taskWorkflowStates&&session.taskWorkflowStates.size>0)return session.taskWorkflowStates.keys().next().value??null;try{if(typeof directory!=="string"||directory.length===0)return null;let resolvedDirectory=path42.resolve(directory),planPath=path42.join(resolvedDirectory,".swarm","plan.json");if(resolvedPlanPath=path42.resolve(planPath),!resolvedPlanPath.startsWith(resolvedDirectory+path42.sep)&&resolvedPlanPath!==resolvedDirectory)return null;let planContent=await fs18.promises.readFile(resolvedPlanPath,"utf-8"),plan=EvidenceTaskIdPlanSchema.parse(JSON.parse(planContent));if(!plan||!Array.isArray(plan.phases))return null;for(let phase of plan.phases)if(Array.isArray(phase.tasks)){for(let task of phase.tasks)if(task.status==="in_progress")return task.id??null}}catch(err){if(err instanceof ZodError){let issueSummary=err.issues.slice(0,3).map((issue2)=>issue2.message).join("; ");return warn(`[delegation-gate] getEvidenceTaskId ignored invalid plan schema at ${resolvedPlanPath??"unknown path"}: ${issueSummary}`),null}if(process.env.DEBUG_SWARM&&err instanceof Error)warn(`[delegation-gate] getEvidenceTaskId error: ${err.message} (code=${err.code??"none"})`);return null}return null}async function resolveEvidenceTaskId(args2,session,directory){let rawTaskId=args2?.task_id;if(typeof rawTaskId==="string"&&rawTaskId.length<=20&&isStrictTaskId(rawTaskId.trim()))return rawTaskId.trim();if(args2)try{let plan=await loadPlanJsonOnly(directory);if(plan){let planTaskIds=new Set(plan.phases.flatMap((p)=>p.tasks.map((t)=>t.id))),promptTaskId=resolveDelegatedPlanTaskId(args2,planTaskIds);if(promptTaskId)return promptTaskId}}catch{}return getEvidenceTaskId(session,directory)}function createDelegationGateHook(config2,directory){initDurableStatusPath(directory);let enabled=config2.hooks?.delegation_gate!==!1,delegationMaxChars=config2.hooks?.delegation_max_chars??4000,backgroundSubagentsEnabled=config2.hooks?.background_subagents===!0,backgroundPendingTimeoutMs=(config2.hooks?.background_pending_timeout_minutes??30)*60000;if(!enabled)return{messagesTransform:async(_input,_output)=>{},toolBefore:async()=>{},toolAfter:async()=>{}};return{toolBefore:async(input,output)=>{if(!input.sessionID)return;let normalized=normalizeToolName(input.tool),completionArgs=output.args;if(completionArgs){let completionPlanTaskIds;try{let plan2=await loadPlanJsonOnly(directory);if(plan2)completionPlanTaskIds=new Set(plan2.phases.flatMap((p)=>p.tasks.map((t)=>t.id)))}catch{}let requestedTaskId=resolveDelegatedPlanTaskId(completionArgs,completionPlanTaskIds),completionSession=ensureAgentSession(input.sessionID),taskAwaitingCompletion=await findTaskAwaitingCompletion(directory,completionSession,requestedTaskId);if(taskAwaitingCompletion){let allowingSameTaskRetry=requestedTaskId===taskAwaitingCompletion,requestedTaskIsAwaitingCompletion=requestedTaskId&&completionSession.taskWorkflowStates.get(requestedTaskId)==="tests_run",allowCompletionUpdate=normalized==="update_task_status"&&completionArgs.status==="completed"&&requestedTaskIsAwaitingCompletion;if(!allowingSameTaskRetry&&!allowCompletionUpdate)throw Error(completionGateViolationMessage(taskAwaitingCompletion))}}if(normalized!=="Task"&&normalized!=="task")return;let args2=output.args;if(!args2)return;let subagentType=args2.subagent_type;if(typeof subagentType!=="string")return;let targetAgent=stripKnownSwarmPrefix(subagentType);if(!backgroundSubagentsEnabled&&isBackgroundTrue(args2.background)&&isKnownCanonicalRole(targetAgent))throw Error(SWARM_BACKGROUND_TASK_BLOCKED_MESSAGE);if(targetAgent==="reviewer")try{let reviewSession=swarmState.agentSessions.get(input.sessionID);if(reviewSession){let changedFiles=reviewSession.modifiedFilesThisCoderTask??[];if(changedFiles.length>0){let routing=await routeReviewForChanges(directory,changedFiles);if(shouldParallelizeReview(routing))reviewSession.pendingAdvisoryMessages??=[],reviewSession.pendingAdvisoryMessages.push(`REVIEW ROUTING: High complexity detected (${routing.reason}). Consider parallel review: ${routing.reviewerCount} reviewers, ${routing.testEngineerCount} test engineers recommended.`)}}}catch{}if(targetAgent!=="coder")return;let session=ensureAgentSession(input.sessionID);if(!session||!session.taskWorkflowStates)return;let plan=await _internals25.loadPlanJsonOnly(directory),profile=plan?.execution_profile,parallelEnabled=profile?.parallelization_enabled===!0,maxConcurrent=profile?.max_concurrent_tasks??10,effectiveMaxConcurrent=session.maxConcurrencyOverride??maxConcurrent,parallelModeActive=parallelEnabled&&effectiveMaxConcurrent>1&&!hasActiveLeanTurbo(input.sessionID),planTaskIds=plan?new Set(plan.phases.flatMap((phase)=>phase.tasks.map((t)=>t.id))):new Set,incomingCoderTaskId=resolveDelegatedPlanTaskId(args2,planTaskIds);for(let[taskId,state]of session.taskWorkflowStates){if(state!=="coder_delegated")continue;let freshnessThreshold=session.sessionRehydratedAt>0?session.sessionRehydratedAt:session.lastPhaseCompleteTimestamp??0;if(!(swarmState.delegationChains.get(input.sessionID)??[]).some((d)=>stripKnownSwarmPrefix(d.to)==="coder"&&d.timestamp>freshnessThreshold)){session.taskWorkflowStates.set(taskId,"idle"),warn(`[delegation-gate] Reset stale coder_delegated state for task ${taskId} — `+"no coder delegation found in current session.");continue}if(hasActiveTurboMode(input.sessionID)){if(!taskId.startsWith("3."))continue}if(parallelModeActive&&incomingCoderTaskId&&taskId!==incomingCoderTaskId)continue;throw Error(`REVIEWER_GATE_VIOLATION: Cannot re-delegate to coder without reviewer delegation. Task ${taskId} state: coder_delegated. Delegate to reviewer first. If this is stale state from a prior session, run /swarm reset-session to clear workflow state.`)}if(parallelModeActive){let coderDelegatedCount=0;for(let s of session.taskWorkflowStates.values())if(s==="coder_delegated")coderDelegatedCount++;if(coderDelegatedCount>=effectiveMaxConcurrent)throw Error(`PARALLEL_SLOTS_EXHAUSTED: ${coderDelegatedCount} coder task(s) are awaiting review (max_concurrent_tasks=${effectiveMaxConcurrent}). Dispatch reviewer/test_engineer for an in-flight coder task before starting another coder.`)}if(standardWorktreeSerializationSessions.has(input.sessionID))throw Error("STANDARD_WORKTREE_ISOLATION_SERIALIZED: prior standard worktree isolation setup failed in this session; wait for the active coder task to finish before dispatching another coder.");if(!plan)return;if(!parallelModeActive)return;let resolvedTaskId=incomingCoderTaskId;await precreateStandardWorktreeSession({config:config2,directory,parentSessionID:input.sessionID,callID:input.callID,taskId:resolvedTaskId??sanitizeWorktreeTaskId(input.callID),planTaskId:resolvedTaskId??void 0,description:typeof args2.description==="string"?args2.description:void 0,outputArgs:args2})},messagesTransform:async(_input,output)=>{let messages=output.messages;if(!messages||messages.length===0)return;let lastUserMessageIndex=-1;for(let i=messages.length-1;i>=0;i--)if(messages[i]?.info?.role==="user"){lastUserMessageIndex=i;break}if(lastUserMessageIndex===-1)return;let lastUserMessage=messages[lastUserMessageIndex];if(!lastUserMessage?.parts)return;let agent=lastUserMessage.info?.agent;if(agent==="")return;let strippedAgent=agent?stripKnownSwarmPrefix(agent):void 0;if(strippedAgent&&strippedAgent!=="architect")return;let textPartIndex=lastUserMessage.parts.findIndex((p)=>p?.type==="text"&&p.text!==void 0);if(textPartIndex===-1)return;let textPart=lastUserMessage.parts[textPartIndex],text=textPart.text??"",taskDisclosureSessionID=lastUserMessage.info?.sessionID;if(taskDisclosureSessionID){let currentTaskIdForWindow=ensureAgentSession(taskDisclosureSessionID).currentTaskId;if(currentTaskIdForWindow){let taskLineRegex=/^[ \t]*-[ \t]*(?:\[[ x]\][ \t]+)?(\d+\.\d+(?:\.\d+)*)[:. ].*/gm,taskLines=[];taskLineRegex.lastIndex=0;let regexMatch=taskLineRegex.exec(text);while(regexMatch!==null)taskLines.push({line:regexMatch[0],taskId:regexMatch[1],index:regexMatch.index}),regexMatch=taskLineRegex.exec(text);if(taskLines.length>5){let currentIdx=taskLines.findIndex((t)=>t.taskId===currentTaskIdForWindow),windowStart=Math.max(0,currentIdx-2),windowEnd=Math.min(taskLines.length-1,currentIdx+3),visibleTasks=taskLines.slice(windowStart,windowEnd+1),hiddenBefore=windowStart,hiddenAfter=taskLines.length-1-windowEnd,totalTasks=taskLines.length,visibleCount=visibleTasks.length,firstTaskIndex=taskLines[0].index,lastTask=taskLines[taskLines.length-1],lastTaskEnd=lastTask.index+lastTask.line.length,before=text.slice(0,firstTaskIndex),after=text.slice(lastTaskEnd),visibleLines=visibleTasks.map((t)=>t.line).join(`
|
|
617
|
+
`,"utf-8")}async function recordPendingDelegation(directory,input,options={}){let now=Date.now(),record2={schemaVersion:input.batchId?2:1,correlationId:input.correlationId,jobId:input.jobId,subagentSessionId:input.subagentSessionId,parentSessionId:input.parentSessionId,callID:input.callID,normalizedAgent:input.normalizedAgent,swarmPrefixedAgent:input.swarmPrefixedAgent,planTaskId:input.planTaskId,evidenceTaskId:input.evidenceTaskId,status:"pending",createdAt:now,updatedAt:now,...input.batchId?{batchId:input.batchId}:{},...input.laneId?{laneId:input.laneId}:{},...input.mode?{mode:input.mode}:{},...input.promptHash?{promptHash:input.promptHash}:{},...input.workspace?{workspace:input.workspace}:{},...input.prompt?{prompt:input.prompt}:{},...input.generation!==void 0?{generation:input.generation}:{}};try{return await withEvidenceLock(directory,BACKGROUND_DELEGATIONS_FILE,STORE_LOCK_AGENT,STORE_LOCK_TASK,async()=>{if(options.staleTimeoutMs&&options.staleTimeoutMs>0)sweepStaleLocked(directory,options.staleTimeoutMs,now);appendRecord(directory,record2)}),record2}catch(err){return warn(`[background] recordPendingDelegation failed: ${err instanceof Error?err.message:String(err)}`),null}}function buildPromptSnapshot(text,maxChars){let boundedMax=Math.max(0,Math.min(maxChars,20000)),truncated=text.length>boundedMax;return{text:truncated?text.slice(0,boundedMax):text,chars:text.length,truncated,digest:createHash8("sha256").update(text).digest("hex")}}async function appendDelegationTransition(directory,correlationId,transition){let now=Date.now();try{let next=null;return await withEvidenceLock(directory,BACKGROUND_DELEGATIONS_FILE,STORE_LOCK_AGENT,STORE_LOCK_TASK,async()=>{let current=findByCorrelationId(directory,correlationId);if(!current)return;if(isTerminal(current.status)&&transition.status!=="consumed"&&transition.status!=="ingestion_error"){next=current;return}next={...current,schemaVersion:current.schemaVersion===1?2:current.schemaVersion,status:transition.status,updatedAt:now,...transition.completedAt!==void 0?{completedAt:transition.completedAt}:transition.status==="completed"||transition.status==="error"?{completedAt:now}:{},...transition.result?{result:transition.result}:{}},appendRecord(directory,next)}),next}catch(err){return warn(`[background] appendDelegationTransition failed: ${err instanceof Error?err.message:String(err)}`),null}}function findByBatchId(directory,batchId,opts){if(!batchId)return[];return readDelegations(directory).filter((record2)=>record2.batchId===batchId&&(opts?.parentSessionId===void 0||record2.parentSessionId===opts.parentSessionId))}function findOpenAsyncLaneBatches(directory){return readDelegations(directory).filter((record2)=>record2.batchId!==void 0&&(record2.status==="pending"||record2.status==="running"))}function isTerminal(status){return status==="completed"||status==="error"||status==="cancelled"||status==="stale"||status==="consumed"}function sweepStaleLocked(directory,timeoutMs,now){let swept=0;for(let record2 of readDelegations(directory)){if(record2.status!=="pending"&&record2.status!=="running"&&record2.status!=="ingestion_error")continue;if(now-record2.updatedAt<=timeoutMs)continue;appendRecord(directory,{...record2,status:"stale",updatedAt:now}),swept+=1}return swept}async function sweepStaleDelegations(directory,timeoutMs){if(!timeoutMs||timeoutMs<=0)return 0;try{return await withEvidenceLock(directory,BACKGROUND_DELEGATIONS_FILE,STORE_LOCK_AGENT,STORE_LOCK_TASK,async()=>sweepStaleLocked(directory,timeoutMs,Date.now()))}catch(err){return warn(`[background] sweepStaleDelegations failed: ${err instanceof Error?err.message:String(err)}`),0}}var BACKGROUND_DELEGATIONS_FILE="background-delegations.jsonl",STORE_LOCK_AGENT="background",STORE_LOCK_TASK="background-delegations",ResultSchema,WorkspaceSchema,PromptSchema,RecordSchema;var init_pending_delegations=__esm(()=>{init_zod();init_lock();init_utils2();init_logger();ResultSchema=exports_external.object({text:exports_external.string().optional(),error:exports_external.string().optional(),chars:exports_external.number(),truncated:exports_external.boolean(),digest:exports_external.string(),outputRef:exports_external.string().optional(),outputPreviewChars:exports_external.number().optional(),outputDegraded:exports_external.boolean().optional(),outputArtifactError:exports_external.string().optional(),transcriptIncomplete:exports_external.boolean().optional(),messageCount:exports_external.number().optional()}).strict(),WorkspaceSchema=exports_external.object({directory:exports_external.string(),gitHead:exports_external.string().nullable(),dirtyHash:exports_external.string().nullable(),prHeadSha:exports_external.string().nullable(),scope:exports_external.string().nullable()}).strict(),PromptSchema=exports_external.object({text:exports_external.string(),chars:exports_external.number(),truncated:exports_external.boolean(),digest:exports_external.string()}).strict(),RecordSchema=exports_external.object({schemaVersion:exports_external.union([exports_external.literal(1),exports_external.literal(2)]),correlationId:exports_external.string().min(1),jobId:exports_external.string().nullable(),subagentSessionId:exports_external.string().min(1),parentSessionId:exports_external.string().min(1),callID:exports_external.string(),normalizedAgent:exports_external.string(),swarmPrefixedAgent:exports_external.string(),planTaskId:exports_external.string().nullable(),evidenceTaskId:exports_external.string().nullable(),status:exports_external.enum(["pending","running","ingestion_error","completed","error","cancelled","stale","consumed"]),createdAt:exports_external.number(),updatedAt:exports_external.number(),batchId:exports_external.string().optional(),laneId:exports_external.string().optional(),mode:exports_external.string().optional(),promptHash:exports_external.string().optional(),workspace:WorkspaceSchema.optional(),prompt:PromptSchema.optional(),generation:exports_external.number().optional(),result:ResultSchema.optional(),completedAt:exports_external.number().optional()}).strict()});var exports_workspace_snapshot={};__export(exports_workspace_snapshot,{workspaceSnapshotMatches:()=>workspaceSnapshotMatches,digest:()=>digest,compareWorkspaceSnapshots:()=>compareWorkspaceSnapshots,compareWorkspaceSnapshot:()=>compareWorkspaceSnapshot,captureWorkspaceSnapshot:()=>captureWorkspaceSnapshot,_internals:()=>_internals23});import*as child_process2 from"node:child_process";import{createHash as createHash9}from"node:crypto";import*as path39 from"node:path";function runGit3(directory,args2){let result=_internals23.spawnSync("git",["-C",directory,...args2],{cwd:directory,encoding:"utf-8",timeout:GIT_SNAPSHOT_TIMEOUT_MS,maxBuffer:GIT_SNAPSHOT_MAX_BUFFER,stdio:["ignore","pipe","pipe"]});if(result.error||result.status!==0)return null;return typeof result.stdout==="string"?result.stdout.trimEnd():null}function captureWorkspaceSnapshot(directory,optionsOrScope=null,prHeadShaArg=null){let scope=typeof optionsOrScope==="object"&&optionsOrScope!==null?optionsOrScope.scope??null:optionsOrScope,prHeadSha=(()=>{if(typeof optionsOrScope!=="object"||optionsOrScope===null)return prHeadShaArg;if(optionsOrScope.resolveCurrentPrHeadSha)return runGit3(directory,["rev-parse","@{upstream}"]);return optionsOrScope.prHeadSha??null})(),gitHead=runGit3(directory,["rev-parse","HEAD"]),porcelain=runGit3(directory,["status","--porcelain=v1","--untracked-files=all"]);return{directory:path39.resolve(directory),gitHead,dirtyHash:porcelain===null?null:digest(porcelain),prHeadSha,scope}}function workspaceSnapshotMatches(expected,current){if(!expected)return{ok:!0};if(path39.resolve(expected.directory)!==path39.resolve(current.directory))return{ok:!1,reason:`directory changed: expected ${expected.directory}, got ${current.directory}`};let checks3=["gitHead","dirtyHash","prHeadSha"];for(let key of checks3){let expectedValue=expected[key];if(expectedValue===null)continue;if(current[key]!==expectedValue)return{ok:!1,reason:`${key} changed: expected ${expectedValue}, got ${current[key]??"unknown"}`}}return{ok:!0}}function compareWorkspaceSnapshots(expected,current){let result=workspaceSnapshotMatches(expected,current);if(result.ok)return{stale:!1};return{stale:!0,reason:result.reason}}function digest(text){return createHash9("sha256").update(text).digest("hex")}var GIT_SNAPSHOT_TIMEOUT_MS=3000,GIT_SNAPSHOT_MAX_BUFFER=524288,compareWorkspaceSnapshot,_internals23;var init_workspace_snapshot=__esm(()=>{compareWorkspaceSnapshot=workspaceSnapshotMatches;_internals23={spawnSync:child_process2.spawnSync}});import{renameSync as renameSync9,unlinkSync as unlinkSync7}from"node:fs";import*as path40 from"node:path";function taskEvidenceRelPath(taskId){return path40.join("evidence",`${taskId}.json`)}function taskEvidencePath(directory,taskId){return path40.join(directory,".swarm",taskEvidenceRelPath(taskId))}async function atomicWriteFile(targetPath,content){let tempPath=`${targetPath}.tmp.${Date.now()}.${Math.floor(Math.random()*1e9)}`;try{await bunWrite(tempPath,content),_internals24.renameSync(tempPath,targetPath)}finally{try{_internals24.unlinkSync(tempPath)}catch{}}}function withTaskEvidenceLock(directory,taskId,agent,fn2){return withEvidenceLock(directory,taskEvidenceRelPath(taskId),agent,taskId,fn2)}var _internals24;var init_task_file=__esm(()=>{init_bun_compat();init_lock();_internals24={renameSync:renameSync9,unlinkSync:unlinkSync7}});var exports_gate_evidence={};__export(exports_gate_evidence,{recordGateEvidence:()=>recordGateEvidence,recordAgentDispatch:()=>recordAgentDispatch,readTaskEvidenceRaw:()=>readTaskEvidenceRaw,readTaskEvidence:()=>readTaskEvidence,isValidTaskId:()=>isValidTaskId,hasPassedAllGates:()=>hasPassedAllGates,expandRequiredGates:()=>expandRequiredGates,deriveRequiredGates:()=>deriveRequiredGates,DEFAULT_REQUIRED_GATES:()=>DEFAULT_REQUIRED_GATES});import{mkdirSync as mkdirSync15,readFileSync as readFileSync12,realpathSync as realpathSync8}from"node:fs";import*as path41 from"node:path";function isValidTaskId(taskId){return isStrictTaskId(taskId)}function assertValidTaskId(taskId){assertStrictTaskId(taskId)}function deriveRequiredGates(agentType){switch(agentType){case"coder":return["reviewer","test_engineer"];case"docs":return["docs"];case"designer":return["designer","reviewer","test_engineer"];case"explorer":return["explorer"];case"sme":return["sme"];case"reviewer":return["reviewer"];case"test_engineer":return["test_engineer"];case"critic":return["critic"];case"critic_sounding_board":return["critic_sounding_board"];case"critic_drift_verifier":return["critic_drift_verifier"];case"critic_hallucination_verifier":return["critic_hallucination_verifier"];case"critic_architecture_supervisor":return["critic_architecture_supervisor"];default:return["reviewer","test_engineer"]}}function expandRequiredGates(existingGates,newAgentType){let newGates=deriveRequiredGates(newAgentType);return[...new Set([...existingGates??[],...newGates])].sort()}function getEvidenceDir(directory){let swarmDir=path41.resolve(directory,".swarm"),evidenceDir=path41.join(swarmDir,"evidence");mkdirSync15(evidenceDir,{recursive:!0});let resolvedSwarmDir,resolvedEvidenceDir;try{resolvedSwarmDir=path41.normalize(realpathSync8(swarmDir)),resolvedEvidenceDir=path41.normalize(realpathSync8(evidenceDir))}catch(error49){throw Error(`Unable to resolve evidence directory: ${error49.message}`)}let swarmPrefix=`${resolvedSwarmDir}${path41.sep}`;if(!(process.platform==="win32"?resolvedEvidenceDir.toLowerCase().startsWith(swarmPrefix.toLowerCase()):resolvedEvidenceDir.startsWith(swarmPrefix)))throw Error(`Evidence path escapes .swarm boundary: ${resolvedEvidenceDir}`);return resolvedEvidenceDir}function getEvidencePath(directory,taskId){return assertValidTaskId(taskId),taskEvidencePath(directory,taskId)}function readExisting(evidencePath,taskId){try{let raw=readFileSync12(evidencePath,"utf-8");return TaskEvidenceSchema.parse(JSON.parse(raw))}catch(error49){if(error49.code==="ENOENT")return null;throw telemetry.gateParseError(taskId,error49),error49}}async function recordGateEvidence(directory,taskId,gate,sessionId,turbo){assertValidTaskId(taskId),await withTaskEvidenceLock(directory,taskId,gate,async()=>{let resolvedEvidenceDir=getEvidenceDir(directory),evidencePath=path41.join(resolvedEvidenceDir,`${taskId}.json`),existing=null;try{existing=readExisting(evidencePath,taskId)}catch(error49){throw telemetry.gateParseError(taskId,error49),error49}let requiredGates=existing?expandRequiredGates(existing.required_gates,gate):deriveRequiredGates(gate),updated={taskId,required_gates:requiredGates,turbo:turbo===!0?!0:existing?.turbo,gates:{...existing?.gates??{},[gate]:{sessionId,timestamp:new Date().toISOString(),agent:gate}}};await atomicWriteFile(evidencePath,JSON.stringify(updated,null,2))}),telemetry.gatePassed(sessionId,gate,taskId)}async function recordAgentDispatch(directory,taskId,agentType,turbo){assertValidTaskId(taskId),await withTaskEvidenceLock(directory,taskId,agentType,async()=>{let resolvedEvidenceDir=getEvidenceDir(directory),evidencePath=path41.join(resolvedEvidenceDir,`${taskId}.json`),existing=null;try{existing=readExisting(evidencePath,taskId)}catch(error49){throw telemetry.gateParseError(taskId,error49),error49}let requiredGates=existing?expandRequiredGates(existing.required_gates,agentType):deriveRequiredGates(agentType),updated={taskId,required_gates:requiredGates,turbo:turbo===!0?!0:existing?.turbo,gates:existing?.gates??{}};await atomicWriteFile(evidencePath,JSON.stringify(updated,null,2))})}async function readTaskEvidence(directory,taskId){try{return assertValidTaskId(taskId),readExisting(getEvidencePath(directory,taskId),taskId)}catch{return null}}function readTaskEvidenceRaw(directory,taskId){assertValidTaskId(taskId);let evidencePath=getEvidencePath(directory,taskId);try{let raw=readFileSync12(evidencePath,"utf-8");return TaskEvidenceSchema.parse(JSON.parse(raw))}catch(error49){let code=error49.code;if(code==="ENOENT"||code==="ENAMETOOLONG")return null;throw error49}}async function hasPassedAllGates(directory,taskId){let evidence=await readTaskEvidence(directory,taskId);if(!evidence)return!1;if(!Array.isArray(evidence.required_gates)||evidence.required_gates.length===0)return!1;return evidence.required_gates.every((gate)=>evidence.gates[gate]!=null)}var GateEvidenceSchema,TaskEvidenceSchema,DEFAULT_REQUIRED_GATES;var init_gate_evidence=__esm(()=>{init_zod();init_task_file();init_telemetry();init_task_id();GateEvidenceSchema=exports_external.object({sessionId:exports_external.string(),timestamp:exports_external.string(),agent:exports_external.string()}).passthrough(),TaskEvidenceSchema=exports_external.object({taskId:exports_external.string(),required_gates:exports_external.array(exports_external.string()).default([]),gates:exports_external.record(exports_external.string(),GateEvidenceSchema),turbo:exports_external.boolean().optional()}),DEFAULT_REQUIRED_GATES=["reviewer","test_engineer"]});import*as fs18 from"node:fs";import*as path42 from"node:path";function clearPendingCoderScope(){pendingCoderScopeByTaskId.clear()}function isBackgroundTrue(value){return value===!0||value==="true"}function outputLooksLikeBackgroundRunning(output){if(typeof output!=="object"||output===null)return!1;let o=output;if(o.state==="running")return!0;let metadata=o.metadata;return typeof metadata==="object"&&metadata!==null&&metadata.background===!0}function extractTaskLine(text){let match=text.match(/TASK:\s*(.+?)(?:\n|$)/i);return match?match[1].trim():null}function extractPlanTaskId(text){let taskListMatch=text.match(/^[ \t]*-[ \t]*(?:\[[ x]\][ \t]+)?(\d+\.\d+(?:\.\d+)*)[:. ]/m);if(taskListMatch)return taskListMatch[1];let taskLineMatch=text.match(/TASK:\s*(?:.+?\s)?(\d+\.\d+(?:\.\d+)*)(?:\s|$|:)/i);if(taskLineMatch)return taskLineMatch[1];return null}function getSeedTaskId(session){return session.currentTaskId??session.lastCoderDelegationTaskId}function isTaskCompletedForParallelGuidance(task){let status=task.status??"pending";return status==="completed"||status==="closed"}function getPlanTaskStatus(plan,taskId){for(let phase of plan.phases){let task=phase.tasks.find((candidate)=>candidate.id===taskId);if(task)return task.status??"pending"}return null}function resolveDelegatedPlanTaskId(args2,knownPlanTaskIds){let rawTaskId=args2.task_id??args2.taskId;if(typeof rawTaskId==="string"){let trimmed=rawTaskId.trim();if(trimmed.length<=20&&isStrictTaskId(trimmed))return trimmed;return null}let candidateTextFields=[args2.prompt,args2.description,args2.task,args2.input],taskLineMatches=new Set;for(let field of candidateTextFields){if(typeof field!=="string")continue;let taskLine=extractTaskLine(field);if(!taskLine)continue;for(let m of taskLine.matchAll(/\b(\d+\.\d+(?:\.\d+)*)\b/g)){let candidate=m[1];if(!isStrictTaskId(candidate))continue;if(knownPlanTaskIds&&!knownPlanTaskIds.has(candidate))continue;taskLineMatches.add(candidate)}}if(taskLineMatches.size===1)return taskLineMatches.values().next().value;if(taskLineMatches.size>1)return null;let seen=new Set;for(let field of candidateTextFields){if(typeof field!=="string")continue;for(let m of field.matchAll(/\b(\d+\.\d+(?:\.\d+)*)\b/g)){let candidate=m[1];if(isStrictTaskId(candidate)){if(knownPlanTaskIds&&!knownPlanTaskIds.has(candidate))continue;seen.add(candidate)}}}if(seen.size===1)return seen.values().next().value;return null}async function findTaskAwaitingCompletion(directory,session,requestedTaskId){if(!directory)return null;let plan=null;try{plan=await loadPlanJsonOnly(directory)}catch{return null}if(!plan)return null;for(let[taskId,state]of session.taskWorkflowStates){if(state!=="tests_run")continue;if(requestedTaskId&&requestedTaskId===taskId)continue;let planStatus=getPlanTaskStatus(plan,taskId);if(!planStatus)continue;if(planStatus==="completed"||planStatus==="closed")continue;return taskId}return null}function completionGateViolationMessage(taskAwaitingCompletion){return`TASK_COMPLETION_GATE_VIOLATION: Task ${taskAwaitingCompletion} reached tests_run but is not marked completed in plan.json/plan.md. Call update_task_status with task_id="${taskAwaitingCompletion}" and status="completed" before starting another task.`}async function buildParallelExecutionGuidance(directory,sessionID,session){if(!directory)return null;let plan=await loadPlanJsonOnly(directory);if(!plan)return null;let profile=plan.execution_profile,enabled=profile?.parallelization_enabled===!0,maxConcurrent=profile?.max_concurrent_tasks??10,effectiveMaxConcurrent=session?.maxConcurrencyOverride??maxConcurrent,allTasks=plan.phases.flatMap((phase)=>phase.tasks),blockedTasks=allTasks.filter((task)=>{if(task.status!=="blocked")return!1;let reason=(task.blocked_reason??"").toLowerCase();return reason.includes("fail")||reason.includes("error")||reason.includes("exception")}),totalTasks=allTasks.length,backoffTriggered=!1;if(totalTasks>0&&blockedTasks.length>0){let failureRate=blockedTasks.length/totalTasks,FAILURE_RATE_THRESHOLD=0.2,BACKOFF_MULTIPLIER=0.5;if(failureRate>0.2&&blockedTasks.length>=2){let newConcurrency=Math.max(1,Math.floor(effectiveMaxConcurrent*0.5));if(newConcurrency<effectiveMaxConcurrent)effectiveMaxConcurrent=newConcurrency,session.maxConcurrencyOverride=newConcurrency,backoffTriggered=!0}}if(!enabled||effectiveMaxConcurrent<=1)return null;if(hasActiveLeanTurbo(sessionID))return"[NEXT] Lean Turbo is active; use lean_turbo_run_phase and Lean Turbo lane guidance instead of standard execution-profile slot filling.";let currentPhase=plan.current_phase!==void 0?plan.phases.find((phase)=>phase.id===plan.current_phase):plan.phases.find((phase)=>!isParallelGuidancePhaseComplete(phase));if(!currentPhase)return null;let tasks=currentPhase.tasks;if(tasks.length===0)return null;let completed=new Set;for(let task of allTasks){let taskId=task.id;if(isTaskCompletedForParallelGuidance(task))completed.add(taskId);if(getTaskState(session,taskId)==="complete")completed.add(taskId)}let occupied=new Set;for(let task of allTasks){let taskId=task.id;if(task.status==="in_progress")occupied.add(taskId);let state=getTaskState(session,taskId);if(ACTIVE_PARALLEL_TASK_STATES.has(state))occupied.add(taskId)}let availableSlots=Math.max(0,effectiveMaxConcurrent-occupied.size);if(availableSlots<=0)return`[PARALLEL EXECUTION PROFILE] parallelization_enabled=true max_concurrent_tasks=${effectiveMaxConcurrent}; all standard execution slots are occupied. Continue current active task gates before starting more coder work.`;let eligible=tasks.filter((task)=>{let taskId=task.id;if((task.status??"pending")!=="pending")return!1;if(occupied.has(taskId))return!1;return task.depends.every((dep)=>completed.has(dep))}).map((task)=>task.id).slice(0,availableSlots);if(eligible.length===0)return`[PARALLEL EXECUTION PROFILE] parallelization_enabled=true max_concurrent_tasks=${effectiveMaxConcurrent}; no dependency-ready pending tasks are available for a new coder slot. Continue the current task/gate.`;let failureWarning=backoffTriggered?` (${blockedTasks.length} blocked task(s) detected — concurrency auto-reduced due to failures)`:"";return`[PARALLEL EXECUTION PROFILE] parallelization_enabled=true max_concurrent_tasks=${effectiveMaxConcurrent}; ${occupied.size} slot(s) occupied. Eligible now: ${eligible.join(", ")}. [NEXT] dispatch up to ${availableSlots} eligible coder task(s) before waiting; preserve ONE task per coder call and call declare_scope for each task.${failureWarning}`}function isParallelGuidancePhaseComplete(phase){return phase.status==="complete"||phase.status==="completed"||phase.status==="closed"}async function getEvidenceTaskId(session,directory){let resolvedPlanPath,primary=session.currentTaskId??session.lastCoderDelegationTaskId;if(primary)return primary;if(session.taskWorkflowStates&&session.taskWorkflowStates.size>0)return session.taskWorkflowStates.keys().next().value??null;try{if(typeof directory!=="string"||directory.length===0)return null;let resolvedDirectory=path42.resolve(directory),planPath=path42.join(resolvedDirectory,".swarm","plan.json");if(resolvedPlanPath=path42.resolve(planPath),!resolvedPlanPath.startsWith(resolvedDirectory+path42.sep)&&resolvedPlanPath!==resolvedDirectory)return null;let planContent=await fs18.promises.readFile(resolvedPlanPath,"utf-8"),plan=EvidenceTaskIdPlanSchema.parse(JSON.parse(planContent));if(!plan||!Array.isArray(plan.phases))return null;for(let phase of plan.phases)if(Array.isArray(phase.tasks)){for(let task of phase.tasks)if(task.status==="in_progress")return task.id??null}}catch(err){if(err instanceof ZodError){let issueSummary=err.issues.slice(0,3).map((issue2)=>issue2.message).join("; ");return warn(`[delegation-gate] getEvidenceTaskId ignored invalid plan schema at ${resolvedPlanPath??"unknown path"}: ${issueSummary}`),null}if(process.env.DEBUG_SWARM&&err instanceof Error)warn(`[delegation-gate] getEvidenceTaskId error: ${err.message} (code=${err.code??"none"})`);return null}return null}async function resolveEvidenceTaskId(args2,session,directory){let rawTaskId=args2?.task_id;if(typeof rawTaskId==="string"&&rawTaskId.length<=20&&isStrictTaskId(rawTaskId.trim()))return rawTaskId.trim();if(args2)try{let plan=await loadPlanJsonOnly(directory);if(plan){let planTaskIds=new Set(plan.phases.flatMap((p)=>p.tasks.map((t)=>t.id))),promptTaskId=resolveDelegatedPlanTaskId(args2,planTaskIds);if(promptTaskId)return promptTaskId}}catch{}return getEvidenceTaskId(session,directory)}function createDelegationGateHook(config2,directory){initDurableStatusPath(directory);let enabled=config2.hooks?.delegation_gate!==!1,delegationMaxChars=config2.hooks?.delegation_max_chars??4000,backgroundSubagentsEnabled=config2.hooks?.background_subagents===!0,backgroundPendingTimeoutMs=(config2.hooks?.background_pending_timeout_minutes??30)*60000;if(!enabled)return{messagesTransform:async(_input,_output)=>{},toolBefore:async()=>{},toolAfter:async()=>{}};return{toolBefore:async(input,output)=>{if(!input.sessionID)return;let normalized=normalizeToolName(input.tool),completionArgs=output.args;if(completionArgs){let completionPlanTaskIds;try{let plan2=await loadPlanJsonOnly(directory);if(plan2)completionPlanTaskIds=new Set(plan2.phases.flatMap((p)=>p.tasks.map((t)=>t.id)))}catch{}let requestedTaskId=resolveDelegatedPlanTaskId(completionArgs,completionPlanTaskIds),completionSession=ensureAgentSession(input.sessionID),taskAwaitingCompletion=await findTaskAwaitingCompletion(directory,completionSession,requestedTaskId);if(taskAwaitingCompletion){let allowingSameTaskRetry=requestedTaskId===taskAwaitingCompletion,requestedTaskIsAwaitingCompletion=requestedTaskId&&completionSession.taskWorkflowStates.get(requestedTaskId)==="tests_run",allowCompletionUpdate=normalized==="update_task_status"&&completionArgs.status==="completed"&&requestedTaskIsAwaitingCompletion;if(!allowingSameTaskRetry&&!allowCompletionUpdate)throw Error(completionGateViolationMessage(taskAwaitingCompletion))}}if(normalized!=="Task"&&normalized!=="task")return;let args2=output.args;if(!args2)return;let subagentType=args2.subagent_type;if(typeof subagentType!=="string")return;let targetAgent=stripKnownSwarmPrefix(subagentType);if(!backgroundSubagentsEnabled&&isBackgroundTrue(args2.background)&&isKnownCanonicalRole(targetAgent))throw Error(SWARM_BACKGROUND_TASK_BLOCKED_MESSAGE);if(targetAgent==="reviewer")try{let reviewSession=swarmState.agentSessions.get(input.sessionID);if(reviewSession){let changedFiles=reviewSession.modifiedFilesThisCoderTask??[];if(changedFiles.length>0){let routing=await routeReviewForChanges(directory,changedFiles);if(shouldParallelizeReview(routing))reviewSession.pendingAdvisoryMessages??=[],reviewSession.pendingAdvisoryMessages.push(`REVIEW ROUTING: High complexity detected (${routing.reason}). Consider parallel review: ${routing.reviewerCount} reviewers, ${routing.testEngineerCount} test engineers recommended.`)}}}catch{}if(targetAgent!=="coder")return;let session=ensureAgentSession(input.sessionID);if(!session||!session.taskWorkflowStates)return;let plan=await _internals25.loadPlanJsonOnly(directory),profile=plan?.execution_profile,parallelEnabled=profile?.parallelization_enabled===!0,maxConcurrent=profile?.max_concurrent_tasks??10,effectiveMaxConcurrent=session.maxConcurrencyOverride??maxConcurrent,parallelModeActive=parallelEnabled&&effectiveMaxConcurrent>1&&!hasActiveLeanTurbo(input.sessionID),planTaskIds=plan?new Set(plan.phases.flatMap((phase)=>phase.tasks.map((t)=>t.id))):new Set,incomingCoderTaskId=resolveDelegatedPlanTaskId(args2,planTaskIds);for(let[taskId,state]of session.taskWorkflowStates){if(state!=="coder_delegated")continue;let freshnessThreshold=session.sessionRehydratedAt>0?session.sessionRehydratedAt:session.lastPhaseCompleteTimestamp??0;if(!(swarmState.delegationChains.get(input.sessionID)??[]).some((d)=>stripKnownSwarmPrefix(d.to)==="coder"&&d.timestamp>freshnessThreshold)){session.taskWorkflowStates.set(taskId,"idle"),warn(`[delegation-gate] Reset stale coder_delegated state for task ${taskId} — `+"no coder delegation found in current session.");continue}if(hasActiveTurboMode(input.sessionID)){if(!taskId.startsWith("3."))continue}if(parallelModeActive&&incomingCoderTaskId&&taskId!==incomingCoderTaskId)continue;throw Error(`REVIEWER_GATE_VIOLATION: Cannot re-delegate to coder without reviewer delegation. Task ${taskId} state: coder_delegated. Delegate to reviewer first. If this is stale state from a prior session, run /swarm reset-session to clear workflow state.`)}if(parallelModeActive){let coderDelegatedCount=0;for(let s of session.taskWorkflowStates.values())if(s==="coder_delegated")coderDelegatedCount++;if(coderDelegatedCount>=effectiveMaxConcurrent)throw Error(`PARALLEL_SLOTS_EXHAUSTED: ${coderDelegatedCount} coder task(s) are awaiting review (max_concurrent_tasks=${effectiveMaxConcurrent}). Dispatch reviewer/test_engineer for an in-flight coder task before starting another coder.`)}if(standardWorktreeSerializationSessions.has(input.sessionID))throw Error("STANDARD_WORKTREE_ISOLATION_SERIALIZED: prior standard worktree isolation setup failed in this session; wait for the active coder task to finish before dispatching another coder.");if(!plan)return;if(!parallelModeActive)return;let resolvedTaskId=incomingCoderTaskId;await precreateStandardWorktreeSession({config:config2,directory,parentSessionID:input.sessionID,callID:input.callID,taskId:resolvedTaskId??sanitizeWorktreeTaskId(input.callID),planTaskId:resolvedTaskId??void 0,description:typeof args2.description==="string"?args2.description:void 0,outputArgs:args2})},messagesTransform:async(_input,output)=>{let messages=output.messages;if(!messages||messages.length===0)return;let lastUserMessageIndex=-1;for(let i=messages.length-1;i>=0;i--)if(messages[i]?.info?.role==="user"){lastUserMessageIndex=i;break}if(lastUserMessageIndex===-1)return;let lastUserMessage=messages[lastUserMessageIndex];if(!lastUserMessage?.parts)return;let agent=lastUserMessage.info?.agent;if(agent==="")return;let strippedAgent=agent?stripKnownSwarmPrefix(agent):void 0;if(strippedAgent&&strippedAgent!=="architect")return;let textPartIndex=lastUserMessage.parts.findIndex((p)=>p?.type==="text"&&p.text!==void 0);if(textPartIndex===-1)return;let textPart=lastUserMessage.parts[textPartIndex],text=textPart.text??"",taskDisclosureSessionID=lastUserMessage.info?.sessionID;if(taskDisclosureSessionID){let currentTaskIdForWindow=ensureAgentSession(taskDisclosureSessionID).currentTaskId;if(currentTaskIdForWindow){let taskLineRegex=/^[ \t]*-[ \t]*(?:\[[ x]\][ \t]+)?(\d+\.\d+(?:\.\d+)*)[:. ].*/gm,taskLines=[];taskLineRegex.lastIndex=0;let regexMatch=taskLineRegex.exec(text);while(regexMatch!==null)taskLines.push({line:regexMatch[0],taskId:regexMatch[1],index:regexMatch.index}),regexMatch=taskLineRegex.exec(text);if(taskLines.length>5){let currentIdx=taskLines.findIndex((t)=>t.taskId===currentTaskIdForWindow),windowStart=Math.max(0,currentIdx-2),windowEnd=Math.min(taskLines.length-1,currentIdx+3),visibleTasks=taskLines.slice(windowStart,windowEnd+1),hiddenBefore=windowStart,hiddenAfter=taskLines.length-1-windowEnd,totalTasks=taskLines.length,visibleCount=visibleTasks.length,firstTaskIndex=taskLines[0].index,lastTask=taskLines[taskLines.length-1],lastTaskEnd=lastTask.index+lastTask.line.length,before=text.slice(0,firstTaskIndex),after=text.slice(lastTaskEnd),visibleLines=visibleTasks.map((t)=>t.line).join(`
|
|
618
618
|
`),trimComment=`[Task window: showing ${visibleCount} of ${totalTasks} tasks]`,trimmedMiddle=(hiddenBefore>0?`[...${hiddenBefore} tasks hidden...]
|
|
619
619
|
`:"")+visibleLines+(hiddenAfter>0?`
|
|
620
620
|
[...${hiddenAfter} tasks hidden...]`:"");textPart.text=`${before}${trimmedMiddle}
|
|
@@ -5267,7 +5267,7 @@ ${phaseNumber!==null&&phaseNumber>=4?`
|
|
|
5267
5267
|
|
|
5268
5268
|
---
|
|
5269
5269
|
|
|
5270
|
-
${originalText}`})}}init_constants();import*as path147 from"node:path";init_profiles();import*as fsSync9 from"node:fs";import{existsSync as existsSync80,realpathSync as
|
|
5270
|
+
${originalText}`})}}init_constants();import*as path147 from"node:path";init_profiles();import*as fsSync9 from"node:fs";import{existsSync as existsSync80,realpathSync as realpathSync16}from"node:fs";import*as fsPromises5 from"node:fs/promises";import*as os21 from"node:os";import*as path142 from"node:path";var PUBLIC_INFO={exported:!0,visibility:"public",exportedReason:"top_level_public",apiSurfaceKind:"public"},PRIVATE_INFO={exported:!1,visibility:"private",exportedReason:"unknown",apiSurfaceKind:"private"};function collectCommonJsExports(source){let sanitized=maskCommentsAndStrings(source),exportsByLocal=new Map,add2=(localName,exportedName,sourceIndex)=>{if(!isIdentifier(localName)||!isIdentifier(exportedName))return;let existing=exportsByLocal.get(localName);if(existing&&existing.sourceIndex<=sourceIndex)return;exportsByLocal.set(localName,{localName,exportedName,exportedReason:"explicit_export",sourceIndex})};for(let match of sanitized.matchAll(/\bmodule\s*\.\s*exports\s*=\s*([A-Za-z_$][\w$]*)\b/g))add2(match[1],match[1],match.index??0);for(let match of sanitized.matchAll(/\bmodule\s*\.\s*exports\s*=\s*\{([^}]*)\}/g)){let body=match[1],baseIndex=match.index??0;for(let part of body.split(",")){let entry=part.trim();if(!entry)continue;let alias=entry.match(/^([A-Za-z_$][\w$]*)\s*:\s*([A-Za-z_$][\w$]*)$/);if(alias){add2(alias[2],alias[1],baseIndex+match[0].indexOf(part));continue}let shorthand=entry.match(/^([A-Za-z_$][\w$]*)$/);if(shorthand)add2(shorthand[1],shorthand[1],baseIndex+match[0].indexOf(part))}}for(let match of sanitized.matchAll(/\b(?:module\s*\.\s*exports|exports)\s*\.\s*([A-Za-z_$][\w$]*)\s*=\s*([A-Za-z_$][\w$]*)\b/g))add2(match[2],match[1],match.index??0);return exportsByLocal}function collectPythonAllNames(source){let match=source.match(/__all__\s*=\s*([[({])([\s\S]*?)[\])}]/);if(!match)return null;let body=match[2].trim();if(!body)return new Set;let names=new Set;for(let part of body.split(",")){let trimmed=part.trim();if(!trimmed)continue;let stringMatch=trimmed.match(/^['"]([^'"]+)['"]$/);if(!stringMatch)return null;names.add(stringMatch[1])}return names}function getSymbolVisibilityInfo(ctx){if(hasPrivateContainer(ctx.defNode))return{...PRIVATE_INFO};if(ctx.explicitExported||ctx.commonJsExport)return{exported:!0,visibility:"public",exportedReason:"explicit_export",apiSurfaceKind:"export"};let ownVisibility=visibilityFromText(ctx.grammarId,ctx.defNode.text);if(ctx.kind==="method"){if(ctx.grammarId==="go")return isUppercasePublic(ctx.localName)?{...PUBLIC_INFO,exportedReason:"naming_convention"}:{...PRIVATE_INFO};if(ctx.grammarId==="python"&&ctx.pythonParentClassExported){let isPrivate=ctx.localName.startsWith("_"),isInit=ctx.localName==="__init__";if(isPrivate||isInit)return{...PRIVATE_INFO};return{exported:!0,visibility:"public",exportedReason:"modifier",apiSurfaceKind:"public"}}return{exported:!1,visibility:ownVisibility,exportedReason:ownVisibility==="unknown"?"unknown":"modifier",apiSurfaceKind:ownVisibility==="private"?"private":"public"}}if(!ctx.isTopLevel&&isMemberLikeNode(ctx.defNode))return{exported:!1,visibility:ownVisibility==="unknown"?"public":ownVisibility,exportedReason:ownVisibility==="unknown"?"module_public":"modifier",apiSurfaceKind:ownVisibility==="private"?"private":"public"};if(!ctx.isTopLevel)return{...PRIVATE_INFO};switch(ctx.grammarId){case"typescript":case"javascript":case"tsx":return{...PRIVATE_INFO};case"python":return pythonVisibility(ctx);case"rust":return rustVisibility(ctx);case"go":return isUppercasePublic(ctx.localName)?{...PUBLIC_INFO,exportedReason:"naming_convention"}:{...PRIVATE_INFO};case"java":case"kotlin":case"csharp":case"swift":case"php":return modifierLanguageVisibility(ctx);case"cpp":return cppVisibility(ctx);case"dart":return ctx.localName.startsWith("_")?{...PRIVATE_INFO}:{...PUBLIC_INFO,exportedReason:"naming_convention"};case"ruby":return ctx.localName.startsWith("_")?{...PRIVATE_INFO}:{...PUBLIC_INFO,exportedReason:"module_public"};default:return{exported:!1,visibility:"unknown",exportedReason:"unknown",apiSurfaceKind:"unknown"}}}function pythonVisibility(ctx){if(ctx.pythonAllNames)return ctx.pythonAllNames.has(ctx.localName)?{exported:!0,visibility:"public",exportedReason:"module_public",apiSurfaceKind:"public"}:{...PRIVATE_INFO};return ctx.localName.startsWith("_")?{...PRIVATE_INFO}:{...PUBLIC_INFO,exportedReason:"naming_convention"}}function rustVisibility(ctx){let text=ctx.defNode.text.trimStart();if(!/^pub\b|^pub\s*\(/.test(text))return{...PRIVATE_INFO};return{exported:!0,visibility:/^pub\s*\(\s*(crate|super|in\b)/.test(text)?"internal":"public",exportedReason:"modifier",apiSurfaceKind:"public"}}function modifierLanguageVisibility(ctx){if(ctx.grammarId==="php"&&ctx.localName.startsWith("_"))return{...PRIVATE_INFO};let visibility=visibilityFromText(ctx.grammarId,ctx.defNode.text);if(visibility==="private")return{...PRIVATE_INFO};if(visibility==="unknown")return{exported:!0,visibility:ctx.grammarId==="java"?"package":defaultModuleVisibility(ctx.grammarId),exportedReason:"module_public",apiSurfaceKind:"public"};return{exported:!0,visibility,exportedReason:"modifier",apiSurfaceKind:"public"}}function cppVisibility(ctx){let text=ctx.defNode.text.trimStart();if(/^static\b/.test(text)||ctx.localName.startsWith("_"))return{...PRIVATE_INFO};return{exported:!0,visibility:"public",exportedReason:"namespace_public",apiSurfaceKind:"public"}}function visibilityFromText(grammarId,text){let normalized=declarationPrefix(text).trimStart();if(/\b(private|fileprivate)\b/.test(normalized))return"private";if(/\bprotected\b/.test(normalized))return"protected";if(/\binternal\b/.test(normalized))return"internal";if(/\b(public|open)\b/.test(normalized))return"public";if(grammarId==="rust"&&/^pub\s*\(\s*(crate|super|in\b)/.test(normalized))return"internal";if(grammarId==="rust"&&/^pub\b|^pub\s*\(/.test(normalized))return"public";return"unknown"}function declarationPrefix(text){let bodyStart=text.search(/[{\n]/);return bodyStart===-1?text:text.slice(0,bodyStart)}function defaultModuleVisibility(grammarId){switch(grammarId){case"kotlin":case"swift":case"csharp":return"internal";case"php":return"public";default:return"public"}}function hasPrivateContainer(node){let current=node.parent;while(current){if(isContainerNode(current)&&visibilityFromText("",current.text)==="private")return!0;current=current.parent}return!1}function isContainerNode(node){return/(?:class|struct|interface|object|protocol|namespace|module)/.test(node.type)}function isMemberLikeNode(node){return/(?:method|function)_declaration|function_definition/.test(node.type)}function isUppercasePublic(name){return/^[A-Z]/.test(name)}function isIdentifier(value){return/^[A-Za-z_$][\w$]*$/.test(value)}function maskCommentsAndStrings(source){let chars=[...source],i=0;while(i<chars.length){let ch=chars[i],next=chars[i+1];if(ch==="/"&&next==="/"){chars[i++]=" ",chars[i++]=" ";while(i<chars.length&&chars[i]!==`
|
|
5271
5271
|
`)chars[i++]=" ";continue}if(ch==="/"&&next==="*"){chars[i++]=" ",chars[i++]=" ";while(i<chars.length){let end=chars[i]==="*"&&chars[i+1]==="/";if(chars[i++]=" ",end){chars[i++]=" ";break}}continue}if(ch==='"'||ch==="'"||ch==="`"){let quote=ch;chars[i++]=" ";while(i<chars.length){if(chars[i]==="\\"){if(chars[i++]=" ",i<chars.length)chars[i++]=" ";continue}let done=chars[i]===quote;if(chars[i++]=" ",done)break}continue}i++}return chars.join("")}var _QueryCtor=null,AST_TIMEOUT_MS=500,QUERIES={typescript:{defs:`
|
|
5272
5272
|
(function_declaration name: (identifier) @func.name) @func.def
|
|
5273
5273
|
(generator_function_declaration name: (identifier) @func.name) @func.def
|
|
@@ -5470,7 +5470,7 @@ ${originalText}`})}}init_constants();import*as path147 from"node:path";init_prof
|
|
|
5470
5470
|
`),implDepth=0,braceDelta=(text)=>(text.match(/{/g)?.length??0)-(text.match(/}/g)?.length??0);for(let i=0;i<lines.length;i++){let line=lines[i],trimmed=line.trim(),inImpl=implDepth>0;if(!inImpl&&/^impl\b/.test(trimmed)){implDepth=Math.max(0,implDepth+braceDelta(trimmed));continue}if(inImpl){let method=trimmed.match(/^(pub(?:\s*\([^)]*\))?\s+)?(?:async\s+)?fn\s+([A-Za-z_][A-Za-z0-9_]*)/);if(method){let modifier2=method[1]??"";symbols.push({name:method[2],kind:"method",exported:modifier2.trim().startsWith("pub"),signature:trimmed.substring(0,100),line:i+1})}implDepth=Math.max(0,implDepth+braceDelta(trimmed));continue}if(/^\s/.test(line))continue;let item=trimmed.match(/^(pub(?:\s*\([^)]*\))?\s+)?(?:async\s+)?(fn|struct|enum|trait|mod)\s+([A-Za-z_][A-Za-z0-9_]*)/);if(!item)continue;let exported=(item[1]??"").trim().startsWith("pub"),kindMap={fn:"function",struct:"type",enum:"enum",trait:"interface",mod:"type"};symbols.push({name:item[3],kind:kindMap[item[2]]??"type",exported,signature:trimmed.substring(0,100),line:i+1})}return symbols.sort((a,b)=>{if(a.line!==b.line)return a.line-b.line;return a.name.localeCompare(b.name)})}function extractGoSymbols(filePath,cwd){let content=readValidatedSourceFile(filePath,cwd);if(content===null)return[];let symbols=[],lines=content.split(`
|
|
5471
5471
|
`);for(let i=0;i<lines.length;i++){let line=lines[i],method=line.match(/^func\s+\([^)]*\)\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(/);if(method){symbols.push({name:method[1],kind:"method",exported:/^[A-Z]/.test(method[1]),signature:line.trim().substring(0,100),line:i+1});continue}let fn2=line.match(/^func\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(/);if(fn2){symbols.push({name:fn2[1],kind:"function",exported:/^[A-Z]/.test(fn2[1]),signature:line.trim().substring(0,100),line:i+1});continue}let typeDecl=line.match(/^type\s+([A-Za-z_][A-Za-z0-9_]*)\b/);if(typeDecl){symbols.push({name:typeDecl[1],kind:"type",exported:/^[A-Z]/.test(typeDecl[1]),signature:line.trim().substring(0,100),line:i+1});continue}let valueDecl=line.match(/^(var|const)\s+([A-Za-z_][A-Za-z0-9_]*)\b/);if(valueDecl)symbols.push({name:valueDecl[2],kind:valueDecl[1]==="const"?"const":"variable",exported:/^[A-Z]/.test(valueDecl[2]),signature:line.trim().substring(0,100),line:i+1})}return symbols.sort((a,b)=>{if(a.line!==b.line)return a.line-b.line;return a.name.localeCompare(b.name)})}function findSourceFiles(cwd,maxFiles){let files=[];return walkDir(cwd,cwd,files,maxFiles),files}function walkDir(currentDir,rootDir,files,maxFiles){let entries;try{entries=fs78.readdirSync(currentDir,{withFileTypes:!0})}catch{return}entries.sort((a,b)=>a.name.toLowerCase().localeCompare(b.name.toLowerCase()));for(let entry of entries){if(files.length>=maxFiles)return;if(SKIP_DIRECTORIES.has(entry.name))continue;let fullPath=path139.join(currentDir,entry.name);if(entry.isDirectory())walkDir(fullPath,rootDir,files,maxFiles);else if(entry.isFile()&&SYMBOL_EXTENSIONS.has(path139.extname(entry.name).toLowerCase()))files.push(path139.relative(rootDir,fullPath))}}function searchWorkspaceSymbols(cwd,name,exportedOnly=!0){let startTime=Date.now(),sourceFiles=findSourceFiles(cwd,MAX_WORKSPACE_SCANNED_FILES),files=[],scannedCount=0,truncated=!1;if(sourceFiles.length>=MAX_WORKSPACE_SCANNED_FILES)truncated=!0;let totalSymbols=0;for(let relFile of sourceFiles){if(Date.now()-startTime>WORKSPACE_TIMEOUT_MS){truncated=!0;break}scannedCount++;let syms;switch(path139.extname(relFile).toLowerCase()){case".ts":case".tsx":case".js":case".jsx":case".mjs":case".cjs":syms=extractTSSymbols(relFile,cwd);break;case".py":case".pyw":syms=extractPythonSymbols(relFile,cwd);break;case".rs":syms=extractRustSymbols(relFile,cwd);break;case".go":syms=extractGoSymbols(relFile,cwd);break;default:continue}if(exportedOnly)syms=syms.filter((s)=>s.exported);if(name)syms=syms.filter((s)=>s.name.includes(name));if(syms.length>0){let remaining=MAX_WORKSPACE_RESULTS-totalSymbols;if(remaining<=0){truncated=!0;break}let cappedSyms=syms.slice(0,remaining);if(files.push({file:relFile,symbolCount:cappedSyms.length,symbols:cappedSyms}),totalSymbols+=cappedSyms.length,totalSymbols>=MAX_WORKSPACE_RESULTS){truncated=syms.length>remaining||scannedCount<sourceFiles.length;break}}}return{query:{workspace:!0,name},fileCount:files.length,scannedFileCount:scannedCount,totalSymbols,files,truncated}}var symbols=createSwarmTool({description:"Extract all exported symbols from a source file: functions with signatures, classes with public members, interfaces, types, enums, constants. Supports TypeScript/JavaScript, Python, Rust, and Go. Use for architect planning, designer scaffolding, and understanding module public API surface.",args:{file:exports_external.string().optional().describe('File path to extract symbols from (e.g., "src/auth/login.ts"). Required when not using workspace mode.'),exported_only:exports_external.boolean().default(!0).describe("If true, only return exported/public symbols. If false, include all top-level symbols."),workspace:exports_external.boolean().optional().describe("When true, search across the workspace instead of a single file. Returns per-file symbol summaries."),name:exports_external.string().optional().describe("Search for symbols by name (case-sensitive substring match). When provided without workspace, only searches the specified file.")},execute:async(args2,directory)=>{let file3,exportedOnly=!0,workspace=!1,name;try{let obj=args2;file3=obj.file!=null&&typeof obj.file==="string"?obj.file:void 0,exportedOnly=obj.exported_only!==!1,workspace=obj.workspace===!0,name=obj.name!=null&&typeof obj.name==="string"?obj.name:void 0}catch{return JSON.stringify({file:"<unknown>",error:"Invalid arguments: could not extract parameters",symbols:[]},null,2)}let cwd=directory;if(workspace)return JSON.stringify(searchWorkspaceSymbols(cwd,name,exportedOnly),null,2);if(!file3)return JSON.stringify({error:"file parameter is required when not using workspace mode",symbols:[]},null,2);if(containsControlChars(file3))return JSON.stringify({file:file3,error:"Path contains invalid control characters",symbols:[]},null,2);if(containsPathTraversal(file3))return JSON.stringify({file:file3,error:"Path contains path traversal sequence",symbols:[]},null,2);if(containsWindowsAttacks(file3))return JSON.stringify({file:file3,error:"Path contains invalid Windows-specific sequence",symbols:[]},null,2);if(!isPathInWorkspace(file3,cwd))return JSON.stringify({file:file3,error:"Path is outside workspace",symbols:[]},null,2);let ext=path139.extname(file3),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 JSON.stringify({file:file3,error:`Unsupported file extension: ${ext}. Supported: .ts, .tsx, .js, .jsx, .mjs, .cjs, .py, .pyw, .rs, .go`,symbols:[]},null,2)}if(exportedOnly)syms=syms.filter((s)=>s.exported);if(name)syms=syms.filter((s)=>s.name.includes(name));return JSON.stringify({file:file3,symbolCount:syms.length,symbols:syms},null,2)}});import*as path140 from"node:path";var HTTP_METHODS=["GET","POST","PUT","PATCH","DELETE","OPTIONS","HEAD"],MAX_FACTS_PER_KIND=50;function stripComments(content){let out="",i=0,state="code";while(i<content.length){let ch=content[i],next=i+1<content.length?content[i+1]:"";switch(state){case"code":if(ch==="/"&&next==="/")state="line",i+=2;else if(ch==="/"&&next==="*")state="block",i+=2;else{if(ch==="'")state="single";else if(ch==='"')state="double";else if(ch==="`")state="template";out+=ch,i++}break;case"single":case"double":case"template":{let quote=state==="single"?"'":state==="double"?'"':"`";if(ch==="\\")out+=ch+next,i+=2;else{if(ch===quote)state="code";out+=ch,i++}break}case"line":if(ch===`
|
|
5472
5472
|
`)state="code",out+=ch;i++;break;case"block":if(ch==="*"&&next==="/")state="code",i+=2;else{if(ch===`
|
|
5473
|
-
`)out+=ch;i++}break}}return out}function normalizeModuleName(moduleName){return moduleName.replace(/\\/g,"/").replace(/^(?:\.\/)+/,"")}function uniqueSorted(values){return[...new Set(values)].sort((a,b)=>a.localeCompare(b))}function addRole(roles,role){roles.add(role)}function boundaryForModule(moduleName){let parts=normalizeModuleName(moduleName).split("/").filter(Boolean);if(parts.length===0)return".";if((parts[0]==="packages"||parts[0]==="crates")&&parts.length>=2)return`${parts[0]}/${parts[1]}`;if(parts[0]==="src"&&parts.length>=3){if(parts[1]==="tools"&&parts[2]==="repo-graph")return"src/tools/repo-graph";return`src/${parts[1]}`}if(parts[0]==="tests"&&parts.length>=2)return`tests/${parts[1]}`;return parts[0]}function inferRoles(moduleName,content){let normalized=normalizeModuleName(moduleName).toLowerCase(),roles=new Set;if(/(^|\/)(__tests__|tests?)\//.test(normalized)||/\.(test|spec)\.[cm]?[jt]sx?$/.test(normalized))addRole(roles,"test_file");if(/(^|\/)(app\/api|pages\/api)\//.test(normalized)||/(^|\/)(routes?|controllers?)\//.test(normalized)||/\/route\.[cm]?[jt]sx?$/.test(normalized)||/\b(router|app|server)\s*\.\s*(get|post|put|patch|delete|all)\s*\(/i.test(content))addRole(roles,"api_route");if(/(^|\/)middleware\.[cm]?[jt]sx?$/.test(normalized))addRole(roles,"middleware");if(normalized.startsWith("src/tools/"))addRole(roles,"swarm_tool");if(normalized.startsWith("src/hooks/"))addRole(roles,"hook");if(normalized.startsWith("src/agents/"))addRole(roles,"agent");if(normalized.startsWith("src/cli/")||normalized.startsWith("src/commands/"))addRole(roles,"cli_command");if(normalized.startsWith("src/config/")||/(^|\/)(config|settings)\.[cm]?[jt]s$/.test(normalized))addRole(roles,"config");if(/(^|\/)(schema|schemas|types)\//.test(normalized)||/\b(z\.object|type\s+\w+\s*=|interface\s+\w+)/.test(content))addRole(roles,"schema");if(/(^|\/)(db|database|repositories?|models?|migrations?)\//.test(normalized)||/\b(prisma|drizzle|sequelize|knex|sqlite|sql`|db\.)/i.test(content))addRole(roles,"data_module");if(/(^|\/)(services?|lib|utils?)\//.test(normalized)||/\bexport\s+(async\s+)?function\b/.test(content))addRole(roles,"service_module");if(/\.(md|mdx|rst)$/.test(normalized))addRole(roles,"documentation");if(roles.size===0)addRole(roles,"source_module");return uniqueSorted(roles)}function pathRouteFromModule(moduleName){let parts=normalizeModuleName(moduleName).split("/"),appApi=parts.findIndex((part,index)=>{return part==="api"&&index>0&&parts[index-1]==="app"});if(appApi>=0)return`/${parts.slice(appApi).filter((part)=>!/^route\.[cm]?[jt]sx?$/.test(part)).map(routeSegment).join("/")}`.replace(/\/+/g,"/");let pagesApi=parts.findIndex((part,index)=>{return part==="api"&&index>0&&parts[index-1]==="pages"});if(pagesApi>=0){let last=parts[parts.length-1]?.replace(/\.[^.]+$/,"");return`/${[...parts.slice(pagesApi,-1),last].filter(Boolean).map(routeSegment).join("/")}`.replace(/\/+/g,"/")}return null}function routeSegment(segment){return segment.replace(/^\[(\.\.\.)?(.+)]$/,(_m,rest,name)=>rest?`:${name}*`:`:${name}`).replace(/\.[^.]+$/,"")}function extractRoutes(moduleName,content){let routes=[],pathRoute=pathRouteFromModule(moduleName),lines=content.split(/\r?\n/);for(let i=0;i<lines.length;i++){let line=lines[i];for(let method of HTTP_METHODS){let exportPattern=new RegExp(`\\bexport\\s+(?:async\\s+)?(?:function|const)\\s+${method}\\b`);if(pathRoute&&exportPattern.test(line))routes.push({method,path:pathRoute,line:i+1,source:"handler_export"})}let routerMatch=line.match(/\b(?:router|app|server)\s*\.\s*(get|post|put|patch|delete|options|head|all)\s*\(\s*['"`]([^'"`\0\r\n]+)['"`]/i);if(routerMatch)routes.push({method:routerMatch[1].toUpperCase(),path:routerMatch[2],line:i+1,source:"router_call"})}if(pathRoute&&routes.length===0)routes.push({method:"ALL",path:pathRoute,source:"file_path"});return routes.slice(0,MAX_FACTS_PER_KIND)}function classifyDataOperation(line){let trimmed=line.trim(),lower=trimmed.toLowerCase(),evidence=trimmed.slice(0,160),operation=null,access5="unknown",entity;if(/\b(transaction|begintransaction|commit|rollback)\b/i.test(trimmed))operation="transaction",access5="database";if(/\b(migrate|migration|schema\.alter|createTable|dropTable)\b/i.test(trimmed))operation="migration",access5="database";if(/\b(findMany|findUnique|findFirst|select|query|count|aggregate)\b/.test(trimmed))operation??="read";if(/\b(create|insert|update|upsert|save|patch)\b/.test(trimmed))operation??="write";if(/\b(delete|deleteMany|remove|destroy)\b/.test(trimmed))operation="delete";if(/\b(sql`|\bselect\b|\binsert\b|\bupdate\b|\bdelete\b|\bfrom\b)/i.test(trimmed))access5="sql";if(/\b(prisma|drizzle|sequelize|knex|db\.|database\.|repository\.)/i.test(trimmed))access5=access5==="sql"?"sql":"orm";if(/\b(readFile|writeFile|appendFile|rmSync|unlink)\b/.test(trimmed))access5="filesystem",operation??=lower.includes("read")?"read":"write";if(/\b(fetch|axios|http\.|https\.)\b/.test(trimmed))access5="network",operation??="read";let entityMatch=trimmed.match(/\b(?:prisma|db|database)\.(\w+)/i);if(entityMatch)entity=entityMatch[1];if(!operation)return null;return{operation,access:access5,entity,line:0,evidence}}function extractDataOperations(content){let facts=[],lines=content.split(/\r?\n/);for(let i=0;i<lines.length;i++){let fact=classifyDataOperation(lines[i]);if(!fact)continue;if(fact.line=i+1,facts.push(fact),facts.length>=MAX_FACTS_PER_KIND)break}return facts}function extractSecurityFacts(content){let facts=[],lines=content.split(/\r?\n/),push=(kind,line,evidence,confidence)=>{facts.push({kind,line,evidence:evidence.trim().slice(0,160),confidence})};for(let i=0;i<lines.length&&facts.length<MAX_FACTS_PER_KIND;i++){let line=lines[i];if(/\b(requireAuth|requireUser|getServerSession|currentUser|verifyToken|jwt|isAuthenticated|ctx\.user|session)\b/i.test(line))push("authentication",i+1,line,"high");if(/\b(requireRole|hasPermission|authorize|authorization|isAdmin|rbac|policy\.check|can\()\b/i.test(line))push("authorization",i+1,line,"high");if(/\b(z\.object|safeParse|\.parse\(|joi\.|yup\.|validate\w*)\b/i.test(line))push("input_validation",i+1,line,"high");if(/\b(csrf|csrfToken|sameSite)\b/i.test(line))push("csrf",i+1,line,"medium");if(/\b(sanitize|escapeHtml|DOMPurify|xss)\b/i.test(line))push("sanitization",i+1,line,"medium");if(/\b(secret|api[_-]?key|token|password)\b/i.test(line))push("secret_handling",i+1,line,"low")}return facts}function extractConventions(moduleName,roles,routes){let conventions=[];if(roles.includes("test_file"))conventions.push({name:"test_file_naming",evidence:`${path140.basename(moduleName)} matches test/spec naming`});if(routes.some((route)=>route.source==="handler_export"))conventions.push({name:"next_app_route_handler",evidence:"HTTP method exports map to route handlers"});if(roles.includes("swarm_tool"))conventions.push({name:"swarm_tool_module",evidence:"module lives under src/tools"});if(roles.includes("hook"))conventions.push({name:"hook_module",evidence:"module lives under src/hooks"});return conventions}function buildFindings(roles,routes,dataOperations,security){let findings=[],hasAuth=security.some((fact)=>fact.kind==="authentication"||fact.kind==="authorization"||fact.kind==="csrf"),hasValidation=security.some((fact)=>fact.kind==="input_validation"||fact.kind==="sanitization"),mutatingRoute=routes.some((route)=>["POST","PUT","PATCH","DELETE","ALL"].includes(route.method)),writes=dataOperations.filter((fact)=>["write","delete","migration"].includes(fact.operation)),hasTransaction=dataOperations.some((fact)=>fact.operation==="transaction");if(roles.includes("api_route")&&routes.length>0&&!hasAuth)findings.push({code:"api_route_without_detected_auth",severity:"medium",message:"No authentication, authorization, or CSRF guard was detected near this route.",line:routes[0]?.line});if(mutatingRoute&&!hasValidation)findings.push({code:"mutating_route_without_detected_validation",severity:"medium",message:"Route appears to mutate state without a detected validation or sanitization fact.",line:routes.find((route)=>["POST","PUT","PATCH","DELETE","ALL"].includes(route.method))?.line});if(writes.length>1&&!hasTransaction)findings.push({code:"multiple_writes_without_detected_transaction",severity:"low",message:"Multiple write/delete operations were detected without a transaction fact.",line:writes[0]?.line});return findings}function extractFileOntology(input){let moduleName=normalizeModuleName(input.moduleName),content=stripComments(input.content),roles=inferRoles(moduleName,content),routes=extractRoutes(moduleName,content),dataOperations=extractDataOperations(content),security=extractSecurityFacts(content),conventions=extractConventions(moduleName,roles,routes),findings=buildFindings(roles,routes,dataOperations,security);return{roles,packageBoundary:boundaryForModule(moduleName),routes,dataOperations,security,conventions,findings}}import{realpathSync as realpathSync14}from"node:fs";function safeRealpathSync(targetPath,fallback,realpathResolver=realpathSync14){try{return realpathResolver(targetPath)}catch(error93){if(error93 instanceof Error&&error93.code==="ENOENT")return fallback;return null}}import*as path141 from"node:path";var REPO_GRAPH_FILENAME="repo-graph.json",GRAPH_SCHEMA_VERSION="1.2.0";function isSchemaVersionAtLeast(version5,minimum){let parse10=(v)=>v.split(".").map((part)=>{let n=Number.parseInt(part,10);return Number.isFinite(n)?n:0}),a=parse10(version5??""),b=parse10(minimum),len=Math.max(a.length,b.length);for(let i=0;i<len;i++){let av=a[i]??0,bv=b[i]??0;if(av>bv)return!0;if(av<bv)return!1}return!0}var FILE_ROLE_VALUES=["api_route","middleware","service_module","data_module","swarm_tool","agent","hook","config","schema","test_file","cli_command","documentation","source_module"],ROUTE_METHOD_VALUES=["GET","POST","PUT","PATCH","DELETE","OPTIONS","HEAD","ALL"],ROUTE_SOURCE_VALUES=["file_path","handler_export","router_call"],DATA_OPERATION_VALUES=["read","write","delete","transaction","migration"],DATA_ACCESS_VALUES=["database","orm","sql","filesystem","network","unknown"],SECURITY_KIND_VALUES=["authentication","authorization","input_validation","csrf","sanitization","secret_handling"],SECURITY_CONFIDENCE_VALUES=["low","medium","high"],ONTOLOGY_FINDING_SEVERITY_VALUES=["info","low","medium","high"],IMPORT_TYPE_VALUES=["default","named","namespace","require","sideeffect","type"];function normalizeGraphPath(filePath){return path141.normalize(filePath).replace(/\\/g,"/")}function createEmptyGraph(workspaceRoot){return{schema_version:GRAPH_SCHEMA_VERSION,workspaceRoot:path141.normalize(workspaceRoot),nodes:{},edges:[],metadata:{generatedAt:new Date().toISOString(),generator:"repo-graph",nodeCount:0,edgeCount:0}}}function updateGraphMetadata(graph){graph.metadata={generatedAt:new Date().toISOString(),generator:"repo-graph",nodeCount:Object.keys(graph.nodes).length,edgeCount:graph.edges.length}}init_path_security();var FILE_ROLE_SET=new Set(FILE_ROLE_VALUES),ROUTE_METHOD_SET=new Set(ROUTE_METHOD_VALUES),ROUTE_SOURCE_SET=new Set(ROUTE_SOURCE_VALUES),DATA_OPERATION_SET=new Set(DATA_OPERATION_VALUES),DATA_ACCESS_SET=new Set(DATA_ACCESS_VALUES),SECURITY_KIND_SET=new Set(SECURITY_KIND_VALUES),SECURITY_CONFIDENCE_SET=new Set(SECURITY_CONFIDENCE_VALUES),ONTOLOGY_FINDING_SEVERITY_SET=new Set(ONTOLOGY_FINDING_SEVERITY_VALUES),IMPORT_TYPE_SET=new Set(IMPORT_TYPE_VALUES),ONTOLOGY_NAME_PATTERN=/^[a-z][a-z0-9_]*$/;function validateWorkspace(workspace){if(!workspace||typeof workspace!=="string"||workspace.trim()==="")throw Error("Invalid workspace: must be a non-empty string");if(containsControlChars(workspace))throw Error("Invalid workspace: control characters detected");if(containsPathTraversal(workspace))throw Error("Invalid workspace: path traversal detected")}function validateGraphNode(node){if(!node||typeof node!=="object")throw Error("Invalid node: must be an object");if(!node.filePath||typeof node.filePath!=="string")throw Error("Invalid node: filePath is required");if(!node.filePath.startsWith("/")&&!/^[A-Za-z]:[/\\]/.test(node.filePath))throw Error("Invalid node: filePath must be absolute");if(containsPathTraversal(node.filePath))throw Error("Invalid node: filePath contains path traversal");if(containsControlChars(node.filePath))throw Error("Invalid node: filePath contains control characters");if(!node.moduleName||typeof node.moduleName!=="string")throw Error("Invalid node: moduleName is required");if(node.moduleName.startsWith("/")||node.moduleName.startsWith("\\")||/^[A-Za-z]:[/\\]/.test(node.moduleName))throw Error("Invalid node: moduleName must be relative");if(containsPathTraversal(node.moduleName))throw Error("Invalid node: moduleName contains path traversal");if(containsControlChars(node.moduleName))throw Error("Invalid node: moduleName contains control characters");if(typeof node.language!=="string")throw Error("Invalid node: language is required");if(typeof node.mtime!=="string")throw Error("Invalid node: mtime is required");if(!Array.isArray(node.exports))throw Error("Invalid node: exports must be an array");for(let exp of node.exports){if(typeof exp!=="string")throw Error("Invalid node: exports must be an array of strings");if(containsControlChars(exp)){let preview=exp.slice(0,120);throw Error(`Invalid node: exports contains control characters (file=${node.filePath}, value="${preview}")`)}}if(!Array.isArray(node.imports))throw Error("Invalid node: imports must be an array");for(let imp of node.imports){if(typeof imp!=="string")throw Error("Invalid node: imports must be an array of strings");if(containsControlChars(imp)){let preview=imp.slice(0,120);throw Error(`Invalid node: imports contains control characters (file=${node.filePath}, value="${preview}")`)}}if(node.exportLines!==void 0){if(typeof node.exportLines!=="object"||node.exportLines===null||Array.isArray(node.exportLines))throw Error("Invalid node: exportLines must be an object");for(let[name,line]of Object.entries(node.exportLines)){if(containsControlChars(name))throw Error("Invalid node: exportLines key contains control characters");if(typeof line!=="number"||!Number.isFinite(line)||line<0)throw Error("Invalid node: exportLines values must be non-negative numbers")}}if(node.exportRanges!==void 0){if(typeof node.exportRanges!=="object"||node.exportRanges===null||Array.isArray(node.exportRanges))throw Error("Invalid node: exportRanges must be an object");for(let[name,range]of Object.entries(node.exportRanges)){if(containsControlChars(name))throw Error("Invalid node: exportRanges key contains control characters");if(typeof range!=="object"||range===null||Array.isArray(range))throw Error("Invalid node: exportRanges values must be objects");let r=range;if(typeof r.startLine!=="number"||!Number.isFinite(r.startLine)||!Number.isInteger(r.startLine)||r.startLine<1||typeof r.endLine!=="number"||!Number.isFinite(r.endLine)||!Number.isInteger(r.endLine)||r.endLine<1)throw Error("Invalid node: exportRanges value must have positive integer startLine and endLine (1-based)");if(r.startLine>r.endLine)throw Error("Invalid node: exportRanges value must have startLine <= endLine")}}if(node.ontology!==void 0)validateOntologyStrings(node)}function validateOntologyStrings(node){let ontology=node.ontology;if(!ontology||typeof ontology!=="object")throw Error("Invalid node: ontology must be an object");let values=[...ontology.roles??[],ontology.packageBoundary,...(ontology.routes??[]).flatMap((route)=>[route.method,route.path,route.source]),...(ontology.dataOperations??[]).flatMap((fact)=>[fact.operation,fact.access,fact.entity??"",fact.evidence]),...(ontology.security??[]).flatMap((fact)=>[fact.kind,fact.evidence,fact.confidence]),...(ontology.conventions??[]).flatMap((fact)=>[fact.name,fact.evidence]),...(ontology.findings??[]).flatMap((finding)=>[finding.code,finding.severity,finding.message])];for(let value of values){if(typeof value!=="string")throw Error("Invalid node: ontology contains non-string value");if(containsControlChars(value)){let preview=value.slice(0,120);throw Error(`Invalid node: ontology contains control characters (file=${node.filePath}, value="${preview}")`)}}for(let role of ontology.roles??[])validateAllowedOntologyValue(node,"ontology.roles",role,FILE_ROLE_SET);for(let route of ontology.routes??[])validateAllowedOntologyValue(node,"ontology.routes.method",route.method,ROUTE_METHOD_SET),validateAllowedOntologyValue(node,"ontology.routes.source",route.source,ROUTE_SOURCE_SET);for(let fact of ontology.dataOperations??[])validateAllowedOntologyValue(node,"ontology.dataOperations.operation",fact.operation,DATA_OPERATION_SET),validateAllowedOntologyValue(node,"ontology.dataOperations.access",fact.access,DATA_ACCESS_SET);for(let fact of ontology.security??[])validateAllowedOntologyValue(node,"ontology.security.kind",fact.kind,SECURITY_KIND_SET),validateAllowedOntologyValue(node,"ontology.security.confidence",fact.confidence,SECURITY_CONFIDENCE_SET);for(let finding of ontology.findings??[])validateOntologyName(node,"ontology.findings.code",finding.code),validateAllowedOntologyValue(node,"ontology.findings.severity",finding.severity,ONTOLOGY_FINDING_SEVERITY_SET)}function validateOntologyName(node,field,value){if(ONTOLOGY_NAME_PATTERN.test(value))return;let preview=value.slice(0,120);throw Error(`Invalid node: ${field} must be lower_snake_case (file=${node.filePath}, value="${preview}")`)}function validateAllowedOntologyValue(node,field,value,allowed){if(allowed.has(value))return;let preview=value.slice(0,120);throw Error(`Invalid node: ${field} contains invalid value (file=${node.filePath}, value="${preview}")`)}function validateGraphEdge(edge){if(!edge||typeof edge!=="object")throw Error("Invalid edge: must be an object");if(!edge.source||typeof edge.source!=="string")throw Error("Invalid edge: source is required");if(!edge.target||typeof edge.target!=="string")throw Error("Invalid edge: target is required");if(containsPathTraversal(edge.source)||containsPathTraversal(edge.target))throw Error("Invalid edge: path traversal detected");if(containsControlChars(edge.source)||containsControlChars(edge.target))throw Error("Invalid edge: control characters detected");if(!edge.importSpecifier||typeof edge.importSpecifier!=="string")throw Error("Invalid edge: importSpecifier is required");if(containsControlChars(edge.importSpecifier))throw Error("Invalid edge: importSpecifier contains control characters");if(!IMPORT_TYPE_SET.has(edge.importType))throw Error("Invalid edge: importType is invalid");if(edge.importedSymbols!==void 0){if(!Array.isArray(edge.importedSymbols))throw Error("Invalid edge: importedSymbols must be an array");for(let symbol3 of edge.importedSymbols){if(typeof symbol3!=="string")throw Error("Invalid edge: importedSymbols must be an array of strings");if(containsControlChars(symbol3))throw Error("Invalid edge: importedSymbols contains control characters")}}if(edge.usedSymbols!==void 0){if(!Array.isArray(edge.usedSymbols))throw Error("Invalid edge: usedSymbols must be an array");for(let symbol3 of edge.usedSymbols){if(typeof symbol3!=="string")throw Error("Invalid edge: usedSymbols must be an array of strings");if(containsControlChars(symbol3))throw Error("Invalid edge: usedSymbols contains control characters")}}}var _internals89={safeRealpathSync,extractTSSymbols,extractPythonSymbols,extractRustSymbols,extractGoSymbols,parseFileImports,extractFileOntology,stripComments:stripComments2,computeUsedSymbols,extractFileSymbols},SKIP_DIRECTORIES2=new Set(["node_modules",".git","dist","build","out","coverage",".next",".nuxt",".cache","vendor",".svn",".hg",".svelte-kit"]);function resolveSkipDirectories(excludeDirs){let extras=excludeDirs?.filter((d)=>d.length>0)??[];if(extras.length===0)return SKIP_DIRECTORIES2;return new Set([...SKIP_DIRECTORIES2,...extras])}var SUPPORTED_EXTENSIONS=new Set(LANGUAGE_REGISTRY.getAll().filter((p)=>!p.parserOnly).flatMap((p)=>p.extensions)),DEFAULT_WALK_FILE_CAP=1e4,DEFAULT_WALK_BUDGET_MS=5000,ASYNC_WALK_YIELD_INTERVAL=200,MAX_DIAGNOSTIC_ENTRIES=200,EXTENSION_TO_LANGUAGE={};for(let profile of LANGUAGE_REGISTRY.getAll()){if(profile.parserOnly)continue;for(let ext of profile.extensions)EXTENSION_TO_LANGUAGE[ext]=profile.treeSitter.grammarId}var JS_FAMILY_EXTENSION_TO_LANGUAGE={".js":"javascript",".jsx":"javascript",".mjs":"javascript",".cjs":"javascript",".ts":"typescript",".tsx":"tsx"};function upsertNode(graph,node){validateGraphNode(node);let key=normalizeGraphPath(node.filePath);graph.nodes[key]=node,updateGraphMetadata(graph)}function addEdge(graph,edge){if(validateGraphEdge(edge),!graph.edges.some((e)=>e.source===edge.source&&e.target===edge.target&&e.importSpecifier===edge.importSpecifier))graph.edges.push(edge),updateGraphMetadata(graph)}function buildLoopEdgeKey(edge){return`${edge.source}\x00${edge.target}\x00${edge.importSpecifier}`}function appendNodeFast(graph,node){validateGraphNode(node),graph.nodes[normalizeGraphPath(node.filePath)]=node}function appendEdgeFast(graph,edge,seenEdgeKeys){validateGraphEdge(edge);let key=buildLoopEdgeKey(edge);if(seenEdgeKeys.has(key))return;seenEdgeKeys.add(key),graph.edges.push(edge)}function resolveModuleSpecifier(workspaceRoot,sourceFile,specifier){if(containsControlChars(specifier))return null;if(specifier.startsWith("/")||specifier.startsWith("\\"))return null;if(/^[A-Za-z]:[/\\]/.test(specifier))return null;if(specifier.startsWith("http://")||specifier.startsWith("https://"))return null;try{let normalizedSpecifier=specifier,rustParts=specifier.split("::").filter(Boolean);if(rustParts[0]==="crate"){let target=path142.join(workspaceRoot,...rustParts.slice(1));if(!(existsSync80(target)||existsSync80(`${target}.rs`)||existsSync80(path142.join(target,"mod.rs"))))target=path142.join(path142.dirname(sourceFile),...rustParts.slice(1));if(normalizedSpecifier=path142.relative(path142.dirname(sourceFile),target).replace(/\\/g,"/"),!normalizedSpecifier.startsWith("."))normalizedSpecifier=`./${normalizedSpecifier}`}else if(rustParts[0]==="self")normalizedSpecifier=`./${rustParts.slice(1).join("/")}`;else if(rustParts[0]==="super"){let superCount=0;while(rustParts[superCount]==="super")superCount++;normalizedSpecifier=`${"../".repeat(superCount)}${rustParts.slice(superCount).join("/")}`}if(normalizedSpecifier.startsWith(".")){let sourceDir=path142.dirname(sourceFile),resolved=path142.resolve(sourceDir,normalizedSpecifier),initialRealResolved=_internals89.safeRealpathSync(resolved,resolved);if(initialRealResolved===null)return null;let realResolved=initialRealResolved,realRoot=_internals89.safeRealpathSync(workspaceRoot,path142.normalize(workspaceRoot));if(realRoot===null)return null;let findDirectoryEntry=(directory)=>{for(let initName of["__init__.py","__init__.pyw","mod.rs"]){let candidate=path142.join(directory,initName);if(existsSync80(candidate))return candidate}if(path142.extname(sourceFile).toLowerCase()===".go"){let basenameCandidate=path142.join(directory,`${path142.basename(directory)}.go`);if(existsSync80(basenameCandidate))return basenameCandidate;try{let firstGo=fsSync9.readdirSync(directory).filter((entry)=>entry.endsWith(".go")&&!entry.endsWith("_test.go")).sort((a,b)=>a.localeCompare(b))[0];if(firstGo)return path142.join(directory,firstGo)}catch{return null}}return null};if(existsSync80(resolved))try{if(fsSync9.statSync(resolved).isDirectory()){let found=findDirectoryEntry(resolved);if(!found)return null;let foundRealPath=_internals89.safeRealpathSync(found,found);if(foundRealPath===null)return null;realResolved=foundRealPath,resolved=found}}catch{return null}if(!existsSync80(resolved)){let EXTENSIONS=path142.extname(sourceFile).toLowerCase()===".pyw"?[".pyw",".py",".rs",".go",".ts",".tsx",".js",".jsx",".mjs",".cjs",".json"]:[".ts",".tsx",".js",".jsx",".mjs",".cjs",".py",".pyw",".rs",".go",".json"],found=null;for(let ext of EXTENSIONS){let candidate=resolved+ext;if(existsSync80(candidate)){found=candidate;break}}if(!found)found=findDirectoryEntry(resolved);if(found){let foundRealPath=_internals89.safeRealpathSync(found,found);if(foundRealPath===null)return null;realResolved=foundRealPath,resolved=found}else return null}let normalizedResolved=path142.normalize(realResolved),normalizedRoot=path142.normalize(realRoot);if(!normalizedResolved.startsWith(normalizedRoot+path142.sep)&&normalizedResolved!==normalizedRoot)return null;return resolved}return null}catch{return null}}function isRefusedWorkspaceRoot(target){let resolved;try{resolved=realpathSync15(target)}catch{resolved=path142.resolve(target)}let refused=new Set,add2=(p)=>{if(typeof p==="string"&&p.length>0)refused.add(path142.resolve(p))};if(add2(os21.homedir()),add2(os21.tmpdir()),add2("/"),add2("/Users"),add2("/home"),add2("/root"),process.platform==="win32")add2("C:\\"),add2("C:\\Users");return refused.has(resolved)}function createEmptyDiagnostics(){return{extractionFailures:[],unresolvedImports:[],oversizedFiles:[],unsupportedFiles:[],binaryFiles:[],unreadableFiles:[],lowConfidenceEdgeCount:0}}function diagnosticsHaveEntries(diagnostics){return(diagnostics.extractionFailures?.length??0)>0||(diagnostics.unresolvedImports?.length??0)>0||(diagnostics.oversizedFiles?.length??0)>0||(diagnostics.unsupportedFiles?.length??0)>0||(diagnostics.binaryFiles?.length??0)>0||(diagnostics.unreadableFiles?.length??0)>0||(diagnostics.lowConfidenceEdgeCount??0)>0}function pushCapped(target,value){if(target.length<MAX_DIAGNOSTIC_ENTRIES)target.push(value)}function mergeDiagnostics(target,source){if(!source)return;for(let entry of source.extractionFailures??[])pushCapped(target.extractionFailures,entry);for(let entry of source.unresolvedImports??[])pushCapped(target.unresolvedImports,entry);for(let entry of source.oversizedFiles??[])pushCapped(target.oversizedFiles,entry);for(let entry of source.unsupportedFiles??[])pushCapped(target.unsupportedFiles,entry);for(let entry of source.binaryFiles??[])pushCapped(target.binaryFiles,entry);for(let entry of source.unreadableFiles??[])pushCapped(target.unreadableFiles,entry);target.lowConfidenceEdgeCount+=source.lowConfidenceEdgeCount??0}function isRelativeImportSpecifier(specifier){return specifier==="."||specifier===".."||specifier.startsWith("./")||specifier.startsWith("../")}function unresolvedRelativeImportsFor(parsedImports,filePath,absoluteRoot){let unresolved=[],moduleName=toModuleName(filePath,absoluteRoot);for(let parsed of parsedImports){if(!isRelativeImportSpecifier(parsed.specifier))continue;if(resolveModuleSpecifier(absoluteRoot,filePath,parsed.specifier)===null)unresolved.push({file:moduleName,specifier:parsed.specifier})}return unresolved}var REGEX_ALLOWED_AFTER=new Set("(,=:[!&|?{};*+-~^<>%".split(""));function stripComments2(content){let out="",i=0,n=content.length,state="code",prevSignificant="",regexInClass=!1;while(i<n){let ch=content[i],next=i+1<n?content[i+1]:"";switch(state){case"code":if(ch==="/"&&next==="/")state="line",i+=2;else if(ch==="/"&&next==="*")state="block",i+=2;else if(ch==="/"&®EX_ALLOWED_AFTER.has(prevSignificant))state="regex",regexInClass=!1,out+=ch,i+=1;else{if(ch==="'")state="single";else if(ch==='"')state="double";else if(ch==="`")state="template";if(out+=ch,ch.trim()!=="")prevSignificant=ch;i+=1}break;case"single":case"double":case"template":{let quote=state==="single"?"'":state==="double"?'"':"`";if(ch==="\\")out+=ch+next,i+=2;else{if(ch===quote)state="code",prevSignificant=quote;out+=ch,i+=1}break}case"regex":if(ch==="\\")out+=ch+next,i+=2;else if(ch===`
|
|
5473
|
+
`)out+=ch;i++}break}}return out}function normalizeModuleName(moduleName){return moduleName.replace(/\\/g,"/").replace(/^(?:\.\/)+/,"")}function uniqueSorted(values){return[...new Set(values)].sort((a,b)=>a.localeCompare(b))}function addRole(roles,role){roles.add(role)}function boundaryForModule(moduleName){let parts=normalizeModuleName(moduleName).split("/").filter(Boolean);if(parts.length===0)return".";if((parts[0]==="packages"||parts[0]==="crates")&&parts.length>=2)return`${parts[0]}/${parts[1]}`;if(parts[0]==="src"&&parts.length>=3){if(parts[1]==="tools"&&parts[2]==="repo-graph")return"src/tools/repo-graph";return`src/${parts[1]}`}if(parts[0]==="tests"&&parts.length>=2)return`tests/${parts[1]}`;return parts[0]}function inferRoles(moduleName,content){let normalized=normalizeModuleName(moduleName).toLowerCase(),roles=new Set;if(/(^|\/)(__tests__|tests?)\//.test(normalized)||/\.(test|spec)\.[cm]?[jt]sx?$/.test(normalized))addRole(roles,"test_file");if(/(^|\/)(app\/api|pages\/api)\//.test(normalized)||/(^|\/)(routes?|controllers?)\//.test(normalized)||/\/route\.[cm]?[jt]sx?$/.test(normalized)||/\b(router|app|server)\s*\.\s*(get|post|put|patch|delete|all)\s*\(/i.test(content))addRole(roles,"api_route");if(/(^|\/)middleware\.[cm]?[jt]sx?$/.test(normalized))addRole(roles,"middleware");if(normalized.startsWith("src/tools/"))addRole(roles,"swarm_tool");if(normalized.startsWith("src/hooks/"))addRole(roles,"hook");if(normalized.startsWith("src/agents/"))addRole(roles,"agent");if(normalized.startsWith("src/cli/")||normalized.startsWith("src/commands/"))addRole(roles,"cli_command");if(normalized.startsWith("src/config/")||/(^|\/)(config|settings)\.[cm]?[jt]s$/.test(normalized))addRole(roles,"config");if(/(^|\/)(schema|schemas|types)\//.test(normalized)||/\b(z\.object|type\s+\w+\s*=|interface\s+\w+)/.test(content))addRole(roles,"schema");if(/(^|\/)(db|database|repositories?|models?|migrations?)\//.test(normalized)||/\b(prisma|drizzle|sequelize|knex|sqlite|sql`|db\.)/i.test(content))addRole(roles,"data_module");if(/(^|\/)(services?|lib|utils?)\//.test(normalized)||/\bexport\s+(async\s+)?function\b/.test(content))addRole(roles,"service_module");if(/\.(md|mdx|rst)$/.test(normalized))addRole(roles,"documentation");if(roles.size===0)addRole(roles,"source_module");return uniqueSorted(roles)}function pathRouteFromModule(moduleName){let parts=normalizeModuleName(moduleName).split("/"),appApi=parts.findIndex((part,index)=>{return part==="api"&&index>0&&parts[index-1]==="app"});if(appApi>=0)return`/${parts.slice(appApi).filter((part)=>!/^route\.[cm]?[jt]sx?$/.test(part)).map(routeSegment).join("/")}`.replace(/\/+/g,"/");let pagesApi=parts.findIndex((part,index)=>{return part==="api"&&index>0&&parts[index-1]==="pages"});if(pagesApi>=0){let last=parts[parts.length-1]?.replace(/\.[^.]+$/,"");return`/${[...parts.slice(pagesApi,-1),last].filter(Boolean).map(routeSegment).join("/")}`.replace(/\/+/g,"/")}return null}function routeSegment(segment){return segment.replace(/^\[(\.\.\.)?(.+)]$/,(_m,rest,name)=>rest?`:${name}*`:`:${name}`).replace(/\.[^.]+$/,"")}function extractRoutes(moduleName,content){let routes=[],pathRoute=pathRouteFromModule(moduleName),lines=content.split(/\r?\n/);for(let i=0;i<lines.length;i++){let line=lines[i];for(let method of HTTP_METHODS){let exportPattern=new RegExp(`\\bexport\\s+(?:async\\s+)?(?:function|const)\\s+${method}\\b`);if(pathRoute&&exportPattern.test(line))routes.push({method,path:pathRoute,line:i+1,source:"handler_export"})}let routerMatch=line.match(/\b(?:router|app|server)\s*\.\s*(get|post|put|patch|delete|options|head|all)\s*\(\s*['"`]([^'"`\0\r\n]+)['"`]/i);if(routerMatch)routes.push({method:routerMatch[1].toUpperCase(),path:routerMatch[2],line:i+1,source:"router_call"})}if(pathRoute&&routes.length===0)routes.push({method:"ALL",path:pathRoute,source:"file_path"});return routes.slice(0,MAX_FACTS_PER_KIND)}function classifyDataOperation(line){let trimmed=line.trim(),lower=trimmed.toLowerCase(),evidence=trimmed.slice(0,160),operation=null,access5="unknown",entity;if(/\b(transaction|begintransaction|commit|rollback)\b/i.test(trimmed))operation="transaction",access5="database";if(/\b(migrate|migration|schema\.alter|createTable|dropTable)\b/i.test(trimmed))operation="migration",access5="database";if(/\b(findMany|findUnique|findFirst|select|query|count|aggregate)\b/.test(trimmed))operation??="read";if(/\b(create|insert|update|upsert|save|patch)\b/.test(trimmed))operation??="write";if(/\b(delete|deleteMany|remove|destroy)\b/.test(trimmed))operation="delete";if(/\b(sql`|\bselect\b|\binsert\b|\bupdate\b|\bdelete\b|\bfrom\b)/i.test(trimmed))access5="sql";if(/\b(prisma|drizzle|sequelize|knex|db\.|database\.|repository\.)/i.test(trimmed))access5=access5==="sql"?"sql":"orm";if(/\b(readFile|writeFile|appendFile|rmSync|unlink)\b/.test(trimmed))access5="filesystem",operation??=lower.includes("read")?"read":"write";if(/\b(fetch|axios|http\.|https\.)\b/.test(trimmed))access5="network",operation??="read";let entityMatch=trimmed.match(/\b(?:prisma|db|database)\.(\w+)/i);if(entityMatch)entity=entityMatch[1];if(!operation)return null;return{operation,access:access5,entity,line:0,evidence}}function extractDataOperations(content){let facts=[],lines=content.split(/\r?\n/);for(let i=0;i<lines.length;i++){let fact=classifyDataOperation(lines[i]);if(!fact)continue;if(fact.line=i+1,facts.push(fact),facts.length>=MAX_FACTS_PER_KIND)break}return facts}function extractSecurityFacts(content){let facts=[],lines=content.split(/\r?\n/),push=(kind,line,evidence,confidence)=>{facts.push({kind,line,evidence:evidence.trim().slice(0,160),confidence})};for(let i=0;i<lines.length&&facts.length<MAX_FACTS_PER_KIND;i++){let line=lines[i];if(/\b(requireAuth|requireUser|getServerSession|currentUser|verifyToken|jwt|isAuthenticated|ctx\.user|session)\b/i.test(line))push("authentication",i+1,line,"high");if(/\b(requireRole|hasPermission|authorize|authorization|isAdmin|rbac|policy\.check|can\()\b/i.test(line))push("authorization",i+1,line,"high");if(/\b(z\.object|safeParse|\.parse\(|joi\.|yup\.|validate\w*)\b/i.test(line))push("input_validation",i+1,line,"high");if(/\b(csrf|csrfToken|sameSite)\b/i.test(line))push("csrf",i+1,line,"medium");if(/\b(sanitize|escapeHtml|DOMPurify|xss)\b/i.test(line))push("sanitization",i+1,line,"medium");if(/\b(secret|api[_-]?key|token|password)\b/i.test(line))push("secret_handling",i+1,line,"low")}return facts}function extractConventions(moduleName,roles,routes){let conventions=[];if(roles.includes("test_file"))conventions.push({name:"test_file_naming",evidence:`${path140.basename(moduleName)} matches test/spec naming`});if(routes.some((route)=>route.source==="handler_export"))conventions.push({name:"next_app_route_handler",evidence:"HTTP method exports map to route handlers"});if(roles.includes("swarm_tool"))conventions.push({name:"swarm_tool_module",evidence:"module lives under src/tools"});if(roles.includes("hook"))conventions.push({name:"hook_module",evidence:"module lives under src/hooks"});return conventions}function buildFindings(roles,routes,dataOperations,security){let findings=[],hasAuth=security.some((fact)=>fact.kind==="authentication"||fact.kind==="authorization"||fact.kind==="csrf"),hasValidation=security.some((fact)=>fact.kind==="input_validation"||fact.kind==="sanitization"),mutatingRoute=routes.some((route)=>["POST","PUT","PATCH","DELETE","ALL"].includes(route.method)),writes=dataOperations.filter((fact)=>["write","delete","migration"].includes(fact.operation)),hasTransaction=dataOperations.some((fact)=>fact.operation==="transaction");if(roles.includes("api_route")&&routes.length>0&&!hasAuth)findings.push({code:"api_route_without_detected_auth",severity:"medium",message:"No authentication, authorization, or CSRF guard was detected near this route.",line:routes[0]?.line});if(mutatingRoute&&!hasValidation)findings.push({code:"mutating_route_without_detected_validation",severity:"medium",message:"Route appears to mutate state without a detected validation or sanitization fact.",line:routes.find((route)=>["POST","PUT","PATCH","DELETE","ALL"].includes(route.method))?.line});if(writes.length>1&&!hasTransaction)findings.push({code:"multiple_writes_without_detected_transaction",severity:"low",message:"Multiple write/delete operations were detected without a transaction fact.",line:writes[0]?.line});return findings}function extractFileOntology(input){let moduleName=normalizeModuleName(input.moduleName),content=stripComments(input.content),roles=inferRoles(moduleName,content),routes=extractRoutes(moduleName,content),dataOperations=extractDataOperations(content),security=extractSecurityFacts(content),conventions=extractConventions(moduleName,roles,routes),findings=buildFindings(roles,routes,dataOperations,security);return{roles,packageBoundary:boundaryForModule(moduleName),routes,dataOperations,security,conventions,findings}}import{realpathSync as realpathSync15}from"node:fs";function safeRealpathSync(targetPath,fallback,realpathResolver=realpathSync15){try{return realpathResolver(targetPath)}catch(error93){if(error93 instanceof Error&&error93.code==="ENOENT")return fallback;return null}}import*as path141 from"node:path";var REPO_GRAPH_FILENAME="repo-graph.json",GRAPH_SCHEMA_VERSION="1.2.0";function isSchemaVersionAtLeast(version5,minimum){let parse10=(v)=>v.split(".").map((part)=>{let n=Number.parseInt(part,10);return Number.isFinite(n)?n:0}),a=parse10(version5??""),b=parse10(minimum),len=Math.max(a.length,b.length);for(let i=0;i<len;i++){let av=a[i]??0,bv=b[i]??0;if(av>bv)return!0;if(av<bv)return!1}return!0}var FILE_ROLE_VALUES=["api_route","middleware","service_module","data_module","swarm_tool","agent","hook","config","schema","test_file","cli_command","documentation","source_module"],ROUTE_METHOD_VALUES=["GET","POST","PUT","PATCH","DELETE","OPTIONS","HEAD","ALL"],ROUTE_SOURCE_VALUES=["file_path","handler_export","router_call"],DATA_OPERATION_VALUES=["read","write","delete","transaction","migration"],DATA_ACCESS_VALUES=["database","orm","sql","filesystem","network","unknown"],SECURITY_KIND_VALUES=["authentication","authorization","input_validation","csrf","sanitization","secret_handling"],SECURITY_CONFIDENCE_VALUES=["low","medium","high"],ONTOLOGY_FINDING_SEVERITY_VALUES=["info","low","medium","high"],IMPORT_TYPE_VALUES=["default","named","namespace","require","sideeffect","type"];function normalizeGraphPath(filePath){return path141.normalize(filePath).replace(/\\/g,"/")}function createEmptyGraph(workspaceRoot){return{schema_version:GRAPH_SCHEMA_VERSION,workspaceRoot:path141.normalize(workspaceRoot),nodes:{},edges:[],metadata:{generatedAt:new Date().toISOString(),generator:"repo-graph",nodeCount:0,edgeCount:0}}}function updateGraphMetadata(graph){graph.metadata={generatedAt:new Date().toISOString(),generator:"repo-graph",nodeCount:Object.keys(graph.nodes).length,edgeCount:graph.edges.length}}init_path_security();var FILE_ROLE_SET=new Set(FILE_ROLE_VALUES),ROUTE_METHOD_SET=new Set(ROUTE_METHOD_VALUES),ROUTE_SOURCE_SET=new Set(ROUTE_SOURCE_VALUES),DATA_OPERATION_SET=new Set(DATA_OPERATION_VALUES),DATA_ACCESS_SET=new Set(DATA_ACCESS_VALUES),SECURITY_KIND_SET=new Set(SECURITY_KIND_VALUES),SECURITY_CONFIDENCE_SET=new Set(SECURITY_CONFIDENCE_VALUES),ONTOLOGY_FINDING_SEVERITY_SET=new Set(ONTOLOGY_FINDING_SEVERITY_VALUES),IMPORT_TYPE_SET=new Set(IMPORT_TYPE_VALUES),ONTOLOGY_NAME_PATTERN=/^[a-z][a-z0-9_]*$/;function validateWorkspace(workspace){if(!workspace||typeof workspace!=="string"||workspace.trim()==="")throw Error("Invalid workspace: must be a non-empty string");if(containsControlChars(workspace))throw Error("Invalid workspace: control characters detected");if(containsPathTraversal(workspace))throw Error("Invalid workspace: path traversal detected")}function validateGraphNode(node){if(!node||typeof node!=="object")throw Error("Invalid node: must be an object");if(!node.filePath||typeof node.filePath!=="string")throw Error("Invalid node: filePath is required");if(!node.filePath.startsWith("/")&&!/^[A-Za-z]:[/\\]/.test(node.filePath))throw Error("Invalid node: filePath must be absolute");if(containsPathTraversal(node.filePath))throw Error("Invalid node: filePath contains path traversal");if(containsControlChars(node.filePath))throw Error("Invalid node: filePath contains control characters");if(!node.moduleName||typeof node.moduleName!=="string")throw Error("Invalid node: moduleName is required");if(node.moduleName.startsWith("/")||node.moduleName.startsWith("\\")||/^[A-Za-z]:[/\\]/.test(node.moduleName))throw Error("Invalid node: moduleName must be relative");if(containsPathTraversal(node.moduleName))throw Error("Invalid node: moduleName contains path traversal");if(containsControlChars(node.moduleName))throw Error("Invalid node: moduleName contains control characters");if(typeof node.language!=="string")throw Error("Invalid node: language is required");if(typeof node.mtime!=="string")throw Error("Invalid node: mtime is required");if(!Array.isArray(node.exports))throw Error("Invalid node: exports must be an array");for(let exp of node.exports){if(typeof exp!=="string")throw Error("Invalid node: exports must be an array of strings");if(containsControlChars(exp)){let preview=exp.slice(0,120);throw Error(`Invalid node: exports contains control characters (file=${node.filePath}, value="${preview}")`)}}if(!Array.isArray(node.imports))throw Error("Invalid node: imports must be an array");for(let imp of node.imports){if(typeof imp!=="string")throw Error("Invalid node: imports must be an array of strings");if(containsControlChars(imp)){let preview=imp.slice(0,120);throw Error(`Invalid node: imports contains control characters (file=${node.filePath}, value="${preview}")`)}}if(node.exportLines!==void 0){if(typeof node.exportLines!=="object"||node.exportLines===null||Array.isArray(node.exportLines))throw Error("Invalid node: exportLines must be an object");for(let[name,line]of Object.entries(node.exportLines)){if(containsControlChars(name))throw Error("Invalid node: exportLines key contains control characters");if(typeof line!=="number"||!Number.isFinite(line)||line<0)throw Error("Invalid node: exportLines values must be non-negative numbers")}}if(node.exportRanges!==void 0){if(typeof node.exportRanges!=="object"||node.exportRanges===null||Array.isArray(node.exportRanges))throw Error("Invalid node: exportRanges must be an object");for(let[name,range]of Object.entries(node.exportRanges)){if(containsControlChars(name))throw Error("Invalid node: exportRanges key contains control characters");if(typeof range!=="object"||range===null||Array.isArray(range))throw Error("Invalid node: exportRanges values must be objects");let r=range;if(typeof r.startLine!=="number"||!Number.isFinite(r.startLine)||!Number.isInteger(r.startLine)||r.startLine<1||typeof r.endLine!=="number"||!Number.isFinite(r.endLine)||!Number.isInteger(r.endLine)||r.endLine<1)throw Error("Invalid node: exportRanges value must have positive integer startLine and endLine (1-based)");if(r.startLine>r.endLine)throw Error("Invalid node: exportRanges value must have startLine <= endLine")}}if(node.ontology!==void 0)validateOntologyStrings(node)}function validateOntologyStrings(node){let ontology=node.ontology;if(!ontology||typeof ontology!=="object")throw Error("Invalid node: ontology must be an object");let values=[...ontology.roles??[],ontology.packageBoundary,...(ontology.routes??[]).flatMap((route)=>[route.method,route.path,route.source]),...(ontology.dataOperations??[]).flatMap((fact)=>[fact.operation,fact.access,fact.entity??"",fact.evidence]),...(ontology.security??[]).flatMap((fact)=>[fact.kind,fact.evidence,fact.confidence]),...(ontology.conventions??[]).flatMap((fact)=>[fact.name,fact.evidence]),...(ontology.findings??[]).flatMap((finding)=>[finding.code,finding.severity,finding.message])];for(let value of values){if(typeof value!=="string")throw Error("Invalid node: ontology contains non-string value");if(containsControlChars(value)){let preview=value.slice(0,120);throw Error(`Invalid node: ontology contains control characters (file=${node.filePath}, value="${preview}")`)}}for(let role of ontology.roles??[])validateAllowedOntologyValue(node,"ontology.roles",role,FILE_ROLE_SET);for(let route of ontology.routes??[])validateAllowedOntologyValue(node,"ontology.routes.method",route.method,ROUTE_METHOD_SET),validateAllowedOntologyValue(node,"ontology.routes.source",route.source,ROUTE_SOURCE_SET);for(let fact of ontology.dataOperations??[])validateAllowedOntologyValue(node,"ontology.dataOperations.operation",fact.operation,DATA_OPERATION_SET),validateAllowedOntologyValue(node,"ontology.dataOperations.access",fact.access,DATA_ACCESS_SET);for(let fact of ontology.security??[])validateAllowedOntologyValue(node,"ontology.security.kind",fact.kind,SECURITY_KIND_SET),validateAllowedOntologyValue(node,"ontology.security.confidence",fact.confidence,SECURITY_CONFIDENCE_SET);for(let finding of ontology.findings??[])validateOntologyName(node,"ontology.findings.code",finding.code),validateAllowedOntologyValue(node,"ontology.findings.severity",finding.severity,ONTOLOGY_FINDING_SEVERITY_SET)}function validateOntologyName(node,field,value){if(ONTOLOGY_NAME_PATTERN.test(value))return;let preview=value.slice(0,120);throw Error(`Invalid node: ${field} must be lower_snake_case (file=${node.filePath}, value="${preview}")`)}function validateAllowedOntologyValue(node,field,value,allowed){if(allowed.has(value))return;let preview=value.slice(0,120);throw Error(`Invalid node: ${field} contains invalid value (file=${node.filePath}, value="${preview}")`)}function validateGraphEdge(edge){if(!edge||typeof edge!=="object")throw Error("Invalid edge: must be an object");if(!edge.source||typeof edge.source!=="string")throw Error("Invalid edge: source is required");if(!edge.target||typeof edge.target!=="string")throw Error("Invalid edge: target is required");if(containsPathTraversal(edge.source)||containsPathTraversal(edge.target))throw Error("Invalid edge: path traversal detected");if(containsControlChars(edge.source)||containsControlChars(edge.target))throw Error("Invalid edge: control characters detected");if(!edge.importSpecifier||typeof edge.importSpecifier!=="string")throw Error("Invalid edge: importSpecifier is required");if(containsControlChars(edge.importSpecifier))throw Error("Invalid edge: importSpecifier contains control characters");if(!IMPORT_TYPE_SET.has(edge.importType))throw Error("Invalid edge: importType is invalid");if(edge.importedSymbols!==void 0){if(!Array.isArray(edge.importedSymbols))throw Error("Invalid edge: importedSymbols must be an array");for(let symbol3 of edge.importedSymbols){if(typeof symbol3!=="string")throw Error("Invalid edge: importedSymbols must be an array of strings");if(containsControlChars(symbol3))throw Error("Invalid edge: importedSymbols contains control characters")}}if(edge.usedSymbols!==void 0){if(!Array.isArray(edge.usedSymbols))throw Error("Invalid edge: usedSymbols must be an array");for(let symbol3 of edge.usedSymbols){if(typeof symbol3!=="string")throw Error("Invalid edge: usedSymbols must be an array of strings");if(containsControlChars(symbol3))throw Error("Invalid edge: usedSymbols contains control characters")}}}var _internals89={safeRealpathSync,extractTSSymbols,extractPythonSymbols,extractRustSymbols,extractGoSymbols,parseFileImports,extractFileOntology,stripComments:stripComments2,computeUsedSymbols,extractFileSymbols},SKIP_DIRECTORIES2=new Set(["node_modules",".git","dist","build","out","coverage",".next",".nuxt",".cache","vendor",".svn",".hg",".svelte-kit"]);function resolveSkipDirectories(excludeDirs){let extras=excludeDirs?.filter((d)=>d.length>0)??[];if(extras.length===0)return SKIP_DIRECTORIES2;return new Set([...SKIP_DIRECTORIES2,...extras])}var SUPPORTED_EXTENSIONS=new Set(LANGUAGE_REGISTRY.getAll().filter((p)=>!p.parserOnly).flatMap((p)=>p.extensions)),DEFAULT_WALK_FILE_CAP=1e4,DEFAULT_WALK_BUDGET_MS=5000,ASYNC_WALK_YIELD_INTERVAL=200,MAX_DIAGNOSTIC_ENTRIES=200,EXTENSION_TO_LANGUAGE={};for(let profile of LANGUAGE_REGISTRY.getAll()){if(profile.parserOnly)continue;for(let ext of profile.extensions)EXTENSION_TO_LANGUAGE[ext]=profile.treeSitter.grammarId}var JS_FAMILY_EXTENSION_TO_LANGUAGE={".js":"javascript",".jsx":"javascript",".mjs":"javascript",".cjs":"javascript",".ts":"typescript",".tsx":"tsx"};function upsertNode(graph,node){validateGraphNode(node);let key=normalizeGraphPath(node.filePath);graph.nodes[key]=node,updateGraphMetadata(graph)}function addEdge(graph,edge){if(validateGraphEdge(edge),!graph.edges.some((e)=>e.source===edge.source&&e.target===edge.target&&e.importSpecifier===edge.importSpecifier))graph.edges.push(edge),updateGraphMetadata(graph)}function buildLoopEdgeKey(edge){return`${edge.source}\x00${edge.target}\x00${edge.importSpecifier}`}function appendNodeFast(graph,node){validateGraphNode(node),graph.nodes[normalizeGraphPath(node.filePath)]=node}function appendEdgeFast(graph,edge,seenEdgeKeys){validateGraphEdge(edge);let key=buildLoopEdgeKey(edge);if(seenEdgeKeys.has(key))return;seenEdgeKeys.add(key),graph.edges.push(edge)}function resolveModuleSpecifier(workspaceRoot,sourceFile,specifier){if(containsControlChars(specifier))return null;if(specifier.startsWith("/")||specifier.startsWith("\\"))return null;if(/^[A-Za-z]:[/\\]/.test(specifier))return null;if(specifier.startsWith("http://")||specifier.startsWith("https://"))return null;try{let normalizedSpecifier=specifier,rustParts=specifier.split("::").filter(Boolean);if(rustParts[0]==="crate"){let target=path142.join(workspaceRoot,...rustParts.slice(1));if(!(existsSync80(target)||existsSync80(`${target}.rs`)||existsSync80(path142.join(target,"mod.rs"))))target=path142.join(path142.dirname(sourceFile),...rustParts.slice(1));if(normalizedSpecifier=path142.relative(path142.dirname(sourceFile),target).replace(/\\/g,"/"),!normalizedSpecifier.startsWith("."))normalizedSpecifier=`./${normalizedSpecifier}`}else if(rustParts[0]==="self")normalizedSpecifier=`./${rustParts.slice(1).join("/")}`;else if(rustParts[0]==="super"){let superCount=0;while(rustParts[superCount]==="super")superCount++;normalizedSpecifier=`${"../".repeat(superCount)}${rustParts.slice(superCount).join("/")}`}if(normalizedSpecifier.startsWith(".")){let sourceDir=path142.dirname(sourceFile),resolved=path142.resolve(sourceDir,normalizedSpecifier),initialRealResolved=_internals89.safeRealpathSync(resolved,resolved);if(initialRealResolved===null)return null;let realResolved=initialRealResolved,realRoot=_internals89.safeRealpathSync(workspaceRoot,path142.normalize(workspaceRoot));if(realRoot===null)return null;let findDirectoryEntry=(directory)=>{for(let initName of["__init__.py","__init__.pyw","mod.rs"]){let candidate=path142.join(directory,initName);if(existsSync80(candidate))return candidate}if(path142.extname(sourceFile).toLowerCase()===".go"){let basenameCandidate=path142.join(directory,`${path142.basename(directory)}.go`);if(existsSync80(basenameCandidate))return basenameCandidate;try{let firstGo=fsSync9.readdirSync(directory).filter((entry)=>entry.endsWith(".go")&&!entry.endsWith("_test.go")).sort((a,b)=>a.localeCompare(b))[0];if(firstGo)return path142.join(directory,firstGo)}catch{return null}}return null};if(existsSync80(resolved))try{if(fsSync9.statSync(resolved).isDirectory()){let found=findDirectoryEntry(resolved);if(!found)return null;let foundRealPath=_internals89.safeRealpathSync(found,found);if(foundRealPath===null)return null;realResolved=foundRealPath,resolved=found}}catch{return null}if(!existsSync80(resolved)){let EXTENSIONS=path142.extname(sourceFile).toLowerCase()===".pyw"?[".pyw",".py",".rs",".go",".ts",".tsx",".js",".jsx",".mjs",".cjs",".json"]:[".ts",".tsx",".js",".jsx",".mjs",".cjs",".py",".pyw",".rs",".go",".json"],found=null;for(let ext of EXTENSIONS){let candidate=resolved+ext;if(existsSync80(candidate)){found=candidate;break}}if(!found)found=findDirectoryEntry(resolved);if(found){let foundRealPath=_internals89.safeRealpathSync(found,found);if(foundRealPath===null)return null;realResolved=foundRealPath,resolved=found}else return null}let normalizedResolved=path142.normalize(realResolved),normalizedRoot=path142.normalize(realRoot);if(!normalizedResolved.startsWith(normalizedRoot+path142.sep)&&normalizedResolved!==normalizedRoot)return null;return resolved}return null}catch{return null}}function isRefusedWorkspaceRoot(target){let resolved;try{resolved=realpathSync16(target)}catch{resolved=path142.resolve(target)}let refused=new Set,add2=(p)=>{if(typeof p==="string"&&p.length>0)refused.add(path142.resolve(p))};if(add2(os21.homedir()),add2(os21.tmpdir()),add2("/"),add2("/Users"),add2("/home"),add2("/root"),process.platform==="win32")add2("C:\\"),add2("C:\\Users");return refused.has(resolved)}function createEmptyDiagnostics(){return{extractionFailures:[],unresolvedImports:[],oversizedFiles:[],unsupportedFiles:[],binaryFiles:[],unreadableFiles:[],lowConfidenceEdgeCount:0}}function diagnosticsHaveEntries(diagnostics){return(diagnostics.extractionFailures?.length??0)>0||(diagnostics.unresolvedImports?.length??0)>0||(diagnostics.oversizedFiles?.length??0)>0||(diagnostics.unsupportedFiles?.length??0)>0||(diagnostics.binaryFiles?.length??0)>0||(diagnostics.unreadableFiles?.length??0)>0||(diagnostics.lowConfidenceEdgeCount??0)>0}function pushCapped(target,value){if(target.length<MAX_DIAGNOSTIC_ENTRIES)target.push(value)}function mergeDiagnostics(target,source){if(!source)return;for(let entry of source.extractionFailures??[])pushCapped(target.extractionFailures,entry);for(let entry of source.unresolvedImports??[])pushCapped(target.unresolvedImports,entry);for(let entry of source.oversizedFiles??[])pushCapped(target.oversizedFiles,entry);for(let entry of source.unsupportedFiles??[])pushCapped(target.unsupportedFiles,entry);for(let entry of source.binaryFiles??[])pushCapped(target.binaryFiles,entry);for(let entry of source.unreadableFiles??[])pushCapped(target.unreadableFiles,entry);target.lowConfidenceEdgeCount+=source.lowConfidenceEdgeCount??0}function isRelativeImportSpecifier(specifier){return specifier==="."||specifier===".."||specifier.startsWith("./")||specifier.startsWith("../")}function unresolvedRelativeImportsFor(parsedImports,filePath,absoluteRoot){let unresolved=[],moduleName=toModuleName(filePath,absoluteRoot);for(let parsed of parsedImports){if(!isRelativeImportSpecifier(parsed.specifier))continue;if(resolveModuleSpecifier(absoluteRoot,filePath,parsed.specifier)===null)unresolved.push({file:moduleName,specifier:parsed.specifier})}return unresolved}var REGEX_ALLOWED_AFTER=new Set("(,=:[!&|?{};*+-~^<>%".split(""));function stripComments2(content){let out="",i=0,n=content.length,state="code",prevSignificant="",regexInClass=!1;while(i<n){let ch=content[i],next=i+1<n?content[i+1]:"";switch(state){case"code":if(ch==="/"&&next==="/")state="line",i+=2;else if(ch==="/"&&next==="*")state="block",i+=2;else if(ch==="/"&®EX_ALLOWED_AFTER.has(prevSignificant))state="regex",regexInClass=!1,out+=ch,i+=1;else{if(ch==="'")state="single";else if(ch==='"')state="double";else if(ch==="`")state="template";if(out+=ch,ch.trim()!=="")prevSignificant=ch;i+=1}break;case"single":case"double":case"template":{let quote=state==="single"?"'":state==="double"?'"':"`";if(ch==="\\")out+=ch+next,i+=2;else{if(ch===quote)state="code",prevSignificant=quote;out+=ch,i+=1}break}case"regex":if(ch==="\\")out+=ch+next,i+=2;else if(ch===`
|
|
5474
5474
|
`)state="code",out+=ch,i+=1;else{if(ch==="[")regexInClass=!0;else if(ch==="]")regexInClass=!1;else if(ch==="/"&&!regexInClass)state="code",prevSignificant="/";out+=ch,i+=1}break;case"line":if(ch===`
|
|
5475
5475
|
`)state="code",out+=ch;i+=1;break;case"block":if(ch==="*"&&next==="/")state="code",i+=2;else{if(ch===`
|
|
5476
5476
|
`)out+=ch;i+=1}break}}return out}function parseFileImports(rawContent,sourceFile,workspaceRoot){let ext=sourceFile?path142.extname(sourceFile).toLowerCase():"";if(ext===".py"||ext===".pyw")return parsePythonFileImports(rawContent,sourceFile);if(ext===".rs")return parseRustFileImports(rawContent,sourceFile,workspaceRoot);if(ext===".go")return parseGoFileImports(rawContent);let imports=[],content=stripComments2(rawContent),importRegex=/import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`\0\t\r\n]+)['"`]|import\s+['"`]([^'"`\0\t\r\n]+)['"`]|require\s*\(\s*['"`]([^'"`\0\t\r\n]+)['"`]\s*\)|export\s*\{[^}]*\}\s*from\s+['"`]([^'"`\0\t\r\n]+)['"`]|export\s+\*(?:\s+as\s+\w+)?\s+from\s+['"`]([^'"`\0\t\r\n]+)['"`]|import\s*\(\s*['"`]([^'"`\0\t\r\n]+)['"`]\s*\)/g;for(let match of content.matchAll(importRegex)){let modulePath=match[1]||match[2]||match[3]||match[4]||match[5]||match[6];if(!modulePath)continue;if(containsControlChars(modulePath))continue;let matchedString=match[0],importType="named";if(matchedString.includes("* as"))importType="namespace";else if(/^import\s*\(/.test(matchedString))importType="sideeffect";else if(/^export\s*\{/.test(matchedString))importType="named";else if(/^export\s+\*/.test(matchedString))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";imports.push({specifier:modulePath,importType,importedSymbols:parseImportedSymbols(matchedString,importType),bindings:parseImportBindings(matchedString,importType),reExport:/^\s*export\b/.test(matchedString)})}return imports}function makeParsedImport(specifier,importType,bindings,reExport=!1){if(!specifier||containsControlChars(specifier))return null;return{specifier,importType,importedSymbols:bindings.map((binding)=>binding.imported),bindings,reExport}}function parsePythonFileImports(rawContent,sourceFile){let imports=[],isPackageInit=sourceFile?["__init__.py","__init__.pyw"].includes(path142.basename(sourceFile)):!1;for(let line of rawContent.split(/\r?\n/)){let trimmed=line.trim();if(!trimmed||trimmed.startsWith("#"))continue;let fullImport=trimmed.match(/^import\s+(.+?)(?:\s*#.*)?$/);if(fullImport){for(let rawPart of fullImport[1].split(",")){let part=rawPart.trim();if(!part)continue;let alias=part.match(/^([\w.]+)\s+as\s+(\w+)$/),specifier=alias?alias[1]:part,local=alias?alias[2]:specifier.split(".")[0];if(!/^\w+$/.test(local))continue;let parsed2=makeParsedImport(specifier,"namespace",[{imported:specifier,local}]);if(parsed2)imports.push(parsed2)}continue}let fromImport=trimmed.match(/^from\s+(\S+)\s+import\s+(.+?)(?:\s*#.*)?$/);if(!fromImport)continue;if(fromImport[2].trim()==="*"){let parsed2=makeParsedImport(normalizePythonModuleSpecifier2(fromImport[1]),"namespace",[],isPackageInit);if(parsed2)imports.push(parsed2);continue}let bindings=[];for(let rawPart of fromImport[2].split(",")){let part=rawPart.trim();if(!part)continue;let alias=part.match(/^(\w+)\s+as\s+(\w+)$/);if(alias)bindings.push({imported:alias[1],local:alias[2]});else if(/^\w+$/.test(part))bindings.push({imported:part,local:part})}let parsed=makeParsedImport(normalizePythonModuleSpecifier2(fromImport[1]),"named",bindings,isPackageInit);if(parsed)imports.push(parsed)}return imports}function normalizePythonModuleSpecifier2(specifier){let leadingDots=specifier.match(/^\.+/)?.[0].length??0;if(leadingDots===0)return specifier;let rest=specifier.slice(leadingDots).replace(/\./g,"/");return`${leadingDots===1?"./":"../".repeat(leadingDots-1)}${rest}`}function rustModulePathToSpecifier(modulePath,sourceFile,workspaceRoot){let parts=modulePath.split("::").filter(Boolean);if(parts.length===0)return modulePath;if(parts[0]==="self")return`./${parts.slice(1).join("/")}`;if(parts[0]==="super"){let superCount=0;while(parts[superCount]==="super")superCount++;return`${"../".repeat(superCount)}${parts.slice(superCount).join("/")}`}if(parts[0]==="crate"&&sourceFile&&workspaceRoot){let target=path142.join(workspaceRoot,...parts.slice(1)),relative22=path142.relative(path142.dirname(sourceFile),target).replace(/\\/g,"/");if(!relative22.startsWith("."))relative22=`./${relative22}`;return relative22}return modulePath}function parseRustFileImports(rawContent,sourceFile,workspaceRoot){let imports=[];for(let line of rawContent.split(/\r?\n/)){let trimmed=line.trim();if(!trimmed.startsWith("use "))continue;let grouped=trimmed.match(/^use\s+(.+?)::\{(.+)\}\s*;?\s*$/);if(grouped){let specifier2=rustModulePathToSpecifier(grouped[1].trim(),sourceFile,workspaceRoot),bindings=[];for(let rawPart of grouped[2].split(",")){let part=rawPart.trim();if(!part)continue;let alias2=part.match(/^(\w+)\s+as\s+(\w+)$/);if(alias2)bindings.push({imported:alias2[1],local:alias2[2]});else if(/^\w+$/.test(part)){let local2=part==="self"?grouped[1].split("::").pop()||grouped[1]:part;bindings.push({imported:part,local:local2})}}let parsed2=makeParsedImport(specifier2,"named",bindings);if(parsed2)imports.push(parsed2);continue}let simple=trimmed.match(/^use\s+(.+?)\s*;?\s*$/);if(!simple)continue;let rawPath=simple[1].trim(),alias=rawPath.match(/^(.+?)\s+as\s+(\w+)$/),fullPath=(alias?alias[1]:rawPath).trim(),parts=fullPath.split("::").filter(Boolean),imported=parts.pop()??fullPath,specifier=rustModulePathToSpecifier(parts.join("::")||fullPath,sourceFile,workspaceRoot),local=alias?alias[2]:imported,parsed=makeParsedImport(specifier,"named",/^\w+$/.test(imported)&&/^\w+$/.test(local)?[{imported,local}]:[]);if(parsed)imports.push(parsed)}return imports}function parseGoFileImports(rawContent){let imports=[],content=stripComments2(rawContent),parseSpec=(text)=>{let spec=text.trim();if(!spec)return;let aliased=spec.match(/^([\w._]+)\s+["`]([^"`]+)["`]$/);if(aliased){if(aliased[1]==="_"){let parsed2=makeParsedImport(aliased[2],"sideeffect",[]);if(parsed2)imports.push(parsed2);return}if(aliased[1]==="."){let parsed2=makeParsedImport(aliased[2],"namespace",[{imported:"*",local:"."}]);if(parsed2)imports.push(parsed2);return}let parsed=makeParsedImport(aliased[2],"named",[{imported:aliased[2],local:aliased[1]}]);if(parsed)imports.push(parsed);return}let simple=spec.match(/^["`]([^"`]+)["`]$/);if(simple){let parsed=makeParsedImport(simple[1],"namespace",[]);if(parsed)imports.push(parsed)}};for(let block of content.matchAll(/import\s*\(([\s\S]*?)\)/g))for(let line of block[1].split(/\r?\n/))parseSpec(line);let withoutBlocks=content.replace(/import\s*\([\s\S]*?\)/g,"");for(let match of withoutBlocks.matchAll(/^\s*import\s+(.+)$/gm))parseSpec(match[1]);return imports}function parseImportBindings(matchedString,importType){if(importType==="namespace")return[];if(importType==="default"){let defaultMatch=matchedString.match(/^import\s+(\w+)\s+from\s+['"`]/);return defaultMatch?[{imported:"default",local:defaultMatch[1]}]:[]}if(importType!=="named")return[];let braceMatch=matchedString.match(/\{\s*([\s\S]*?)\s*\}/);if(!braceMatch)return[];let bindings=[],seen=new Set;for(let rawPart of braceMatch[1].split(",")){let part=rawPart.trim().replace(/^type\s+/,"");if(!part)continue;let aliasSplit=part.split(/\s+as\s+/i),imported=aliasSplit[0].trim(),local=(aliasSplit[1]??aliasSplit[0]).trim();if(!/^[A-Za-z_$][\w$]*$/.test(imported))continue;if(!/^[A-Za-z_$][\w$]*$/.test(local))continue;if(seen.has(imported))continue;seen.add(imported),bindings.push({imported,local})}return bindings}var SAFE_USAGE_IDENTIFIER=/^[A-Za-z_][A-Za-z0-9_]*$/;function computeUsedSymbols(strippedContent,bindings){if(bindings.length===0)return[];let used=new Set;for(let binding of bindings){if(!SAFE_USAGE_IDENTIFIER.test(binding.local)){used.add(binding.imported);continue}let re=new RegExp(`\\b${binding.local}\\b`,"g"),count=0;for(let _match of strippedContent.matchAll(re))if(count++,count>1)break;if(count>1)used.add(binding.imported)}return[...used].sort((a,b)=>a.localeCompare(b))}function usedSymbolsForImport(parsed,strippedContent){if(parsed.importType==="namespace"||parsed.importType==="sideeffect"||parsed.importType==="require")return;if(parsed.reExport)return[...new Set(parsed.bindings.map((b)=>b.imported))].sort((a,b)=>a.localeCompare(b));return computeUsedSymbols(strippedContent,parsed.bindings)}function collectExports(symbols2){let exported=symbols2.filter((s)=>s.exported),exports=exported.map((s)=>s.signature===`default ${s.name}`?"default":s.name),exportLines={};for(let i=0;i<exported.length;i++){let s=exported[i],name=exports[i];if(typeof s.line==="number"&&Number.isFinite(s.line)&&exportLines[name]===void 0)exportLines[name]=s.line}return{exports,exportLines}}function parseImportedSymbols(matchedString,importType){if(importType==="namespace")return["*"];if(importType==="default")return matchedString.match(/^import\s+(\w+)\s+from\s+['"`]/)?["default"]:[];if(importType!=="named")return[];let braceMatch=matchedString.match(/\{\s*([\s\S]*?)\s*\}/);if(!braceMatch)return[];let symbols2=new Set;for(let rawPart of braceMatch[1].split(",")){let part=rawPart.trim();if(!part)continue;let cleaned=part.replace(/^type\s+/,"").split(/\s+as\s+/i)[0].trim();if(/^[A-Za-z_$][\w$]*$/.test(cleaned))symbols2.add(cleaned)}return[...symbols2].sort((a,b)=>a.localeCompare(b))}function isWalkBudgetExceeded(ctx){if(ctx.abortReason!==void 0)return!0;if(Date.now()-ctx.startedAt>ctx.walkBudgetMs)return ctx.abortReason="budget",!0;return!1}function isFileCapReached(ctx,filesLength){if(filesLength>=ctx.maxFiles)return ctx.abortReason="cap",!0;return!1}async function canonicalDirKeyAsync(dir){try{return await fsPromises5.realpath(dir)}catch{return null}}async function findSourceFilesAsync(dir,stats2,options){let ctx={stats:stats2,seenRealPaths:new Set,startedAt:Date.now(),walkBudgetMs:options?.walkBudgetMs??DEFAULT_WALK_BUDGET_MS,maxFiles:options?.maxFiles??DEFAULT_WALK_FILE_CAP,followSymlinks:options?.followSymlinks??!1,skipDirs:resolveSkipDirectories(options?.excludeDirs)},files=[],queue=[dir],processed=0;while(queue.length>0){if(isWalkBudgetExceeded(ctx)||isFileCapReached(ctx,files.length))break;let current=queue.shift(),key=await canonicalDirKeyAsync(current);if(key!==null){if(ctx.seenRealPaths.has(key)){ctx.stats.skippedDirs++;continue}ctx.seenRealPaths.add(key)}let entries;try{entries=await fsPromises5.readdir(current,{withFileTypes:!0})}catch{continue}entries.sort((a,b)=>a.name.toLowerCase().localeCompare(b.name.toLowerCase()));for(let entry of entries){if(isWalkBudgetExceeded(ctx)||isFileCapReached(ctx,files.length))break;if(ctx.skipDirs.has(entry.name)){ctx.stats.skippedDirs++;continue}let fullPath=path142.join(current,entry.name);if(entry.isSymbolicLink()&&!ctx.followSymlinks){ctx.stats.skippedDirs++;continue}if(entry.isDirectory())queue.push(fullPath);else if(entry.isFile()){let ext=path142.extname(fullPath).toLowerCase();if(SUPPORTED_EXTENSIONS.has(ext))files.push(fullPath)}if(processed++,processed%ASYNC_WALK_YIELD_INTERVAL===0)await yieldToEventLoop()}}if(ctx.abortReason==="cap"||ctx.abortReason==="budget")ctx.stats.truncated=!0;return files}function toModuleName(filePath,workspaceRoot){return path142.relative(workspaceRoot,filePath).split(path142.sep).join("/")}function getLanguage(filePath){let ext=path142.extname(filePath).toLowerCase(),jsFamilyLanguage=JS_FAMILY_EXTENSION_TO_LANGUAGE[ext];if(jsFamilyLanguage)return jsFamilyLanguage;return EXTENSION_TO_LANGUAGE[ext]??"unknown"}function isBinaryContent(content){if(content.includes("\x00"))return!0;return!1}function scanFile(filePath,absoluteRoot,maxFileSize){let content,fileStats;try{if(fileStats=fsSync9.statSync(filePath),fileStats.size>maxFileSize)return{node:null,edges:[]};content=fsSync9.readFileSync(filePath,"utf-8")}catch{return{node:null,edges:[]}}if(isBinaryContent(content))return{node:null,edges:[]};let ext=path142.extname(filePath).toLowerCase(),exports=[],exportLines={};try{if([".ts",".tsx",".js",".jsx",".mjs",".cjs"].includes(ext)){let relativePath=path142.relative(absoluteRoot,filePath);({exports,exportLines}=collectExports(_internals89.extractTSSymbols(relativePath,absoluteRoot)))}else if(ext===".py"||ext===".pyw"){let relativePath=path142.relative(absoluteRoot,filePath);({exports,exportLines}=collectExports(_internals89.extractPythonSymbols(relativePath,absoluteRoot)))}else if(ext===".rs"){let relativePath=path142.relative(absoluteRoot,filePath);({exports,exportLines}=collectExports(_internals89.extractRustSymbols(relativePath,absoluteRoot)))}else if(ext===".go"){let relativePath=path142.relative(absoluteRoot,filePath);({exports,exportLines}=collectExports(_internals89.extractGoSymbols(relativePath,absoluteRoot)))}let parsedImports=_internals89.parseFileImports(content,filePath,absoluteRoot),strippedForUsage=parsedImports.length>0?_internals89.stripComments(content):"",moduleName=toModuleName(filePath,absoluteRoot),node={filePath,moduleName,exports,...Object.keys(exportLines).length>0?{exportLines}:{},imports:parsedImports.map((p)=>p.specifier),language:getLanguage(filePath),mtime:fileStats.mtime.toISOString(),ontology:_internals89.extractFileOntology({moduleName,filePath,content,language:getLanguage(filePath),exports,imports:parsedImports.map((p)=>p.specifier)})},edges=[],sortedImports=[...parsedImports].sort((a,b)=>a.specifier.localeCompare(b.specifier));for(let parsed of sortedImports){let resolvedTarget=resolveModuleSpecifier(absoluteRoot,filePath,parsed.specifier);if(resolvedTarget!==null){let usedSymbols=usedSymbolsForImport(parsed,strippedForUsage);edges.push({source:filePath,target:resolvedTarget,importSpecifier:parsed.specifier,importType:parsed.importType,importedSymbols:parsed.importedSymbols,...usedSymbols!==void 0?{usedSymbols}:{}})}}return{node,edges}}catch{return{node:null,edges:[]}}}async function scanFileAsync(filePath,absoluteRoot,maxFileSize){let content,fileStats;try{if(fileStats=fsSync9.statSync(filePath),fileStats.size>maxFileSize)return{node:null,edges:[],symbolEdges:[],diagnostics:{oversizedFiles:[toModuleName(filePath,absoluteRoot)]}};content=fsSync9.readFileSync(filePath,"utf-8")}catch{return{node:null,edges:[],symbolEdges:[],diagnostics:{unreadableFiles:[toModuleName(filePath,absoluteRoot)]}}}if(isBinaryContent(content))return{node:null,edges:[],symbolEdges:[],diagnostics:{binaryFiles:[toModuleName(filePath,absoluteRoot)]}};let grammarId=getLanguage(filePath),facts=await _internals89.extractFileSymbols(grammarId,content);if(facts===null){let fallback=scanFile(filePath,absoluteRoot,maxFileSize),parsedImports=[];try{parsedImports=_internals89.parseFileImports(content,filePath,absoluteRoot)}catch{parsedImports=[]}return{...fallback,symbolEdges:[],diagnostics:{extractionFailures:[{file:toModuleName(filePath,absoluteRoot),language:grammarId,reason:"symbol_extraction_failed"}],unresolvedImports:unresolvedRelativeImportsFor(parsedImports,filePath,absoluteRoot)}}}let exportedDefs=facts.defs.filter((d)=>d.exported),exports=exportedDefs.map((d)=>d.name),exportLines={},exportRanges={};for(let d of exportedDefs)exportLines[d.name]=d.startLine,exportRanges[d.name]={startLine:d.startLine,endLine:d.endLine};let exportsSet=new Set(exports),isPythonPackageInit=grammarId==="python"&&["__init__.py","__init__.pyw"].includes(path142.basename(filePath));for(let imp of facts.imports){let packageInitBindings=isPythonPackageInit&&imp.bindings.length>0?imp.bindings.filter((binding)=>!binding.local.startsWith("_")).map((binding)=>({imported:binding.imported,exported:binding.local})):[],exportedBindings=imp.reExport&&imp.exportedBindings?imp.exportedBindings:packageInitBindings;if(exportedBindings.length===0)continue;for(let binding of exportedBindings){if(binding.imported==="*"){if(!exportsSet.has(binding.exported))exportsSet.add(binding.exported),exports.push(binding.exported);if(imp.startLine!==void 0&&exportLines[binding.exported]===void 0)exportLines[binding.exported]=imp.startLine;if(imp.startLine!==void 0&&imp.endLine!==void 0&&exportRanges[binding.exported]===void 0)exportRanges[binding.exported]={startLine:imp.startLine,endLine:imp.endLine};continue}if(!exportsSet.has(binding.exported))exportsSet.add(binding.exported),exports.push(binding.exported);if(imp.startLine!==void 0&&exportLines[binding.exported]===void 0)exportLines[binding.exported]=imp.startLine;if(imp.startLine!==void 0&&imp.endLine!==void 0&&exportRanges[binding.exported]===void 0)exportRanges[binding.exported]={startLine:imp.startLine,endLine:imp.endLine}}}let imports=facts.imports.map((i)=>i.specifier),moduleName=toModuleName(filePath,absoluteRoot),language=grammarId,node={filePath,moduleName,exports,...Object.keys(exportLines).length>0?{exportLines}:{},...Object.keys(exportRanges).length>0?{exportRanges}:{},imports,language,mtime:fileStats.mtime.toISOString(),ontology:_internals89.extractFileOntology({moduleName,filePath,content,language,exports,imports})},edges=[],sortedImports=[...facts.imports].sort((a,b)=>a.specifier.localeCompare(b.specifier));for(let imp of sortedImports){let edgeImportType=imp.importType==="commonjs"?"require":imp.importType,resolvedTarget=resolveModuleSpecifier(absoluteRoot,filePath,imp.specifier);if(resolvedTarget!==null){let usedBindings=imp.reExport?imp.bindings:imp.bindings.filter((b)=>facts.refs.some((r)=>r.identifier===b.local)),usedSymbols=edgeImportType!=="namespace"&&edgeImportType!=="require"&&edgeImportType!=="sideeffect"?usedBindings.map((b)=>b.imported):void 0;edges.push({source:filePath,target:resolvedTarget,importSpecifier:imp.specifier,importType:edgeImportType,importedSymbols:imp.bindings.map((b)=>b.imported),...usedSymbols!==void 0?{usedSymbols}:{}})}}let unresolvedImports=sortedImports.filter((imp)=>isRelativeImportSpecifier(imp.specifier)).filter((imp)=>resolveModuleSpecifier(absoluteRoot,filePath,imp.specifier)===null).map((imp)=>({file:moduleName,specifier:imp.specifier})),symbolEdges=[],localToImported=new Map;for(let imp of facts.imports){if(imp.reExport)continue;for(let binding of imp.bindings)localToImported.set(binding.local,{specifier:imp.specifier,imported:binding.imported})}let seenSymbolEdgeKeys=new Set;for(let ref of facts.refs){let mapping=localToImported.get(ref.identifier);if(!mapping)continue;let resolvedTarget=resolveModuleSpecifier(absoluteRoot,filePath,mapping.specifier);if(!resolvedTarget)continue;let fromSymbol=ref.enclosingDecl??"<module>",key=filePath+"\x00"+fromSymbol+"\x00"+resolvedTarget+"\x00"+mapping.imported;if(seenSymbolEdgeKeys.has(key))continue;seenSymbolEdgeKeys.add(key),symbolEdges.push({fromFile:filePath,fromSymbol,toFile:resolvedTarget,toSymbol:mapping.imported})}for(let imp of facts.imports){let packageInitBindings=isPythonPackageInit&&imp.bindings.length>0?imp.bindings.filter((binding)=>!binding.local.startsWith("_")).map((binding)=>({imported:binding.imported,exported:binding.local})):[],exportedBindings=imp.reExport&&imp.exportedBindings?imp.exportedBindings:packageInitBindings;if(exportedBindings.length===0)continue;let resolvedTarget=resolveModuleSpecifier(absoluteRoot,filePath,imp.specifier);if(!resolvedTarget)continue;for(let binding of exportedBindings){if(binding.imported==="*")continue;let key=filePath+"\x00"+binding.exported+"\x00"+resolvedTarget+"\x00"+binding.imported;if(seenSymbolEdgeKeys.has(key))continue;seenSymbolEdgeKeys.add(key),symbolEdges.push({fromFile:filePath,fromSymbol:binding.exported,toFile:resolvedTarget,toSymbol:binding.imported})}}return{node,edges,symbolEdges,diagnostics:unresolvedImports.length>0?{unresolvedImports}:void 0}}async function buildWorkspaceGraphAsync(workspaceRoot,options){validateWorkspace(workspaceRoot);let maxFileSize=options?.maxFileSizeBytes??1048576,maxFiles=options?.maxFiles??DEFAULT_WALK_FILE_CAP,walkBudgetMs=options?.walkBudgetMs??DEFAULT_WALK_BUDGET_MS,followSymlinks=options?.followSymlinks??!1,absoluteRoot=path142.resolve(workspaceRoot);if(!existsSync80(absoluteRoot))throw Error(`Workspace directory does not exist: ${workspaceRoot}`);if(isRefusedWorkspaceRoot(absoluteRoot))throw Error(`Refusing to scan top-level system path as workspace: ${absoluteRoot}. Set workspaceRoot to a project directory.`);let graph=createEmptyGraph(workspaceRoot),stats2={filesScanned:0,skippedDirs:0,skippedFiles:0,truncated:!1},diagnostics=createEmptyDiagnostics(),sourceFiles=await findSourceFilesAsync(absoluteRoot,stats2,{walkBudgetMs,maxFiles,followSymlinks,excludeDirs:options?.excludeDirs});if(sourceFiles.sort((a,b)=>{let normA=normalizeGraphPath(a),normB=normalizeGraphPath(b);return normA.localeCompare(normB)}),stats2.truncated)warn(`[repo-graph] Walk truncated: collected ${sourceFiles.length} files within ${walkBudgetMs}ms / ${maxFiles}-file budget.`);let seenEdges=new Set,seenSymbolEdges=new Set,allSymbolEdges=[],processedSinceYield=0;for(let filePath of sourceFiles){let result=await scanFileAsync(filePath,absoluteRoot,maxFileSize);if(mergeDiagnostics(diagnostics,result.diagnostics),result.node){let appended=!1;try{appendNodeFast(graph,result.node),appended=!0}catch{stats2.skippedFiles++}if(appended){for(let edge of result.edges)try{appendEdgeFast(graph,edge,seenEdges)}catch{}for(let symbolEdge of result.symbolEdges){let key=symbolEdge.fromFile+"\x00"+symbolEdge.fromSymbol+"\x00"+symbolEdge.toFile+"\x00"+symbolEdge.toSymbol;if(!seenSymbolEdges.has(key))seenSymbolEdges.add(key),allSymbolEdges.push(symbolEdge)}stats2.filesScanned++}}else stats2.skippedFiles++;if(processedSinceYield++,processedSinceYield%ASYNC_WALK_YIELD_INTERVAL===0)await yieldToEventLoop()}if(graph.metadata={generatedAt:new Date().toISOString(),generator:"repo-graph",nodeCount:Object.keys(graph.nodes).length,edgeCount:graph.edges.length},allSymbolEdges.length>0)graph.symbolEdges=allSymbolEdges;if(graph.diagnostics=diagnosticsHaveEntries(diagnostics)?diagnostics:createEmptyDiagnostics(),stats2.skippedFiles>0||stats2.skippedDirs>0||stats2.truncated)log(`[repo-graph] Scan stats: ${stats2.filesScanned} files scanned, ${stats2.skippedFiles} files skipped, ${stats2.skippedDirs} dirs skipped`+(stats2.truncated?", TRUNCATED":""));return graph}import*as path143 from"node:path";var graphCache=new Map,dirtyFlags=new Map,mtimeCache=new Map;function getCachedGraph(workspace){return graphCache.get(path143.normalize(workspace))}function setCachedGraph(workspace,graph,mtime){let normalized=path143.normalize(workspace);if(graphCache.set(normalized,graph),dirtyFlags.set(normalized,!1),mtime!==void 0)mtimeCache.set(normalized,mtime)}function isDirty(workspace){return dirtyFlags.get(path143.normalize(workspace))??!1}function clearCache(workspace){let normalized=path143.normalize(workspace);graphCache.delete(normalized),dirtyFlags.delete(normalized),mtimeCache.delete(normalized)}function getCachedMtime(workspace){return mtimeCache.get(path143.normalize(workspace))}init_logger();init_path_security();import{existsSync as existsSync82}from"node:fs";import*as fsPromises7 from"node:fs/promises";import*as path146 from"node:path";init_path_security();import*as fsSync10 from"node:fs";import*as path144 from"node:path";var GRAPH_HEALTH_OUTPUT_LIMIT=50,MAX_HEALTH_PATH_LENGTH=500,cachedReverseIndex=null;function normalizeLookupPath(input){return normalizeGraphPath(input).replace(/^(?:\.\/)+/,"")}function graphRoot(graph){return path144.resolve(graph.workspaceRoot)}function toModuleName2(graph,input){let normalized=normalizeLookupPath(input);if(path144.isAbsolute(normalized)||/^[A-Za-z]:\//.test(normalized))return normalizeLookupPath(path144.relative(graphRoot(graph),normalized));return normalized}function absoluteKeyForModule(graph,moduleName){return normalizeGraphPath(path144.resolve(graphRoot(graph),moduleName))}function getGraphNode(graph,input){let moduleName=toModuleName2(graph,input),direct=graph.nodes[absoluteKeyForModule(graph,moduleName)];if(direct)return direct;return getQueryIndexes(graph).moduleNameIndex.get(moduleName)}function moduleNameForEdgePath(graph,edgePath){let key=normalizeGraphPath(edgePath),node=graph.nodes[key];if(node)return normalizeLookupPath(node.moduleName);return normalizeLookupPath(path144.relative(graphRoot(graph),edgePath))}function buildReverseIndex(graph){let reverse=new Map,forward=new Map,moduleNameIndex=new Map;for(let node of Object.values(graph.nodes))moduleNameIndex.set(normalizeLookupPath(node.moduleName),node);for(let edge of graph.edges){let source=normalizeGraphPath(edge.source),target=normalizeGraphPath(edge.target),sourceRef={file:moduleNameForEdgePath(graph,edge.source),importType:edge.importType},targetRef={file:moduleNameForEdgePath(graph,edge.target),importType:edge.importType},reverseRefs=reverse.get(target);if(reverseRefs)reverseRefs.push(sourceRef);else reverse.set(target,[sourceRef]);let forwardRefs=forward.get(source);if(forwardRefs)forwardRefs.push(targetRef);else forward.set(source,[targetRef])}for(let refs of reverse.values())refs.sort((a,b)=>a.file.localeCompare(b.file));for(let refs of forward.values())refs.sort((a,b)=>a.file.localeCompare(b.file));return cachedReverseIndex={graph,index:reverse,forwardIndex:forward,moduleNameIndex},reverse}function getQueryIndexes(graph){if(cachedReverseIndex&&cachedReverseIndex.graph===graph)return cachedReverseIndex;return buildReverseIndex(graph),cachedReverseIndex}function getReverseIndex(graph){return getQueryIndexes(graph).index}function getForwardIndex(graph){return getQueryIndexes(graph).forwardIndex}function resetQueryCache(){cachedReverseIndex=null}function isGraphFresh(graph,maxAgeMs=300000){if(!graph)return!1;let built=Date.parse(graph.metadata?.generatedAt??"");if(!Number.isFinite(built))return!1;return Date.now()-built<=maxAgeMs}function isSafeHealthPath(value){if(typeof value!=="string")return!1;if(value.length===0||value.length>MAX_HEALTH_PATH_LENGTH)return!1;if(containsControlChars(value)||containsPathTraversal(value))return!1;if(path144.isAbsolute(value)||/^[A-Za-z]:[\\/]/.test(value))return!1;return!0}function isSafeHealthText(value){if(typeof value!=="string")return!1;if(value.length===0||value.length>MAX_HEALTH_PATH_LENGTH)return!1;if(containsControlChars(value))return!1;return!0}function cap(entries){return entries.slice(0,GRAPH_HEALTH_OUTPUT_LIMIT)}function sanitizeExtractionFailures(value){if(!Array.isArray(value))return[];let entries=[];for(let raw of value){if(!raw||typeof raw!=="object")continue;let entry=raw;if(isSafeHealthPath(entry.file)&&isSafeHealthText(entry.language)&&isSafeHealthText(entry.reason))entries.push({file:entry.file,language:entry.language,reason:entry.reason})}return cap(entries)}function sanitizeUnresolvedImports(value){if(!Array.isArray(value))return[];let entries=[];for(let raw of value){if(!raw||typeof raw!=="object")continue;let entry=raw;if(isSafeHealthPath(entry.file)&&isSafeHealthText(entry.specifier))entries.push({file:entry.file,specifier:entry.specifier})}return cap(entries)}function sanitizePathList(value){if(!Array.isArray(value))return[];return cap(value.filter(isSafeHealthPath))}function getStaleFiles(graph,workspaceRoot){let built=Date.parse(graph.metadata.generatedAt);if(!Number.isFinite(built))return[];let root=workspaceRoot??graph.workspaceRoot,stale=[];for(let node of Object.values(graph.nodes)){let moduleName=normalizeGraphPath(node.moduleName);if(!isSafeHealthPath(moduleName))continue;let filePath=path144.join(root,moduleName);try{if(fsSync10.statSync(filePath).mtimeMs>built){if(stale.push(moduleName),stale.length>=GRAPH_HEALTH_OUTPUT_LIMIT)break}}catch{}}return stale}function getGraphHealth(graph,workspaceRoot){if(!graph)return{schemaVersion:null,fresh:!1,staleFiles:[],extractionFailures:[],unresolvedImports:[],oversizedFiles:[],unsupportedFiles:[],binaryFiles:[],unreadableFiles:[],lowConfidenceEdgeCount:0,notes:['No repo graph found at .swarm/repo-graph.json. Run repo_map with action="build" first.']};let diagnostics=graph.diagnostics,fresh=isGraphFresh(graph),staleFiles=getStaleFiles(graph,workspaceRoot),notes=[];if(!fresh||staleFiles.length>0)notes.push('Graph is stale. Run repo_map with action="build" to refresh.');if(!diagnostics)notes.push('Graph has no recorded diagnostics. Rebuild with repo_map action="build" to collect health details.');let binaryFiles=sanitizePathList(diagnostics?.binaryFiles),binaryCount=binaryFiles.length;if(binaryCount>0)notes.push(`${binaryCount} binary files skipped during last build.`);let unreadableFiles=sanitizePathList(diagnostics?.unreadableFiles),unreadableCount=unreadableFiles.length;if(unreadableCount>0)notes.push(`${unreadableCount} unreadable files skipped during last build.`);return{schemaVersion:graph.schema_version,fresh,staleFiles,extractionFailures:sanitizeExtractionFailures(diagnostics?.extractionFailures),unresolvedImports:sanitizeUnresolvedImports(diagnostics?.unresolvedImports),oversizedFiles:sanitizePathList(diagnostics?.oversizedFiles),unsupportedFiles:sanitizePathList(diagnostics?.unsupportedFiles),binaryFiles,unreadableFiles,lowConfidenceEdgeCount:typeof diagnostics?.lowConfidenceEdgeCount==="number"&&Number.isFinite(diagnostics.lowConfidenceEdgeCount)&&diagnostics.lowConfidenceEdgeCount>0?Math.floor(diagnostics.lowConfidenceEdgeCount):0,notes}}function getImporters(graph,filePath){let node=getGraphNode(graph,filePath);if(!node)return[];return getReverseIndex(graph).get(normalizeGraphPath(node.filePath))??[]}function getDependencies(graph,filePath){let node=getGraphNode(graph,filePath);if(!node)return[];let sourceKey=normalizeGraphPath(node.filePath);return getForwardIndex(graph).get(sourceKey)??[]}function getSymbolConsumers(graph,filePath,symbolName){let node=getGraphNode(graph,filePath);if(!node)return[];let targetKey=normalizeGraphPath(node.filePath),refs=[];for(let edge of graph.edges){if(normalizeGraphPath(edge.target)!==targetKey)continue;let importedSymbols=edge.importedSymbols??[];if(edge.importType==="namespace"){refs.push({file:moduleNameForEdgePath(graph,edge.source),importedAs:"*"});continue}if(importedSymbols.includes(symbolName))refs.push({file:moduleNameForEdgePath(graph,edge.source),importedAs:symbolName})}return refs.sort((a,b)=>a.file.localeCompare(b.file)),refs}function getCallers(graph,filePath,symbolName){let node=getGraphNode(graph,filePath);if(!node)return[];let targetKey=normalizeGraphPath(node.filePath),refs=[],seen=new Set;for(let edge of graph.edges){if(normalizeGraphPath(edge.target)!==targetKey)continue;let file3=moduleNameForEdgePath(graph,edge.source);if(seen.has(file3))continue;if(edge.usedSymbols!==void 0){if(edge.usedSymbols.includes(symbolName))seen.add(file3),refs.push({file:file3,resolution:"used"});continue}let imported=edge.importedSymbols??[];if(edge.importType==="namespace"||imported.includes(symbolName))seen.add(file3),refs.push({file:file3,resolution:"imported"})}return refs.sort((a,b)=>a.file.localeCompare(b.file)),refs}var DEAD_EXPORT_EXCLUDED_ROLES=new Set(["api_route","cli_command","test_file","agent","hook","middleware"]);function getDeadExports(graph,options){if(!isSchemaVersionAtLeast(graph.schema_version,"1.1.0"))return{schemaSupported:!1,analyzedFiles:0,skippedUnresolvable:0,candidates:[],note:'Graph predates schema 1.1.0 (no usedSymbols data). Run repo_map action="build" to enable dead_exports.'};let usage=new Map;for(let edge of graph.edges){let target=normalizeGraphPath(edge.target),entry=usage.get(target);if(!entry)entry={used:new Set,unresolvable:!1},usage.set(target,entry);if(edge.importType==="namespace"||edge.importType==="sideeffect"||edge.importType==="require")entry.unresolvable=!0;else if(edge.usedSymbols)for(let symbol3 of edge.usedSymbols)entry.used.add(symbol3)}let reverse=getReverseIndex(graph),candidates=[],analyzedFiles=0,skippedUnresolvable=0;for(let node of Object.values(graph.nodes)){if(node.exports.length===0)continue;let key=normalizeGraphPath(node.filePath),importerCount=reverse.get(key)?.length??0;if(importerCount===0)continue;if((node.ontology?.roles??[]).some((r)=>DEAD_EXPORT_EXCLUDED_ROLES.has(r)))continue;let entry=usage.get(key);if(entry?.unresolvable){skippedUnresolvable++;continue}analyzedFiles++;let used=entry?.used??new Set;for(let symbol3 of node.exports){if(symbol3==="default")continue;if(used.has(symbol3))continue;candidates.push({file:node.moduleName,symbol:symbol3,line:node.exportLines?.[symbol3],importerCount})}}candidates.sort((a,b)=>a.file.localeCompare(b.file)||a.symbol.localeCompare(b.symbol));let limit=options?.maxCandidates??100,truncated=candidates.length>limit;return{schemaSupported:!0,analyzedFiles,skippedUnresolvable,candidates:candidates.slice(0,limit),note:"Advisory: exported symbols with no detected in-repo reference, limited to files imported by >=1 other file. Regex analysis cannot see dynamic dispatch, string-keyed access, or namespace/barrel re-export usage; verify before removing."+(truncated?` Showing ${limit} of ${candidates.length}.`:"")}}function getBlastRadius(graph,filePaths,maxDepth=3){let targetNodes=filePaths.map((filePath)=>getGraphNode(graph,filePath)).filter((node)=>node!==void 0),targets=targetNodes.map((node)=>normalizeLookupPath(node.moduleName));if(maxDepth<=0||targetNodes.length===0)return{target:filePaths.map((filePath)=>toModuleName2(graph,filePath)),directDependents:[],transitiveDependents:[],depthReached:0,totalDependents:0,riskLevel:"low"};let reverse=getReverseIndex(graph),visited=new Set(targetNodes.map((node)=>normalizeGraphPath(node.filePath))),direct=new Set,transitive=new Set,depthReached=0,queue=targetNodes.map((node)=>({key:normalizeGraphPath(node.filePath),depth:0}));while(queue.length>0){let next=[];for(let{key,depth}of queue){let importers=reverse.get(key)??[];for(let ref of importers){let importerNode=getGraphNode(graph,ref.file);if(!importerNode)continue;let importerKey=normalizeGraphPath(importerNode.filePath);if(visited.has(importerKey))continue;if(visited.add(importerKey),depth===0)direct.add(ref.file);else transitive.add(ref.file);if(depthReached=Math.max(depthReached,depth+1),depth+1<maxDepth)next.push({key:importerKey,depth:depth+1})}}queue=next}let totalDependents=direct.size+transitive.size;return{target:targets,directDependents:[...direct].sort(),transitiveDependents:[...transitive].sort(),depthReached,totalDependents,riskLevel:classifyRisk(totalDependents)}}function classifyRisk(count){if(count<=3)return"low";if(count<=10)return"medium";if(count<=25)return"high";return"critical"}function getKeyFiles(graph,topN=10){let reverse=getReverseIndex(graph),scored=Object.values(graph.nodes).map((node)=>({node,inDegree:reverse.get(normalizeGraphPath(node.filePath))?.length??0}));return scored.sort((a,b)=>{if(b.inDegree!==a.inDegree)return b.inDegree-a.inDegree;return a.node.moduleName.localeCompare(b.node.moduleName)}),scored.slice(0,topN).map((item)=>item.node)}function getFileOntology(graph,filePath){return getGraphNode(graph,filePath)?.ontology??null}function getLocalizationContext(graph,filePath,options={}){let target=toModuleName2(graph,filePath),node=getGraphNode(graph,target),importers=getImporters(graph,target),dependencies=getDependencies(graph,target),blast=getBlastRadius(graph,[target],options.maxDepth??2),externalSymbols=collectExternallyUsedSymbols(graph,node),summary=formatLocalizationSummary({target,importers,dependencies,blast,externalSymbols,ontology:node?.ontology??null,maxImporters:options.maxImporters??5,maxDeps:options.maxDeps??5});return{target,importerCount:importers.length,importers:importers.slice(0,options.maxImporters??5),dependencyCount:dependencies.length,dependencies:dependencies.slice(0,options.maxDeps??5),exportedSymbolsUsedExternally:externalSymbols,blastRadius:blast,summary}}function getContextPack(graph,file3,symbol3,options={}){if(!isSchemaVersionAtLeast(graph.schema_version,"1.2.0"))return{schemaSupported:!1,target:{file:file3,symbol:symbol3},spans:[],truncated:!1,estimatedTokens:0,note:'rebuild with repo_map action="build"'};let maxDepth=options.maxDepth??2,maxTokens=options.maxTokens??4000,targetNode=getGraphNode(graph,file3);if(!targetNode)return{schemaSupported:!0,target:{file:file3,symbol:symbol3},spans:[],truncated:!1,estimatedTokens:0,note:"Target file not found in graph"};let targetFile=normalizeGraphPath(targetNode.filePath),forward=new Map,reverse=new Map,symbolEdges=graph.symbolEdges??[];for(let edge of symbolEdges){let fromKey=`${normalizeGraphPath(edge.fromFile)}\x00${edge.fromSymbol}`,toKey=`${normalizeGraphPath(edge.toFile)}\x00${edge.toSymbol}`,fromEdges=forward.get(fromKey);if(fromEdges)fromEdges.push(edge);else forward.set(fromKey,[edge]);let toEdges=reverse.get(toKey);if(toEdges)toEdges.push(edge);else reverse.set(toKey,[edge])}let targetKey=`${targetFile}\x00${symbol3}`,visited=new Map,queue=[{key:targetKey,depth:0}];visited.set(targetKey,0);let reached=[],queueHead=0;while(queueHead<queue.length){let{key,depth}=queue[queueHead];queueHead++;let[curFile,curSymbol]=key.split("\x00",2);if(reached.push({file:curFile,symbol:curSymbol,depth}),depth>=maxDepth)continue;let outEdges=forward.get(key)??[];for(let edge of outEdges){let nextKey=`${normalizeGraphPath(edge.toFile)}\x00${edge.toSymbol}`;if(!visited.has(nextKey))visited.set(nextKey,depth+1),queue.push({key:nextKey,depth:depth+1})}let inEdges=reverse.get(key)??[];for(let edge of inEdges){let nextKey=`${normalizeGraphPath(edge.fromFile)}\x00${edge.fromSymbol}`;if(!visited.has(nextKey))visited.set(nextKey,depth+1),queue.push({key:nextKey,depth:depth+1})}}let TOKENS_PER_LINE=12,TOKENS_PER_SIGNATURE=10,spansWithDepth=[];for(let{file:symFile,symbol:sym,depth:d}of reached){let range=graph.nodes[symFile]?.exportRanges?.[sym];if(!range)continue;let mode=d===0?"full":d<maxDepth?"full":"signature";spansWithDepth.push({span:{file:symFile,symbol:sym,startLine:range.startLine,endLine:range.endLine,mode},depth:d})}spansWithDepth.sort((a,b)=>{let aIsTarget=a.span.file===targetFile&&a.span.symbol===symbol3?0:1,bIsTarget=b.span.file===targetFile&&b.span.symbol===symbol3?0:1;if(aIsTarget!==bIsTarget)return aIsTarget-bIsTarget;if(a.depth!==b.depth)return a.depth-b.depth;let fileCmp=a.span.file.localeCompare(b.span.file);if(fileCmp!==0)return fileCmp;return a.span.symbol.localeCompare(b.span.symbol)});let estimatedTokens=0,finalSpans=[],truncated=!1;for(let{span}of spansWithDepth){let spanTokens=span.mode==="full"?(span.endLine-span.startLine+1)*TOKENS_PER_LINE:TOKENS_PER_SIGNATURE;if(finalSpans.length>0&&estimatedTokens+spanTokens>maxTokens){truncated=!0;break}finalSpans.push(span),estimatedTokens+=spanTokens}return{schemaSupported:!0,target:{file:targetFile,symbol:symbol3},spans:finalSpans,truncated,estimatedTokens}}function collectExternallyUsedSymbols(graph,node){if(!node)return[];let exported=new Set(node.exports),used=new Set,targetKey=normalizeGraphPath(node.filePath);for(let edge of graph.edges){if(normalizeGraphPath(edge.target)!==targetKey)continue;for(let symbol3 of edge.importedSymbols??[])if(exported.has(symbol3))used.add(symbol3)}return[...used].sort((a,b)=>a.localeCompare(b))}function formatLocalizationSummary(opts){let importerList=opts.importers.length===0?"(none)":opts.importers.slice(0,opts.maxImporters).map((ref)=>ref.file).join(", ")+(opts.importers.length>opts.maxImporters?`, +${opts.importers.length-opts.maxImporters} more`:""),depList=opts.dependencies.length===0?"(none)":opts.dependencies.slice(0,opts.maxDeps).map((ref)=>ref.file).join(", ")+(opts.dependencies.length>opts.maxDeps?`, +${opts.dependencies.length-opts.maxDeps} more`:""),symbolList=opts.externalSymbols.length===0?"(none used externally)":opts.externalSymbols.slice(0,8).join(", ")+(opts.externalSymbols.length>8?`, +${opts.externalSymbols.length-8} more`:""),roles=opts.ontology?.roles.join(", ")||"unknown",findings=opts.ontology?.findings.length??0;return["LOCALIZATION CONTEXT",` Target: ${opts.target}`,` Roles: ${roles}`,` Imported by (${opts.importers.length}): ${importerList}`,` Imports (${opts.dependencies.length}): ${depList}`,` Exports used externally: ${symbolList}`,` Blast radius: ${opts.blast.totalDependents} files (${opts.blast.riskLevel} risk)`,` Ontology findings: ${findings}`].join(`
|
|
@@ -5637,7 +5637,7 @@ ${activitySection}`;break}if(contextSummary.length>maxChars)return`${contextSumm
|
|
|
5637
5637
|
`)}function createSummary(output,toolName,summaryId,maxSummaryChars){let contentType=detectContentType(output,toolName),lineCount=output.split(`
|
|
5638
5638
|
`).length,byteSize=Buffer.byteLength(output,"utf8"),formattedSize=formatBytes(byteSize),headerLine=`[SUMMARY ${summaryId}] ${formattedSize} | ${contentType} | ${lineCount} lines`,footerLine=`→ Use /swarm retrieve ${summaryId} for full content`,overhead=headerLine.length+1+footerLine.length+1,maxPreviewChars=maxSummaryChars-overhead,preview;switch(contentType){case"json":{try{let parsed=JSON.parse(output.trim());if(Array.isArray(parsed))preview=summarizeJsonArray(parsed);else if(typeof parsed==="object"&&parsed!==null)preview=summarizeJsonObject(parsed);else preview=summarizeText(output,3)}catch{preview=summarizeText(output,3)}break}case"code":{preview=summarizeCode(output);break}case"text":{preview=summarizeText(output,5);break}case"binary":{preview=`[Binary content - ${formattedSize}]`;break}default:preview=summarizeText(output,5)}if(preview.length>maxPreviewChars)preview=`${preview.substring(0,maxPreviewChars-3)}...`;return`${headerLine}
|
|
5639
5639
|
${preview}
|
|
5640
|
-
${footerLine}`}init_utils();var nextSummaryId=1;function createToolSummarizerHook(config3,directory){if(config3.enabled===!1)return async()=>{};return async(input,output)=>{if(typeof output.output!=="string"||output.output.length===0)return;if((config3.exempt_tools??["retrieve_summary","retrieve_lane_output","task","read"]).includes(input.tool))return;if(!shouldSummarize(output.output,config3.threshold_bytes))return;let summaryId=`S${nextSummaryId++}`,summaryText=createSummary(output.output,input.tool,summaryId,config3.max_summary_chars);try{await storeSummary(directory,summaryId,output.output,summaryText,config3.max_stored_bytes),output.output=summaryText}catch(error93){warn(`Tool output summarization failed for ${summaryId}: ${error93 instanceof Error?error93.message:String(error93)}`)}}}init_utils2();init_constants();init_schema();init_state2();import*as child_process10 from"node:child_process";import*as fs87 from"node:fs";init_state2();import*as fs86 from"node:fs/promises";import*as path155 from"node:path";init_bun_compat();import{rmSync as rmSync8}from"node:fs";import*as fs85 from"node:fs/promises";import*as path154 from"node:path";function leanTurboEvidenceDir(directory,phase){return path154.join(directory,".swarm","evidence",String(phase),"lean-turbo")}function validateLaneId(laneId){if(laneId.length===0)throw Error("Invalid laneId: empty string is not allowed");if(laneId.length>128)throw Error(`Invalid laneId: exceeds maximum length of 128 characters (got ${laneId.length})`);if(laneId.includes("/")||laneId.includes("\\"))throw Error(`Invalid laneId: path separators are not allowed (got "${laneId}")`);if(laneId.includes(".."))throw Error(`Invalid laneId: parent-directory references are not allowed (got "${laneId}")`);if(laneId.startsWith("/")||/^[a-zA-Z]:/i.test(laneId))throw Error(`Invalid laneId: absolute paths are not allowed (got "${laneId}")`)}function laneEvidencePath(directory,phase,laneId){validateLaneId(laneId);let expectedDir=leanTurboEvidenceDir(directory,phase),resolvedPath=path154.resolve(path154.join(expectedDir,`${laneId}.json`)),resolvedDir=path154.resolve(expectedDir);if(!resolvedPath.startsWith(resolvedDir+path154.sep)&&resolvedPath!==resolvedDir)throw Error(`Invalid laneId: path traversal detected (got "${laneId}")`);return resolvedPath}async function atomicWriteJson(filePath,data){let content=JSON.stringify(data,null,2),dir=path154.dirname(filePath);await fs85.mkdir(dir,{recursive:!0});let tempPath=`${filePath}.tmp.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}`;try{await bunWrite(tempPath,content),await fs85.rename(tempPath,filePath)}catch(error93){try{rmSync8(tempPath,{force:!0})}catch{}throw error93}}function phaseEvidencePath(directory,phase){return path154.join(leanTurboEvidenceDir(directory,phase),"lean-turbo-phase.json")}async function writeLaneEvidence(directory,phase,evidence){let targetPath=laneEvidencePath(directory,phase,evidence.laneId);await atomicWriteJson(targetPath,evidence)}async function writePhaseEvidence(directory,evidence){let targetPath=phaseEvidencePath(directory,evidence.phase);await atomicWriteJson(targetPath,evidence)}async function readPhaseEvidence(directory,phase){let targetPath=phaseEvidencePath(directory,phase),content;try{content=await fs85.readFile(targetPath,"utf-8")}catch(error93){let code=error93.code;if(code==="ENOENT"||code==="ENOTDIR")return null;throw error93}try{return JSON.parse(content)}catch{return null}}async function listLaneEvidence(directory,phase){let evidenceDir=leanTurboEvidenceDir(directory,phase),entries;try{entries=await fs85.readdir(evidenceDir)}catch(error93){let code=error93.code;if(code==="ENOENT"||code==="ENOTDIR")return[];throw error93}let lanes=[];for(let entry of entries){if(!entry.endsWith(".json"))continue;if(entry==="lean-turbo-phase.json")continue;let filePath=path154.join(evidenceDir,entry),content;try{content=await fs85.readFile(filePath,"utf-8")}catch{continue}try{let parsed=JSON.parse(content);lanes.push(parsed)}catch{}}return lanes}init_state4();var DEFAULT_CONFIG2={reviewerAgent:"",timeoutMs:0,requireDiffSummary:!1};function resolveDefaultReviewerAgent(generatedAgentNames){if(generatedAgentNames.length===0)return"reviewer";let best=null;for(let name of generatedAgentNames){let lower=name.toLowerCase();if((lower.endsWith("_reviewer")||lower.endsWith("-reviewer"))&&(!best||name.length>best.length))best=name}return best??(generatedAgentNames.includes("reviewer")?"reviewer":generatedAgentNames[0])}async function compileReviewPackage(directory,phase,sessionID,requireDiffSummary){let lanes=await listLaneEvidence(directory,phase),persisted=_internals94.readPersisted?.(directory)??null;if(persisted){let matchingRunState=null;for(let sessionState of Object.values(persisted.sessions))if(typeof sessionState==="object"&&sessionState!==null&&sessionState.status==="running"&&sessionState.phase===phase&&sessionState.strategy==="lean"&&sessionState.sessionID===sessionID){matchingRunState=sessionState;break}if(!matchingRunState&&sessionID===void 0){for(let sessionState of Object.values(persisted.sessions))if(typeof sessionState==="object"&&sessionState!==null&&sessionState.status==="running"&&sessionState.phase===phase&&sessionState.strategy==="lean"){matchingRunState=sessionState;break}}if(matchingRunState?.lanes&&matchingRunState.lanes.length>0){let evidenceLaneIds=new Set(lanes.map((l)=>l.laneId)),missingLanes=matchingRunState.lanes.filter((l)=>(l.status==="completed"||l.status==="failed")&&!evidenceLaneIds.has(l.laneId));if(missingLanes.length>0)throw Error(`Lane evidence missing for ${missingLanes.length} lane(s): ${missingLanes.map((l)=>l.laneId).join(", ")}. Run lane execution before review.`)}}let phaseEvidence=await readPhaseEvidence(directory,phase),filesChangedSet=new Set;for(let lane of lanes)for(let file3 of lane.files)filesChangedSet.add(file3);let completedLanes=lanes.filter((l)=>l.status==="completed").length,failedLanes=lanes.filter((l)=>l.status==="failed").length,laneSummaries=lanes.map((lane)=>({laneId:lane.laneId,taskIds:lane.taskIds,files:lane.files,status:lane.status,agent:lane.agent})),degradedTasks=phaseEvidence?.degradedTasks??[],pendingDegraded=degradedTasks.filter((dt)=>!lanes.some((l)=>l.taskIds.includes(dt.taskId)&&l.status==="completed")).length,buildStatus="unknown";if(phaseEvidence?.status==="completed")buildStatus=failedLanes===0?"passed":"failed";else if(phaseEvidence?.status==="failed")buildStatus="failed";let pkg={phase,sessionID,laneSummaries,filesChanged:[...filesChangedSet],testResults:{totalLanes:lanes.length,completedLanes,failedLanes},buildStatus,degradationSummary:{totalDegraded:degradedTasks.length,resolvedDegraded:degradedTasks.length-pendingDegraded,pendingDegraded}};if(phaseEvidence?.validationArtifacts)pkg.validationArtifacts=phaseEvidence.validationArtifacts;if(requireDiffSummary){if(!phaseEvidence?.integratedDiffSummary)throw Error(`Integrated diff summary is required for phase ${phaseEvidence?.phase??"unknown"} but missing. Run the review step with diff evidence generation enabled.`);pkg.integratedDiffSummary=phaseEvidence.integratedDiffSummary}return pkg}function parseReviewerVerdict(responseText){let verdictMatch=responseText.toUpperCase().match(/VERDICT\s*:\s*(APPROVED|NEEDS_REVISION|REJECTED)/);if(!verdictMatch)return null;let verdict=verdictMatch[1],lines=responseText.split(`
|
|
5640
|
+
${footerLine}`}init_utils();var nextSummaryId=1;function createToolSummarizerHook(config3,directory){if(config3.enabled===!1)return async()=>{};return async(input,output)=>{if(typeof output.output!=="string"||output.output.length===0)return;if((config3.exempt_tools??["retrieve_summary","retrieve_lane_output","task","read"]).includes(input.tool))return;if(!shouldSummarize(output.output,config3.threshold_bytes))return;let summaryId=`S${nextSummaryId++}`,summaryText=createSummary(output.output,input.tool,summaryId,config3.max_summary_chars);try{await storeSummary(directory,summaryId,output.output,summaryText,config3.max_stored_bytes),output.output=summaryText}catch(error93){warn(`Tool output summarization failed for ${summaryId}: ${error93 instanceof Error?error93.message:String(error93)}`)}}}init_utils2();init_constants();init_schema();init_state2();import*as child_process10 from"node:child_process";import*as fs87 from"node:fs";init_state2();import*as fs86 from"node:fs/promises";import*as path155 from"node:path";init_bun_compat();import{rmSync as rmSync8}from"node:fs";import*as fs85 from"node:fs/promises";import*as path154 from"node:path";function leanTurboEvidenceDir(directory,phase){return path154.join(directory,".swarm","evidence",String(phase),"lean-turbo")}function validateLaneId(laneId){if(laneId.length===0)throw Error("Invalid laneId: empty string is not allowed");if(laneId.length>128)throw Error(`Invalid laneId: exceeds maximum length of 128 characters (got ${laneId.length})`);if(laneId.includes("/")||laneId.includes("\\"))throw Error(`Invalid laneId: path separators are not allowed (got "${laneId}")`);if(laneId.includes(".."))throw Error(`Invalid laneId: parent-directory references are not allowed (got "${laneId}")`);if(laneId.startsWith("/")||/^[a-zA-Z]:/i.test(laneId))throw Error(`Invalid laneId: absolute paths are not allowed (got "${laneId}")`)}function laneEvidencePath(directory,phase,laneId){validateLaneId(laneId);let expectedDir=leanTurboEvidenceDir(directory,phase),resolvedPath=path154.resolve(path154.join(expectedDir,`${laneId}.json`)),resolvedDir=path154.resolve(expectedDir);if(!resolvedPath.startsWith(resolvedDir+path154.sep)&&resolvedPath!==resolvedDir)throw Error(`Invalid laneId: path traversal detected (got "${laneId}")`);return resolvedPath}async function atomicWriteJson(filePath,data){let content=JSON.stringify(data,null,2),dir=path154.dirname(filePath);await fs85.mkdir(dir,{recursive:!0});let tempPath=`${filePath}.tmp.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}`;try{await bunWrite(tempPath,content),await fs85.rename(tempPath,filePath)}catch(error93){try{rmSync8(tempPath,{force:!0})}catch{}throw error93}}function phaseEvidencePath(directory,phase){return path154.join(leanTurboEvidenceDir(directory,phase),"lean-turbo-phase.json")}async function writeLaneEvidence(directory,phase,evidence){let targetPath=laneEvidencePath(directory,phase,evidence.laneId);await atomicWriteJson(targetPath,evidence)}async function writePhaseEvidence(directory,evidence){let targetPath=phaseEvidencePath(directory,evidence.phase);await atomicWriteJson(targetPath,evidence)}async function readPhaseEvidence(directory,phase){let targetPath=phaseEvidencePath(directory,phase),content;try{content=await fs85.readFile(targetPath,"utf-8")}catch(error93){let code=error93.code;if(code==="ENOENT"||code==="ENOTDIR")return null;throw error93}try{return JSON.parse(content)}catch{return null}}async function listLaneEvidence(directory,phase){let evidenceDir=leanTurboEvidenceDir(directory,phase),entries;try{entries=await fs85.readdir(evidenceDir)}catch(error93){let code=error93.code;if(code==="ENOENT"||code==="ENOTDIR")return[];throw error93}entries.sort();let lanes=[];for(let entry of entries){if(!entry.endsWith(".json"))continue;if(entry==="lean-turbo-phase.json")continue;let filePath=path154.join(evidenceDir,entry),content;try{content=await fs85.readFile(filePath,"utf-8")}catch{continue}try{let parsed=JSON.parse(content);lanes.push(parsed)}catch{}}return lanes}init_state4();var DEFAULT_CONFIG2={reviewerAgent:"",timeoutMs:0,requireDiffSummary:!1};function resolveDefaultReviewerAgent(generatedAgentNames){if(generatedAgentNames.length===0)return"reviewer";let best=null;for(let name of generatedAgentNames){let lower=name.toLowerCase();if((lower.endsWith("_reviewer")||lower.endsWith("-reviewer"))&&(!best||name.length>best.length))best=name}return best??(generatedAgentNames.includes("reviewer")?"reviewer":generatedAgentNames[0])}async function compileReviewPackage(directory,phase,sessionID,requireDiffSummary){let lanes=await listLaneEvidence(directory,phase),persisted=_internals94.readPersisted?.(directory)??null;if(persisted){let matchingRunState=null;for(let sessionState of Object.values(persisted.sessions))if(typeof sessionState==="object"&&sessionState!==null&&sessionState.status==="running"&&sessionState.phase===phase&&sessionState.strategy==="lean"&&sessionState.sessionID===sessionID){matchingRunState=sessionState;break}if(!matchingRunState&&sessionID===void 0){for(let sessionState of Object.values(persisted.sessions))if(typeof sessionState==="object"&&sessionState!==null&&sessionState.status==="running"&&sessionState.phase===phase&&sessionState.strategy==="lean"){matchingRunState=sessionState;break}}if(matchingRunState?.lanes&&matchingRunState.lanes.length>0){let evidenceLaneIds=new Set(lanes.map((l)=>l.laneId)),missingLanes=matchingRunState.lanes.filter((l)=>(l.status==="completed"||l.status==="failed")&&!evidenceLaneIds.has(l.laneId));if(missingLanes.length>0)throw Error(`Lane evidence missing for ${missingLanes.length} lane(s): ${missingLanes.map((l)=>l.laneId).join(", ")}. Run lane execution before review.`)}}let phaseEvidence=await readPhaseEvidence(directory,phase),filesChangedSet=new Set;for(let lane of lanes)for(let file3 of lane.files)filesChangedSet.add(file3);let completedLanes=lanes.filter((l)=>l.status==="completed").length,failedLanes=lanes.filter((l)=>l.status==="failed").length,laneSummaries=lanes.map((lane)=>({laneId:lane.laneId,taskIds:lane.taskIds,files:lane.files,status:lane.status,agent:lane.agent})),degradedTasks=phaseEvidence?.degradedTasks??[],pendingDegraded=degradedTasks.filter((dt)=>!lanes.some((l)=>l.taskIds.includes(dt.taskId)&&l.status==="completed")).length,buildStatus="unknown";if(phaseEvidence?.status==="completed")buildStatus=failedLanes===0?"passed":"failed";else if(phaseEvidence?.status==="failed")buildStatus="failed";let pkg={phase,sessionID,laneSummaries,filesChanged:[...filesChangedSet],testResults:{totalLanes:lanes.length,completedLanes,failedLanes},buildStatus,degradationSummary:{totalDegraded:degradedTasks.length,resolvedDegraded:degradedTasks.length-pendingDegraded,pendingDegraded}};if(phaseEvidence?.validationArtifacts)pkg.validationArtifacts=phaseEvidence.validationArtifacts;if(requireDiffSummary){if(!phaseEvidence?.integratedDiffSummary)throw Error(`Integrated diff summary is required for phase ${phaseEvidence?.phase??"unknown"} but missing. Run the review step with diff evidence generation enabled.`);pkg.integratedDiffSummary=phaseEvidence.integratedDiffSummary}return pkg}function parseReviewerVerdict(responseText){let verdictMatch=responseText.toUpperCase().match(/VERDICT\s*:\s*(APPROVED|NEEDS_REVISION|REJECTED)/);if(!verdictMatch)return null;let verdict=verdictMatch[1],lines=responseText.split(`
|
|
5641
5641
|
`),verdictIndex=lines.findIndex((l)=>l.toUpperCase().match(/VERDICT\s*:\s*(APPROVED|NEEDS_REVISION|REJECTED)/i)),reason;if(verdictIndex>=0&&verdictIndex+1<lines.length){let reasonMatch=lines[verdictIndex+1].match(/^REASON\s*:\s*(.+)/i);if(reasonMatch)reason=reasonMatch[1].trim()}return{verdict,reason}}async function writeReviewerEvidence(directory,phase,verdict,reason){let evidenceDir=path155.join(directory,".swarm","evidence",String(phase));await fs86.mkdir(evidenceDir,{recursive:!0});let evidencePath=path155.join(evidenceDir,"lean-turbo-reviewer.json"),content=JSON.stringify({phase,verdict,reason:reason??null,timestamp:new Date().toISOString()},null,2),tempPath=`${evidencePath}.tmp.${process.pid}.${Date.now()}`;try{await fs86.writeFile(tempPath,content,"utf-8"),await fs86.rename(tempPath,evidencePath)}catch(error93){try{await fs86.unlink(tempPath)}catch{}throw error93}return evidencePath}async function defaultDispatchReviewerAgent(directory,reviewPackage,agentName,timeoutMs,parentSessionId){let client=swarmState.opencodeClient;if(!client)throw Error("OpencodeClient not available");let sessionResult=await client.session.create({...parentSessionId?{body:{parentID:parentSessionId,title:"lean_turbo_reviewer background"}}:{},query:{directory}});if(!sessionResult.data?.id)throw Error("Failed to create reviewer session");let sessionId=sessionResult.data.id,promptController=new AbortController,timeoutHandle;try{let promptText=`You are a read-only phase reviewer for Lean Turbo execution.
|
|
5642
5642
|
|
|
5643
5643
|
## Phase Review Package
|
|
@@ -5740,14 +5740,14 @@ Review before proceeding.`;injectSystemMessage(input.sessionID,message)}}}init_b
|
|
|
5740
5740
|
`,"utf-8")}catch{}}function createSteeringConsumedHook(directory){return safeHook(async()=>{try{let eventsPath=validateSwarmPath(directory,"events.jsonl"),content=await bunFile(eventsPath).text();if(!content.trim())return;let lines=content.trim().split(`
|
|
5741
5741
|
`),directiveIds=new Set,consumedIds=new Set;for(let line of lines){if(!line.trim())continue;try{let parsed=JSON.parse(line);if(parsed.type==="steering-directive"&&parsed.directiveId)directiveIds.add(parsed.directiveId);else if(parsed.type==="steering-consumed"&&parsed.directiveId)consumedIds.add(parsed.directiveId)}catch{}}for(let directiveId of directiveIds)if(!consumedIds.has(directiveId))recordSteeringConsumed(directory,directiveId)}catch{}})}init_trajectory_logger();init_memory();init_prm();init_compaction_service();init_config_doctor();init_cost_accounting();init_version_check();init_state3();init_utils2();init_state2();init_bun_compat();import{renameSync as renameSync28}from"node:fs";var TRANSIENT_SESSION_FIELDS=[{name:"revisionLimitHit",resetValue:!1},{name:"coderRevisions",resetValue:0},{name:"selfFixAttempted",resetValue:!1},{name:"lastGateFailure",resetValue:null},{name:"architectWriteCount",resetValue:0},{name:"selfCodingWarnedAtCount",resetValue:0},{name:"pendingAdvisoryMessages",resetValue:[]},{name:"model_fallback_index",resetValue:0},{name:"modelFallbackExhausted",resetValue:!1},{name:"scopeViolationDetected",resetValue:!1},{name:"delegationActive",resetValue:!1},{name:"autoProceedOverride",resetValue:void 0},{name:"autoProceedNudgeDone",resetValue:void 0}],VALID_TASK_WORKFLOW_STATES=["idle","coder_delegated","pre_check_passed","reviewer_run","tests_run","complete"];function deserializeTaskWorkflowStates(raw){let m=new Map;if(!raw||typeof raw!=="object")return m;for(let[taskId,stateVal]of Object.entries(raw))if(VALID_TASK_WORKFLOW_STATES.includes(stateVal))m.set(taskId,stateVal);return m}function deserializeAgentSession(s){let gateLog=new Map;if(s.gateLog)for(let[taskId,gates]of Object.entries(s.gateLog))gateLog.set(taskId,new Set(gates??[]));let reviewerCallCount=new Map;if(s.reviewerCallCount)for(let[phase,count]of Object.entries(s.reviewerCallCount)){let numPhase=Number(phase);if(Number.isFinite(numPhase))reviewerCallCount.set(numPhase,count)}let partialGateWarningsIssuedForTask=new Set(s.partialGateWarningsIssuedForTask??[]),catastrophicPhaseWarnings=new Set(s.catastrophicPhaseWarnings??[]),phaseAgentsDispatched=new Set(s.phaseAgentsDispatched??[]),lastCompletedPhaseAgentsDispatched=new Set(s.lastCompletedPhaseAgentsDispatched??[]),stageBCompletion=new Map;if(s.stageBCompletion)for(let[taskId,agents]of Object.entries(s.stageBCompletion))stageBCompletion.set(taskId,new Set(agents));let windows={};for(let[key,win]of Object.entries(s.windows??{})){if(!win||typeof win!=="object")continue;windows[key]={...win,transientRetryCount:"transientRetryCount"in win?win.transientRetryCount??0:0}}return{agentName:s.agentName,lastToolCallTime:s.lastToolCallTime,lastAgentEventTime:s.lastAgentEventTime,delegationActive:s.delegationActive,activeInvocationId:s.activeInvocationId,lastInvocationIdByAgent:s.lastInvocationIdByAgent??{},windows,lastCompactionHint:s.lastCompactionHint??0,architectWriteCount:s.architectWriteCount??0,lastCoderDelegationTaskId:s.lastCoderDelegationTaskId??null,currentTaskId:s.currentTaskId??null,turboMode:s.turboMode??!1,turboStrategy:s.turboStrategy==="lean"||s.turboStrategy==="standard"?s.turboStrategy:void 0,leanTurboActive:s.leanTurboActive??!1,leanTurboCurrentPhase:typeof s.leanTurboCurrentPhase==="number"?s.leanTurboCurrentPhase:void 0,epicModeActive:s.epicModeActive??!1,gateLog,reviewerCallCount,lastGateFailure:s.lastGateFailure??null,partialGateWarningsIssuedForTask,selfFixAttempted:s.selfFixAttempted??!1,selfCodingWarnedAtCount:s.selfCodingWarnedAtCount??0,catastrophicPhaseWarnings,lastPhaseCompleteTimestamp:s.lastPhaseCompleteTimestamp??0,lastPhaseCompletePhase:s.lastPhaseCompletePhase??0,phaseAgentsDispatched,lastCompletedPhaseAgentsDispatched,qaSkipCount:s.qaSkipCount??0,qaSkipTaskIds:s.qaSkipTaskIds??[],taskWorkflowStates:deserializeTaskWorkflowStates(s.taskWorkflowStates),lastGateOutcome:null,declaredCoderScope:null,lastScopeViolation:null,scopeViolationDetected:s.scopeViolationDetected,modifiedFilesThisCoderTask:[],loopDetectionWindow:[],pendingAdvisoryMessages:s.pendingAdvisoryMessages??[],model_fallback_index:s.model_fallback_index??0,modelFallbackExhausted:s.modelFallbackExhausted??!1,coderRevisions:s.coderRevisions??0,revisionLimitHit:s.revisionLimitHit??!1,fullAutoMode:s.fullAutoMode??!1,fullAutoInteractionCount:s.fullAutoInteractionCount??0,fullAutoDeadlockCount:s.fullAutoDeadlockCount??0,fullAutoLastQuestionHash:s.fullAutoLastQuestionHash??null,maxConcurrencyOverride:typeof s.maxConcurrencyOverride==="number"?Math.min(64,Math.max(1,s.maxConcurrencyOverride)):void 0,autoProceedOverride:s.autoProceedOverride,autoProceedNudgeDone:s.autoProceedNudgeDone,prmPatternCounts:new Map,prmEscalationLevel:0,prmLastPatternDetected:null,prmTrajectoryStep:0,prmHardStopPending:!1,sessionRehydratedAt:s.sessionRehydratedAt??0,stageBCompletion,prSubscriptions:new Map}}async function readSnapshot(directory){try{let resolvedPath=validateSwarmPath(directory,"session/state.json"),content=await bunFile(resolvedPath).text();if(!content.trim())return null;let parsed=JSON.parse(content,(key,value)=>{if(key==="__proto__"||key==="constructor")return;return value});if(parsed.version!==1&&parsed.version!==2){try{let quarantinePath=validateSwarmPath(directory,"session/state.json.quarantine");renameSync28(resolvedPath,quarantinePath)}catch{}return null}return parsed}catch{return null}}async function rehydrateState(snapshot,directory){if(swarmState.pendingRehydrations.size>0)await Promise.allSettled([...swarmState.pendingRehydrations]);if(swarmState.toolAggregates.clear(),swarmState.activeAgent.clear(),swarmState.delegationChains.clear(),swarmState.agentSessions.clear(),snapshot.toolAggregates)for(let[key,value]of Object.entries(snapshot.toolAggregates))swarmState.toolAggregates.set(key,value);if(snapshot.activeAgent)for(let[key,value]of Object.entries(snapshot.activeAgent))swarmState.activeAgent.set(key,value);if(snapshot.delegationChains)for(let[key,value]of Object.entries(snapshot.delegationChains))swarmState.delegationChains.set(key,value);let now=Date.now();if(snapshot.agentSessions)for(let[sessionId,serializedSession]of Object.entries(snapshot.agentSessions)){if(!serializedSession||typeof serializedSession!=="object"||typeof serializedSession.agentName!=="string"||typeof serializedSession.lastToolCallTime!=="number"||typeof serializedSession.delegationActive!=="boolean"){console.warn("[snapshot-reader] Skipping malformed session %s: missing required fields (agentName, lastToolCallTime, delegationActive)",sessionId);continue}let session=deserializeAgentSession(serializedSession);if(session.lastToolCallTime=now,session.lastAgentEventTime=now,session.sessionRehydratedAt=now,session.windows)for(let window2 of Object.values(session.windows))window2.startedAtMs=now,window2.lastSuccessTimeMs=now,window2.hardLimitHit=!1,window2.toolCalls=0,window2.consecutiveErrors=0,window2.recentToolCalls=[],window2.warningIssued=!1,window2.warningReason="";for(let field of TRANSIENT_SESSION_FIELDS)session[field.name]=field.resetValue;if(session.fullAutoMode){let runStillActive=!1;if(directory)try{runStillActive=loadFullAutoRunState(directory,sessionId)?.status==="running"}catch{runStillActive=!1}if(!runStillActive)session.fullAutoMode=!1}swarmState.agentSessions.set(sessionId,session)}}async function loadSnapshot(directory){try{await buildRehydrationCache(directory);let snapshot=await readSnapshot(directory);if(snapshot!==null){await rehydrateState(snapshot,directory);for(let session of swarmState.agentSessions.values())applyRehydrationCache(session)}}catch{}}init_snapshot_writer();init_state2();init_telemetry();init_zod();import*as fs96 from"node:fs";import*as path165 from"node:path";init_bun_compat();import*as fs95 from"node:fs";import*as path164 from"node:path";var DEFAULT_WINDOWS_EXTENSIONS=[".exe",".cmd",".bat"];function isExecutableFile(candidate){try{return fs95.statSync(candidate).isFile()}catch{return!1}}function resolveExecutableFromPath(names,envPath=process.env.PATH??"",platform=process.platform){let pathEntries=envPath.split(path164.delimiter).filter(Boolean),isWindows=platform==="win32";for(let rawName of names){if(!rawName)continue;if(path164.isAbsolute(rawName)&&isExecutableFile(rawName))return rawName;let extensions=isWindows&&path164.extname(rawName)===""?DEFAULT_WINDOWS_EXTENSIONS:[""];for(let dir of pathEntries)for(let ext of extensions){let candidate=path164.join(dir,`${rawName}${ext}`);if(isExecutableFile(candidate))return candidate}}return null}async function readBoundedStream2(stream,maxBytes){let reader=stream.getReader(),lockReleased=!1,releaseLock=()=>{if(lockReleased)return;lockReleased=!0;try{reader.releaseLock()}catch{}},cancelAndRelease=async()=>{try{await reader.cancel()}catch{}finally{releaseLock()}};if(maxBytes<=0)return await cancelAndRelease(),{text:"",truncated:!0};let chunks=[],total=0,truncated=!1;try{for(;;){let{done,value}=await reader.read();if(done)break;if(!value)continue;let remaining=maxBytes-total;if(value.byteLength>remaining){if(remaining>0)chunks.push(value.slice(0,remaining)),total+=remaining;truncated=!0,await cancelAndRelease();break}chunks.push(value),total+=value.byteLength}}finally{releaseLock()}let out=new Uint8Array(total),offset=0;for(let chunk of chunks)out.set(chunk,offset),offset+=chunk.byteLength;return{text:new TextDecoder().decode(out),truncated}}function timeoutKillSignal(platform){return platform==="win32"?"SIGTERM":"SIGKILL"}function killProcess(proc){try{proc?.kill(timeoutKillSignal(_internals100.platform()))}catch{}}async function runExternalTool(options){if(!path164.isAbsolute(options.cwd))return{status:"spawn-error",exitCode:null,stdout:"",stderr:"",stdoutTruncated:!1,stderrTruncated:!1,message:"external tool cwd must be absolute"};let proc,timeoutHandle,exitSettled=!1,settledExitCode=null;try{proc=_internals100.bunSpawn([options.executable,...options.args],{cwd:options.cwd,env:options.env,stdin:"ignore",stdout:"pipe",stderr:"pipe",timeout:options.timeoutMs});let exitPromise=proc.exited.then((exitCode)=>{return exitSettled=!0,settledExitCode=exitCode,{kind:"exit",exitCode}}),timeout=new Promise((resolve59)=>{timeoutHandle=setTimeout(()=>{if(exitSettled){resolve59({kind:"exit",exitCode:settledExitCode??proc?.exitCode??0});return}killProcess(proc),resolve59({kind:"timeout"})},options.timeoutMs)}),stdoutPromise=readBoundedStream2(proc.stdout,options.maxStdoutBytes),stderrPromise=readBoundedStream2(proc.stderr,options.maxStderrBytes),exitResult=await Promise.race([exitPromise,timeout]);if(exitResult.kind==="timeout")return{status:"timeout",exitCode:proc.exitCode,stdout:"",stderr:"",stdoutTruncated:!1,stderrTruncated:!1};let[stdout,stderr]=await Promise.all([stdoutPromise,stderrPromise]);return{status:"completed",exitCode:exitResult.exitCode,stdout:stdout.text,stderr:stderr.text,stdoutTruncated:stdout.truncated,stderrTruncated:stderr.truncated}}catch(err){return{status:"spawn-error",exitCode:proc?.exitCode??null,stdout:"",stderr:"",stdoutTruncated:!1,stderrTruncated:!1,message:err instanceof Error?err.message:String(err)}}finally{if(timeoutHandle!==void 0)clearTimeout(timeoutHandle);if(proc)try{proc.kill()}catch{}}}var _internals100={bunSpawn,platform:()=>process.platform};init_path_security();init_create_tool();var ACTIONLINT_TIMEOUT_MS=15000,ACTIONLINT_MAX_STDOUT_BYTES=4194304,ACTIONLINT_MAX_STDERR_BYTES=131072,DEFAULT_MAX_RESULTS=200,HARD_CAP_RESULTS=2000,MAX_WORKFLOW_FILES=500,MAX_WORKFLOW_DIRS=200,MAX_WORKFLOW_DEPTH=20;function resolveActionlintBinary(){return _internals101.resolveExecutableFromPath(["actionlint"])}function normalizeRelativeWorkflowFile(file3,workspace){if(!file3||containsControlChars(file3)||containsPathTraversal(file3))return null;if(path165.isAbsolute(file3)||/^[A-Za-z]:[/\\]/.test(file3))return null;let normalizedInput=file3.split(/[\\/]+/).filter(Boolean).join(path165.sep);if(!/\.(ya?ml)$/i.test(normalizedInput))return null;try{let realWorkspace=fs96.realpathSync(workspace),resolved=path165.resolve(realWorkspace,normalizedInput),realFile=fs96.realpathSync(resolved),relative29=path165.relative(realWorkspace,realFile);if(!relative29||relative29.startsWith("..")||path165.isAbsolute(relative29))return null;return relative29.split(path165.sep).join("/")}catch{return null}}function discoverWorkflowFiles(workspace){let root=path165.join(workspace,".github","workflows");if(!fs96.existsSync(root))return{files:[],truncated:!1};let files=[],dirCount=0,truncated=!1,visit=(dir,depth=0)=>{if(files.length>=MAX_WORKFLOW_FILES||dirCount>=MAX_WORKFLOW_DIRS||depth>MAX_WORKFLOW_DEPTH){truncated=!0;return}dirCount++;let entries;try{entries=fs96.readdirSync(dir,{withFileTypes:!0})}catch{return}for(let entry of entries){if(files.length>=MAX_WORKFLOW_FILES||dirCount>=MAX_WORKFLOW_DIRS){truncated=!0;break}let full=path165.join(dir,entry.name);if(entry.isDirectory())visit(full,depth+1);else if(entry.isFile()&&/\.(ya?ml)$/i.test(entry.name)){let rel=normalizeRelativeWorkflowFile(path165.relative(workspace,full),workspace);if(rel)files.push(rel)}}};return visit(root),{files,truncated}}function parseActionlintOutput(stdout,workspace,maxResults){let findings=[],total=0;for(let line of stdout.split(`
|
|
5742
5742
|
`)){if(!line.trim())continue;try{let entry=JSON.parse(line),file3=typeof entry.filepath==="string"?normalizeRelativeWorkflowFile(path165.isAbsolute(entry.filepath)?path165.relative(workspace,entry.filepath):entry.filepath,workspace):null;if(!file3)continue;if(total++,findings.length>=maxResults)continue;findings.push({file:file3,line:typeof entry.line==="number"?entry.line:1,column:typeof entry.column==="number"?entry.column:1,kind:typeof entry.kind==="string"?entry.kind:"unknown",message:typeof entry.message==="string"?entry.message:"",endColumn:typeof entry.end_column==="number"?entry.end_column:void 0})}catch{}}return{findings,total}}function sanitizeMaxResults(value){let numeric=typeof value==="number"&&Number.isFinite(value)?value:DEFAULT_MAX_RESULTS;return Math.min(Math.max(0,numeric),HARD_CAP_RESULTS)}var actionlint_scan=createSwarmTool({description:"Run actionlint against GitHub Actions workflow YAML files and return structured findings. Read-only; resolves actionlint lazily.",args:{files:exports_external.array(exports_external.string()).optional().describe("Optional workspace-relative workflow YAML files. Defaults to .github/workflows/**/*.yml,yaml."),max_results:exports_external.number().default(DEFAULT_MAX_RESULTS).describe("Maximum findings to return")},execute:async(args2,directory)=>{let obj=typeof args2==="object"&&args2!==null?args2:{},maxResults=sanitizeMaxResults(obj.max_results),requestedFiles=Array.isArray(obj.files)?obj.files:void 0;if(requestedFiles?.some((f)=>typeof f!=="string"))return JSON.stringify({error:!0,type:"invalid-input",message:"files must be an array of strings"},null,2);let discovery=requestedFiles?{files:requestedFiles.map((f)=>normalizeRelativeWorkflowFile(f,directory)).filter((f)=>Boolean(f)),truncated:!1}:_internals101.discoverWorkflowFiles(directory),files=discovery.files;if(requestedFiles&&files.length!==requestedFiles.length)return JSON.stringify({error:!0,type:"path-escape",message:"files must be existing workspace-relative GitHub Actions YAML files"},null,2);let uniqueFiles=Array.from(new Set(files)),cappedFiles=uniqueFiles.slice(0,MAX_WORKFLOW_FILES),discoveryTruncated=discovery.truncated||uniqueFiles.length>cappedFiles.length;if(files=cappedFiles,files.length===0)return JSON.stringify({clean:!discoveryTruncated,findings:[],total:0,truncated:discoveryTruncated,files:[],command:["actionlint","-format","{{json .}}"],note:discoveryTruncated?`Workflow discovery was truncated at ${MAX_WORKFLOW_FILES} files, ${MAX_WORKFLOW_DIRS} directories, or depth ${MAX_WORKFLOW_DEPTH}; result is incomplete.`:"No GitHub Actions workflow YAML files found"},null,2);let executable=_internals101.resolveActionlintBinary();if(!executable)return JSON.stringify({error:!0,type:"actionlint-not-found",message:"actionlint executable not found. Install actionlint and ensure it is on PATH."},null,2);let lintArgs=["-format","{{json .}}",...files.map((file3)=>`./${file3}`)],run=await _internals101.runExternalTool({executable,args:lintArgs,cwd:directory,timeoutMs:ACTIONLINT_TIMEOUT_MS,maxStdoutBytes:ACTIONLINT_MAX_STDOUT_BYTES,maxStderrBytes:ACTIONLINT_MAX_STDERR_BYTES});if(run.status==="timeout")return JSON.stringify({error:!0,type:"timeout",message:`actionlint timed out after ${ACTIONLINT_TIMEOUT_MS}ms`},null,2);if(run.status==="spawn-error")return JSON.stringify({error:!0,type:"unknown",message:run.message??"actionlint failed to start"},null,2);let{findings,total}=parseActionlintOutput(run.stdout,directory,maxResults);if(run.exitCode!==0&&findings.length===0&&run.stderr)return JSON.stringify({error:!0,type:"unknown",message:run.stderr.split(`
|
|
5743
|
-
`)[0]},null,2);return JSON.stringify({findings,total,truncated:discoveryTruncated||total>maxResults||run.stdoutTruncated||run.stderrTruncated,files,command:["actionlint",...lintArgs],outputTruncated:run.stdoutTruncated||run.stderrTruncated,clean:findings.length===0&&total===0&&!discoveryTruncated&&!run.stdoutTruncated&&!run.stderrTruncated,note:discoveryTruncated?`Workflow discovery was truncated at ${MAX_WORKFLOW_FILES} files, ${MAX_WORKFLOW_DIRS} directories, or depth ${MAX_WORKFLOW_DEPTH}; result is incomplete.`:void 0},null,2)}}),_internals101={resolveExecutableFromPath,resolveActionlintBinary,runExternalTool,discoverWorkflowFiles,parseActionlintOutput};init_zod();init_path_security();init_create_tool();import{existsSync as existsSync93,mkdirSync as mkdirSync42,mkdtempSync as mkdtempSync3,readFileSync as readFileSync61,realpathSync as
|
|
5743
|
+
`)[0]},null,2);return JSON.stringify({findings,total,truncated:discoveryTruncated||total>maxResults||run.stdoutTruncated||run.stderrTruncated,files,command:["actionlint",...lintArgs],outputTruncated:run.stdoutTruncated||run.stderrTruncated,clean:findings.length===0&&total===0&&!discoveryTruncated&&!run.stdoutTruncated&&!run.stderrTruncated,note:discoveryTruncated?`Workflow discovery was truncated at ${MAX_WORKFLOW_FILES} files, ${MAX_WORKFLOW_DIRS} directories, or depth ${MAX_WORKFLOW_DEPTH}; result is incomplete.`:void 0},null,2)}}),_internals101={resolveExecutableFromPath,resolveActionlintBinary,runExternalTool,discoverWorkflowFiles,parseActionlintOutput};init_zod();init_path_security();init_create_tool();import{existsSync as existsSync93,mkdirSync as mkdirSync42,mkdtempSync as mkdtempSync3,readFileSync as readFileSync61,realpathSync as realpathSync20,renameSync as renameSync29,rmdirSync as rmdirSync2,unlinkSync as unlinkSync26,writeFileSync as writeFileSync26}from"node:fs";import*as path166 from"node:path";var WINDOWS_RESERVED_NAMES3=/^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i,MAX_PATCH_SIZE=500000;function containsWindowsAttacks2(filePath){if(/:[^\\/]/.test(filePath))return!0;let parts=filePath.split(/[/\\]/);for(let part of parts)if(WINDOWS_RESERVED_NAMES3.test(part))return!0;return!1}function isProtectedPath3(filePath){return filePath.replace(/\\/g,"/").split("/").some((seg)=>seg===".git"||seg===".swarm")}function containsStrictControlChars(str){for(let i=0;i<str.length;i++){let c=str.charCodeAt(i);if(c<=31&&c!==9&&c!==10&&c!==13)return!0}return!1}function isCanonicalProtectedPath(targetPath,workspace){try{let canonicalTarget=realpathSync20(targetPath),canonicalWorkspace=realpathSync20(workspace);return path166.relative(canonicalWorkspace,canonicalTarget).replace(/\\/g,"/").split("/").filter(Boolean).some((seg)=>seg===".git"||seg===".swarm")}catch{let parentDir=path166.dirname(targetPath);if(parentDir===targetPath)return!1;try{let canonicalParent=realpathSync20(parentDir),canonicalWorkspace=realpathSync20(workspace);return path166.relative(canonicalWorkspace,canonicalParent).replace(/\\/g,"/").split("/").filter(Boolean).some((seg)=>seg===".git"||seg===".swarm")}catch{return!1}}}function isCanonicalPathWithinWorkspace(targetPath,workspaceRoot){try{let canonicalTarget=realpathSync20(targetPath),canonicalWorkspace=realpathSync20(workspaceRoot),relative30=path166.relative(canonicalWorkspace,canonicalTarget);if(relative30.startsWith("..")||path166.isAbsolute(relative30))return!1;if(relative30.replace(/\\/g,"/").split("/").filter(Boolean).some((seg)=>seg===".git"||seg===".swarm"))return!1;return!0}catch{let parentDir=path166.dirname(targetPath);if(parentDir===targetPath)return!1;try{let canonicalParent=realpathSync20(parentDir),canonicalWorkspace=realpathSync20(workspaceRoot),relative30=path166.relative(canonicalWorkspace,canonicalParent);if(relative30.startsWith("..")||path166.isAbsolute(relative30))return!1;if(relative30.replace(/\\/g,"/").split("/").filter(Boolean).some((seg)=>seg===".git"||seg===".swarm"))return!1;return!0}catch{return!1}}}function validatePatchTargetPath(filePath,workspace){if(!filePath||filePath.trim()==="")return"Empty file path";if(path166.isAbsolute(filePath)||/^[A-Za-z]:[/\\]/.test(filePath))return`Absolute path rejected: ${filePath}`;if(containsPathTraversal(filePath))return`Path traversal detected: ${filePath}`;if(containsStrictControlChars(filePath))return`Control characters detected in path: ${filePath}`;if(containsControlChars(filePath))return`Control characters detected in path: ${filePath}`;if(containsWindowsAttacks2(filePath))return`Windows reserved name or invalid path: ${filePath}`;if(isProtectedPath3(filePath))return`Protected directory target rejected: ${filePath}`;let resolved=path166.resolve(workspace,filePath),relative30=path166.relative(workspace,resolved);if(relative30.startsWith("..")||path166.isAbsolute(relative30))return`Path escapes workspace: ${filePath}`;if(!isCanonicalPathWithinWorkspace(resolved,workspace))return`Path escapes workspace via symlink/junction: ${filePath}`;return null}function extractHeaderPath(header,prefix){let trimmed=header.trim();if(!trimmed.startsWith(prefix))return null;let rest=trimmed.slice(prefix.length).trim();if(rest==="/dev/null")return"/dev/null";if(rest.startsWith("a/")||rest.startsWith("b/")){let stripped=rest.slice(2);if(stripped.length===0)return null;return stripped}return rest.length>0?rest:null}function parseHunkHeader(line){let match=line.match(/^@@\s*-(\d+)(?:,(\d+))?\s*\+(\d+)(?:,(\d+))?\s*@@/);if(!match)return null;return{oldStart:parseInt(match[1],10),oldCount:match[2]!==void 0?parseInt(match[2],10):1,newStart:parseInt(match[3],10),newCount:match[4]!==void 0?parseInt(match[4],10):1}}function parseUnifiedDiff(patchText){if(patchText.length>MAX_PATCH_SIZE)return{files:[],error:`Patch exceeds maximum size of ${MAX_PATCH_SIZE} characters`};if(patchText.includes("\x00"))return{files:[],error:"Binary content detected (null byte) — binary patches are not supported (FR-013)"};let lines=patchText.replace(/\r\n/g,`
|
|
5744
5744
|
`).replace(/\r/g,`
|
|
5745
5745
|
`).split(`
|
|
5746
5746
|
`);if(lines.length>0&&lines[lines.length-1]==="")lines=lines.slice(0,-1);for(let line of lines){if(line==="GIT binary patch"||line.startsWith("Binary files "))return{files:[],error:"Binary patches are not supported (FR-013)"};if(line.startsWith("rename from")||line.startsWith("rename to")||line.startsWith("copy from")||line.startsWith("copy to"))return{files:[],error:"Rename/copy patches are not supported (FR-013)"}}let fileDiffs=[],i=0;while(i<lines.length){let oldHeaderPath=null,newHeaderPath=null;if(lines[i].startsWith("diff --git ")){i++;while(i<lines.length&&(lines[i].startsWith("index ")||lines[i].startsWith("old mode ")||lines[i].startsWith("new mode ")||lines[i].startsWith("deleted file ")||lines[i].startsWith("new file ")||lines[i].startsWith("similarity index ")||lines[i].startsWith("dissimilarity index ")))i++}if(i<lines.length&&lines[i].startsWith("--- "))oldHeaderPath=extractHeaderPath(lines[i],"--- "),i++;else if(oldHeaderPath===null){i++;continue}if(i<lines.length&&lines[i].startsWith("+++ "))newHeaderPath=extractHeaderPath(lines[i],"+++ "),i++;else continue;if(oldHeaderPath===null||newHeaderPath===null)continue;let isNewFile=oldHeaderPath==="/dev/null",isDelete=newHeaderPath==="/dev/null";if((isDelete?oldHeaderPath:newHeaderPath)==="/dev/null")continue;let hunks=[];while(i<lines.length&&lines[i].startsWith("@@")){let header=parseHunkHeader(lines[i]);if(!header){i++;continue}i++;let hunkLines=[];while(i<lines.length){let line=lines[i];if(line.startsWith("@@")||line.startsWith("diff --git ")||line.startsWith("--- ")||line.startsWith("+++ "))break;if(line.startsWith("\\")){i++;continue}if(line.length===0)break;let firstChar=line[0];if(firstChar!==" "&&firstChar!=="+"&&firstChar!=="-")break;if(firstChar==="+")hunkLines.push({type:"addition",content:line.slice(1)});else if(firstChar==="-")hunkLines.push({type:"removal",content:line.slice(1)});else hunkLines.push({type:"context",content:line.slice(1)});i++}hunks.push({oldStart:header.oldStart,oldCount:header.oldCount,newStart:header.newStart,newCount:header.newCount,lines:hunkLines})}if(hunks.length>0)fileDiffs.push({oldPath:oldHeaderPath,newPath:newHeaderPath,isNewFile,isDelete,hunks});else fileDiffs.push({oldPath:oldHeaderPath,newPath:newHeaderPath,isNewFile,isDelete,hunks:[]})}return{files:fileDiffs,error:null}}function arraysEqual(a,b){if(a.length!==b.length)return!1;for(let idx=0;idx<a.length;idx++)if(a[idx]!==b[idx])return!1;return!0}function applyHunks(content,fileDiff){let fileLines=content.replace(/\r\n/g,`
|
|
5747
5747
|
`).split(`
|
|
5748
5748
|
`);if(fileDiff.isNewFile){let newLines=[];for(let hunk of fileDiff.hunks)for(let line of hunk.lines)if(line.type==="addition"||line.type==="context")newLines.push(line.content);return{success:!0,appliedLines:newLines}}if(fileDiff.isDelete)return{success:!0,appliedLines:[]};let accumulatedDelta=0;for(let hunkIdx=0;hunkIdx<fileDiff.hunks.length;hunkIdx++){let hunk=fileDiff.hunks[hunkIdx],searchStart=Math.max(0,hunk.oldStart-1+accumulatedDelta),expectedOldLines=[],newLinesForHunk=[];for(let line of hunk.lines)if(line.type==="context")expectedOldLines.push(line.content),newLinesForHunk.push(line.content);else if(line.type==="removal")expectedOldLines.push(line.content);else if(line.type==="addition")newLinesForHunk.push(line.content);let exactOffset=searchStart,matchFound=exactOffset<=fileLines.length-expectedOldLines.length&&arraysEqual(fileLines.slice(exactOffset,exactOffset+expectedOldLines.length),expectedOldLines);if(matchFound){fileLines.splice(exactOffset,expectedOldLines.length,...newLinesForHunk);let delta=newLinesForHunk.length-expectedOldLines.length;accumulatedDelta+=delta}if(!matchFound){let diagStart=Math.min(searchStart,fileLines.length),diagEnd=Math.min(diagStart+expectedOldLines.length,fileLines.length),actualContent=fileLines.slice(diagStart,diagEnd).join(`
|
|
5749
5749
|
`),expectedContent=expectedOldLines.join(`
|
|
5750
|
-
`);return{success:!1,failedHunkIndex:hunkIdx,error:{hunkIndex:hunkIdx,type:"context-mismatch",message:`Context mismatch in hunk ${hunkIdx+1} at line ${searchStart+1}: expected context does not match file content`,expected:expectedContent.length>200?`${expectedContent.slice(0,200)}... (truncated)`:expectedContent,actual:actualContent.length>200?`${actualContent.slice(0,200)}... (truncated)`:actualContent,line:searchStart+1}}}}return{success:!0,appliedLines:fileLines}}function atomicWriteFileSync2(targetPath,content){let dir=path166.dirname(targetPath);mkdirSync42(dir,{recursive:!0});let tempPrefix=`.apply-patch-${Date.now()}-${process.pid}`,tempPath;try{let tempDir=
|
|
5750
|
+
`);return{success:!1,failedHunkIndex:hunkIdx,error:{hunkIndex:hunkIdx,type:"context-mismatch",message:`Context mismatch in hunk ${hunkIdx+1} at line ${searchStart+1}: expected context does not match file content`,expected:expectedContent.length>200?`${expectedContent.slice(0,200)}... (truncated)`:expectedContent,actual:actualContent.length>200?`${actualContent.slice(0,200)}... (truncated)`:actualContent,line:searchStart+1}}}}return{success:!0,appliedLines:fileLines}}function atomicWriteFileSync2(targetPath,content){let dir=path166.dirname(targetPath);mkdirSync42(dir,{recursive:!0});let tempPrefix=`.apply-patch-${Date.now()}-${process.pid}`,tempPath;try{let tempDir=realpathSync20(mkdtempSync3(path166.join(dir,tempPrefix)));tempPath=path166.join(tempDir,"content")}catch{tempPath=path166.join(dir,`${tempPrefix}.tmp`)}try{writeFileSync26(tempPath,content,"utf-8"),renameSync29(tempPath,targetPath)}finally{if(existsSync93(tempPath))try{unlinkSync26(tempPath)}catch{}let tempDir=path166.dirname(tempPath);if(tempDir!==dir&&existsSync93(tempDir))try{rmdirSync2(tempDir)}catch{}}}function detectLineEnding(content){return content.includes(`\r
|
|
5751
5751
|
`)?`\r
|
|
5752
5752
|
`:`
|
|
5753
5753
|
`}function ensureFinalNewline(content,originalEndsWithNewline){if(originalEndsWithNewline&&!content.endsWith(`
|
|
@@ -5889,7 +5889,7 @@ Regenerated on: save_plan and phase_complete.
|
|
|
5889
5889
|
`;_fsInternals.writeFileSync(mdPath,header+md)}catch(error93){console.warn(`[checkpoint] Failed to write SWARM_PLAN checkpoint: ${error93 instanceof Error?error93.message:String(error93)}`)}}init_ledger();init_manager();init_curator_llm_factory();init_zod();init_config2();init_curator_decision_helpers();function computeDecayExpiry(memory,halfLifeDays,_now=new Date){if(memory.kind==="scratch")return;let halfLife=halfLifeDays[memory.kind]??0;if(halfLife<=0)return;let created=Date.parse(memory.createdAt);if(!Number.isFinite(created))return;let candidateMs=created+halfLife*86400000,existing=memory.expiresAt?Date.parse(memory.expiresAt):void 0;if(existing!==void 0&&Number.isFinite(existing)&&existing<=candidateMs)return;let candidate=new Date(candidateMs).toISOString();if(memory.expiresAt===candidate)return;return candidate}function isPastDecayHorizon(memory,halfLifeDays,now=new Date){if(memory.kind==="scratch")return!1;let halfLife=halfLifeDays[memory.kind]??0;if(halfLife<=0)return!1;let created=Date.parse(memory.createdAt);if(!Number.isFinite(created))return!1;return created+halfLife*86400000<=now.getTime()}init_scoring();var CONSOLIDATION_AGENT_ROLE="curator_consolidation",DistilledFactSchema=exports_external.object({text:exports_external.string().min(1).max(2000),kind:exports_external.enum(["user_preference","project_fact","architecture_decision","repo_convention","api_finding","code_pattern","test_pattern","failure_pattern","security_note","evidence","todo","scratch"]),confidence:exports_external.number().min(0).max(1),contradictsMemoryId:exports_external.string().regex(/^mem_[a-f0-9]{16}$/).optional()}),DistillationOutputSchema=exports_external.object({facts:exports_external.array(DistilledFactSchema).max(50)});function parseDistillationOutput(raw){let candidates=[],fenceMatch=raw.match(/```(?:json)?\s*([\s\S]*?)```/i);if(fenceMatch?.[1])candidates.push(fenceMatch[1].trim());let firstBrace=raw.indexOf("{"),lastBrace=raw.lastIndexOf("}");if(firstBrace!==-1&&lastBrace>firstBrace)candidates.push(raw.slice(firstBrace,lastBrace+1));candidates.push(raw.trim());for(let candidate of candidates)try{return DistillationOutputSchema.parse(JSON.parse(candidate)).facts}catch{}return[]}function deriveDecision(fact,existing,options){if(fact.text.includes(MEMORY_RECALL_SENTINEL))return{type:"skip",fact,reason:"contains recall sentinel"};if(fact.kind==="scratch")return{type:"skip",fact,reason:"scratch is not promoted to semantic memory"};let eligible=DURABLE_MEMORY_KINDS.has(fact.kind)&&fact.text.length<=CURATOR_PROMOTED_MEMORY_MAX_TEXT_LENGTH&&fact.confidence>=options.autoApplyMinConfidence,factTokens=tokenize(fact.text);for(let memory of existing)if(jaccard(factTokens,tokenize(memory.text))>=options.jaccardThreshold)return{type:"dedup",fact,duplicateOf:memory.id};if(fact.contradictsMemoryId){let target=existing.find((m)=>m.id===fact.contradictsMemoryId);if(target&&eligible)return{type:"supersede",fact,oldMemoryId:target.id};return{type:"proposal",fact,reason:target?"contradiction not auto-appliable (kind/length/confidence)":"contradiction target not found"}}if(!eligible){let reason=!DURABLE_MEMORY_KINDS.has(fact.kind)?`kind ${fact.kind} is not auto-promotable`:fact.text.length>CURATOR_PROMOTED_MEMORY_MAX_TEXT_LENGTH?"text exceeds promotable length":"confidence below auto-apply threshold";return{type:"proposal",fact,reason}}return{type:"add",fact}}function hasRealEvidence(evidenceRefs){return evidenceRefs.some((r)=>/^https?:\/\//i.test(r)||/^[a-f0-9]{40}$/i.test(r)||r.includes("/")||r.includes("\\"))}function sourceForDistilled(evidenceRefs,phaseNumber){let url3=evidenceRefs.find((r)=>/^https?:\/\//i.test(r));if(url3)return{type:"web",url:url3,createdBy:"curator_consolidation"};let file3=evidenceRefs.find((r)=>r.includes("/")||r.includes("\\"));if(file3)return{type:"file",filePath:file3,createdBy:"curator_consolidation"};return{type:"agent",ref:`consolidation:phase-${phaseNumber}`,createdBy:"curator_consolidation"}}function buildDistillationPrompt(cluster,relatedExisting){let episodic=cluster.map((p,i)=>{let text=p.proposedRecord?.text??p.rationale;return`[E${i+1}] kind=${p.proposedRecord?.kind??"n/a"} | ${text}`}).join(`
|
|
5890
5890
|
`),existing=relatedExisting.slice(0,20).map((m)=>`[${m.id}] kind=${m.kind} | ${m.text}`).join(`
|
|
5891
5891
|
`);return["You are consolidating raw episodic memory into durable semantic facts.","","Episodic events (verbatim):",episodic,"","Existing durable memories (for dedup/contradiction):",existing||"(none)","",'Emit STRICT JSON only: {"facts":[{"text":..,"kind":..,"confidence":0-1,"contradictsMemoryId"?:"mem_..."}]}',"Rules: only emit facts directly supported by the cited episodic evidence.","If uncertain, omit the fact (emit fewer facts or an empty array).",`Use durable kinds (${Array.from(DURABLE_MEMORY_KINDS).join(", ")}); keep each fact under ${CURATOR_PROMOTED_MEMORY_MAX_TEXT_LENGTH} characters.`,"Set contradictsMemoryId only when a fact directly conflicts with an existing memory above.",'Never include the literal text "## Retrieved Swarm Memory".'].join(`
|
|
5892
|
-
`)}function aggregateEvidence(cluster,phaseNumber){let refs=new Set;for(let p of cluster)for(let ref of p.evidenceRefs)refs.add(ref);let list=Array.from(refs).slice(0,19);return list.push(`consolidation:phase-${phaseNumber}`),list}async function runConsolidationPass(input,deps){let{phaseNumber,runId,config:config3}=input,consolidation=config3.consolidation,base={skipped:!0,phaseNumber,clusterCount:0,clustersDeferred:0,decisionsEmitted:0,added:0,superseded:0,contradictionsDetected:0,deduped:0,proposed:0,memoriesDecayed:0,errored:0};if(!config3.enabled||!consolidation.enabled||!deps.gateway.isEnabled())return{...base,skipReason:"disabled"};let priorLog=await deps.readLog();if(priorLog.some((r)=>r.phaseNumber===phaseNumber))return{...base,skipReason:"already_consolidated"};let processedBefore=new Set(priorLog.flatMap((r)=>r.processedProposalIds)),startedAt=deps.now().toISOString(),logKey=runId??"unknown";await deps.logEvent({event:"consolidation_started",runId:logKey,phaseNumber,timestamp:startedAt});let pendingProposals=(await deps.gateway.listProposals({status:"pending"})).filter((p)=>p.proposedBy?.agentRole!==CONSOLIDATION_AGENT_ROLE&&!processedBefore.has(p.id)).sort((a,b)=>a.id.localeCompare(b.id)),existingMemories=await deps.gateway.listMemories({}),clusters=clusterByJaccard(pendingProposals,(p)=>p.proposedRecord?.text??p.rationale,consolidation.jaccardThreshold),processable=clusters.slice(0,consolidation.maxClustersPerPass),clustersDeferred=Math.max(0,clusters.length-processable.length);await deps.logEvent({event:"cluster_count",runId:logKey,phaseNumber,clusterCount:clusters.length});let result={...base,skipped:!1,clusterCount:clusters.length,clustersDeferred},processedProposalIds=new Set;if(!deps.llmDelegate){if(result.memoriesDecayed=await applyDecay(existingMemories,input,deps),deps.signal?.aborted)return{...result,skipped:!0,skipReason:"aborted"};return await finalize2(input,deps,result,startedAt,processedProposalIds),{...result,skipReason:"no_llm_delegate_decay_only"}}let seenFactTexts=new Set;for(let cluster of processable){if(deps.signal?.aborted)return{...result,skipped:!0,skipReason:"aborted"};for(let p of cluster)processedProposalIds.add(p.id);let raw;try{let prompt=buildDistillationPrompt(cluster,existingMemories);raw=await deps.llmDelegate("",prompt,deps.signal)}catch{result.errored++;continue}let facts=parseDistillationOutput(raw),evidenceRefs=aggregateEvidence(cluster,phaseNumber);for(let fact of facts){let normalized=fact.text.replace(/\s+/g," ").trim().toLowerCase();if(seenFactTexts.has(normalized))continue;seenFactTexts.add(normalized);let plan=deriveDecision(fact,existingMemories,{autoApplyMinConfidence:consolidation.autoApplyMinConfidence,jaccardThreshold:consolidation.jaccardThreshold});try{await executePlan(plan,evidenceRefs,input,deps,result)}catch{result.errored++}}}if(deps.signal?.aborted)return{...result,skipped:!0,skipReason:"aborted"};if(result.memoriesDecayed=await applyDecay(existingMemories,input,deps),deps.signal?.aborted)return{...result,skipped:!0,skipReason:"aborted"};return await finalize2(input,deps,result,startedAt,processedProposalIds),result}async function executePlan(plan,evidenceRefs,input,deps,result){let{phaseNumber}=input;if(plan.type==="skip")return;if(plan.type==="dedup"){result.deduped++;return}let newRecord={kind:plan.fact.kind,text:plan.fact.text,confidence:plan.fact.confidence,stability:"durable",source:sourceForDistilled(evidenceRefs,phaseNumber),metadata:{consolidatedFromPhase:phaseNumber}},rationale=`consolidation phase ${phaseNumber}`;if(((plan.type==="add"||plan.type==="supersede")&&EVIDENCE_REQUIRED_KINDS.has(plan.fact.kind)&&!hasRealEvidence(evidenceRefs)?"proposal":plan.type)==="proposal"){await deps.gateway.propose({operation:plan.type==="supersede"?"supersede":"add",kind:plan.fact.kind,text:plan.fact.text,rationale:plan.type==="proposal"?`${rationale}: ${plan.reason}`:`${rationale}: evidence-required kind lacks real evidence source`,evidenceRefs,...plan.type==="supersede"?{targetMemoryId:plan.oldMemoryId}:{}}),result.proposed++;return}if(plan.type==="supersede"){let proposal2=await deps.gateway.propose({operation:"supersede",kind:plan.fact.kind,text:plan.fact.text,targetMemoryId:plan.oldMemoryId,rationale,evidenceRefs});if(proposal2.status!=="pending"){result.proposed++;return}await deps.gateway.applyCuratorDecision({action:"supersede",proposalId:proposal2.id,oldMemoryId:plan.oldMemoryId,replacement:newRecord,reason:`contradiction superseded during phase ${phaseNumber} consolidation`}),result.superseded++,result.contradictionsDetected++,result.decisionsEmitted++;return}let proposal=await deps.gateway.propose({operation:"add",kind:plan.fact.kind,text:plan.fact.text,rationale,evidenceRefs});if(proposal.status!=="pending"){result.proposed++;return}await deps.gateway.applyCuratorDecision({action:"add",proposalId:proposal.id,memory:newRecord}),result.added++,result.decisionsEmitted++}async function applyDecay(memories,input,deps){let decayed=0,halfLives=input.config.consolidation.decayHalfLifeDays,now=deps.now();for(let memory of memories){if(deps.signal?.aborted)break;if(memory.metadata.deleted===!0||memory.supersededBy)continue;if(isPastDecayHorizon(memory,halfLives,now))continue;let nextExpiry=computeDecayExpiry(memory,halfLives,now);if(!nextExpiry)continue;try{await deps.gateway.upsertCurated({...memory,expiresAt:nextExpiry}),decayed++}catch{}}return decayed}async function finalize2(input,deps,result,startedAt,processedProposalIds){let{phaseNumber,runId}=input,logKey=runId??"unknown",completedAt=deps.now().toISOString();await deps.logEvent({event:"decisions_emitted",runId:logKey,phaseNumber,decisionsEmitted:result.decisionsEmitted}),await deps.logEvent({event:"contradictions_detected",runId:logKey,phaseNumber,contradictionsDetected:result.contradictionsDetected}),await deps.logEvent({event:"memories_decayed",runId:logKey,phaseNumber,memoriesDecayed:result.memoriesDecayed}),await deps.logEvent({event:"consolidation_completed",runId:logKey,phaseNumber,clusterCount:result.clusterCount,decisionsEmitted:result.decisionsEmitted,contradictionsDetected:result.contradictionsDetected,memoriesDecayed:result.memoriesDecayed,timestamp:completedAt}),await deps.appendLog({phaseNumber,runId,startedAt,completedAt,clusterCount:result.clusterCount,clustersDeferred:result.clustersDeferred,decisionsEmitted:result.decisionsEmitted,added:result.added,superseded:result.superseded,contradictionsDetected:result.contradictionsDetected,deduped:result.deduped,proposed:result.proposed,memoriesDecayed:result.memoriesDecayed,errored:result.errored,processedProposalIds:Array.from(processedProposalIds)})}init_consolidation_log();init_gateway();init_run_log();var CONSOLIDATION_TIMEOUT_MS=300000,runningByDirectory2=new Map;async function runMemoryConsolidation(req){let existing=runningByDirectory2.get(req.directory);if(existing)return existing;let run=(async()=>{if(!req.config.enabled||!req.config.consolidation.enabled)return{started:!1,reason:"disabled"};let gateway=createMemoryGateway({directory:req.directory,sessionID:req.sessionId,runId:req.sessionId,agentRole:"curator_consolidation"},{config:req.config}),controller=new AbortController,timer=setTimeout(()=>controller.abort(),CONSOLIDATION_TIMEOUT_MS);timer.unref?.();try{if(!gateway.isEnabled())return{started:!1,reason:"disabled"};let llmDelegate=createCuratorLLMDelegate(req.directory,"consolidation",req.sessionId),result=await runConsolidationPass({directory:req.directory,phaseNumber:req.phase,runId:req.sessionId,config:req.config},{gateway,llmDelegate,now:()=>new Date,logEvent:(event)=>appendMemoryRunLog(req.directory,req.sessionId,event),readLog:()=>readConsolidationLog(req.directory),appendLog:(record3)=>appendConsolidationLog(req.directory,record3),signal:controller.signal});return{started:!result.skipped,reason:result.skipReason,result}}finally{clearTimeout(timer),await gateway.dispose()}})();runningByDirectory2.set(req.directory,run);try{return await run}finally{runningByDirectory2.delete(req.directory)}}function runMemoryConsolidationFireAndForget(req,onComplete,onError){queueMicrotask(()=>{runMemoryConsolidation(req).then(onComplete).catch(onError)})}init_skill_consolidation();init_snapshot_writer();init_state2();init_telemetry();init_state();init_file_locks();import*as fs119 from"node:fs";import*as path196 from"node:path";init_state4();var DEFAULT_CONFIG3={phase_reviewer:!0,phase_critic:!0,integrated_diff_required:!1};function defaultReadPlanJson(dir){try{let planPath=path196.join(dir,".swarm","plan.json");if(!fs119.existsSync(planPath))return null;let raw=fs119.readFileSync(planPath,"utf-8"),plan=JSON.parse(raw);if(typeof plan!=="object"||plan===null||!Array.isArray(plan.phases))return null;return plan}catch{return null}}function readReviewerEvidenceFromFile(directory,phase){try{let evidencePath=path196.join(directory,".swarm","evidence",String(phase),"lean-turbo-reviewer.json");if(!fs119.existsSync(evidencePath))return null;let raw=fs119.readFileSync(evidencePath,"utf-8"),parsed=JSON.parse(raw);if(typeof parsed!=="object"||parsed===null||typeof parsed.verdict!=="string")return null;let verdict=parsed.verdict;if(verdict!=="APPROVED"&&verdict!=="NEEDS_REVISION"&&verdict!=="REJECTED")return null;return parsed}catch{return null}}function readCriticEvidenceFromFile(directory,phase){try{let evidencePath=path196.join(directory,".swarm","evidence",String(phase),"lean-turbo-critic.json");if(!fs119.existsSync(evidencePath))return null;let raw=fs119.readFileSync(evidencePath,"utf-8"),parsed=JSON.parse(raw);if(typeof parsed!=="object"||parsed===null||typeof parsed.verdict!=="string")return null;let verdict=parsed.verdict;if(verdict!=="APPROVED"&&verdict!=="NEEDS_REVISION"&&verdict!=="REJECTED"&&verdict!=="ESCALATE_TO_HUMAN")return null;return parsed}catch{return null}}function listLaneEvidenceSync(directory,phase){let evidenceDir=path196.join(directory,".swarm","evidence",String(phase),"lean-turbo"),entries;try{entries=fs119.readdirSync(evidenceDir)}catch{return[]}let laneIds=[];for(let entry of entries){if(!entry.endsWith(".json")||entry==="lean-turbo-phase.json")continue;laneIds.push(entry.slice(0,-5))}return laneIds}var _internals127={listActiveLocks,readPersisted:readPersisted3,readPlanJson:defaultReadPlanJson,readReviewerEvidence:readReviewerEvidenceFromFile,readCriticEvidence:readCriticEvidenceFromFile,listLaneEvidence,listLaneEvidenceSync,verifyLeanTurboPhaseReady};function validatePersistedShape(persisted){if(typeof persisted!=="object"||persisted===null)return!1;if(Array.isArray(persisted))return!1;if(typeof persisted.sessions!=="object")return!1;if(persisted.sessions===null)return!1;if(Array.isArray(persisted.sessions))return!1;return!0}function validateLanesArray(lanes){if(!Array.isArray(lanes))return!1;for(let lane of lanes){if(typeof lane!=="object"||lane===null)return!1;if(typeof lane.laneId!=="string")return!1;if(typeof lane.status!=="string")return!1}return!0}function validateDegradedTasksArray(degradedTasks){if(!Array.isArray(degradedTasks))return!1;for(let dt of degradedTasks){if(typeof dt!=="object"||dt===null)return!1;if(typeof dt.taskId!=="string")return!1}return!0}function verifyLeanTurboPhaseReady(directory,phase,sessionIDOrConfig,config3){let sessionID=typeof sessionIDOrConfig==="string"?sessionIDOrConfig:void 0,mergedConfig={...DEFAULT_CONFIG3,...typeof sessionIDOrConfig==="object"&&sessionIDOrConfig!==null?sessionIDOrConfig:config3??DEFAULT_CONFIG3},statePath=path196.join(directory,".swarm","turbo-state.json");if(!fs119.existsSync(statePath))return{ok:!1,reason:"Lean Turbo state unreadable or missing"};let persisted=_internals127.readPersisted(directory);if(!persisted)return{ok:!1,reason:"Lean Turbo state unreadable or missing"};if(!validatePersistedShape(persisted))return{ok:!1,reason:"Lean Turbo state unreadable or missing"};let runState=null;for(let sessionState of Object.values(persisted.sessions))if(typeof sessionState==="object"&&sessionState!==null&&sessionState.status==="running"&&sessionState.phase===phase&&sessionState.strategy==="lean"&&sessionState.sessionID===sessionID){runState=sessionState;break}if(!runState&&sessionID===void 0){for(let sessionState of Object.values(persisted.sessions))if(typeof sessionState==="object"&&sessionState!==null&&sessionState.status==="running"&&sessionState.phase===phase&&sessionState.strategy==="lean"){runState=sessionState;break}}if(!runState)return{ok:!1,reason:sessionID?`No active Lean Turbo session for phase ${phase} and session ${sessionID}`:`No active Lean Turbo session for phase ${phase}`};if(!validateLanesArray(runState.lanes))return{ok:!1,reason:`No active Lean Turbo session for phase ${phase}`};if(!validateDegradedTasksArray(runState.degradedTasks))return{ok:!1,reason:`No active Lean Turbo session for phase ${phase}`};if(runState.lanes.length===0&&(!Array.isArray(runState.serializedTasks)||runState.serializedTasks.length===0)&&(!Array.isArray(runState.degradedTasks)||runState.degradedTasks.length===0))return{ok:!1,reason:`No lane plan or fallback tasks found for phase ${phase}`};let laneIds=runState.lanes.map((l)=>l.laneId);if(runState.lanes.length>0){for(let lane of runState.lanes)if(lane.status!=="completed"&&lane.status!=="failed")return{ok:!1,reason:`Lane ${lane.laneId} is not completed (status: ${lane.status})`}}if(runState.lanes.length>0){let evidenceLaneIds=new Set(_internals127.listLaneEvidenceSync(directory,phase));for(let lane of runState.lanes)if((lane.status==="completed"||lane.status==="failed")&&!evidenceLaneIds.has(lane.laneId))return{ok:!1,reason:`Lane ${lane.laneId} is ${lane.status} but lane evidence file is missing`}}let activeLocks=_internals127.listActiveLocks(directory),phaseLaneIds=new Set(laneIds);for(let lock of activeLocks)if(lock.laneId&&phaseLaneIds.has(lock.laneId))return{ok:!1,reason:`Active locks remain for lane ${lock.laneId}`};let laneTaskIds=new Set;for(let lane of runState.lanes)if(Array.isArray(lane.taskIds))for(let taskId of lane.taskIds)laneTaskIds.add(taskId);let serialDegradedTasks=runState.degradedTasks.filter((dt)=>!laneTaskIds.has(dt.taskId));if(serialDegradedTasks.length>0){let plan=_internals127.readPlanJson(directory);if(!plan)return{ok:!1,reason:"Cannot verify degraded task status: plan.json unreadable or malformed"};for(let dt of serialDegradedTasks){if(!Array.isArray(plan.phases))return{ok:!1,reason:`Cannot verify degraded task ${dt.taskId}: plan.json malformed (phases is not an array)`};let planPhase=plan.phases.find((p)=>p&&typeof p==="object"&&p!==null&&p.id===phase);if(!planPhase)return{ok:!1,reason:`Cannot verify degraded task ${dt.taskId}: phase ${phase} not found in plan.json`};if(!Array.isArray(planPhase.tasks))return{ok:!1,reason:`Cannot verify degraded task ${dt.taskId}: plan.json malformed (phase ${phase} tasks is not an array)`};let task=planPhase.tasks.find((t)=>t&&typeof t==="object"&&t!==null&&t.id===dt.taskId);if(!task)return{ok:!1,reason:`Degraded task ${dt.taskId} not found in plan`};if(task.status!=="completed")return{ok:!1,reason:`Degraded task ${dt.taskId} not yet completed via standard flow`}}}let serializedTasks=runState.serializedTasks;if(Array.isArray(serializedTasks)&&serializedTasks.length>0){let plan=_internals127.readPlanJson(directory);if(!plan)return{ok:!1,reason:"Cannot verify serialized task status: plan.json unreadable or malformed"};if(!Array.isArray(plan.phases))return{ok:!1,reason:"Cannot verify serialized tasks: plan.json malformed (phases is not an array)"};let planPhase=plan.phases.find((p)=>p&&typeof p==="object"&&p!==null&&p.id===phase);if(!planPhase)return{ok:!1,reason:`Cannot verify serialized tasks: phase ${phase} not found in plan.json`};if(!Array.isArray(planPhase.tasks))return{ok:!1,reason:`Cannot verify serialized tasks: plan.json malformed (phase ${phase} tasks is not an array)`};for(let serTaskId of serializedTasks){let task=planPhase.tasks.find((t)=>t&&typeof t==="object"&&t!==null&&t.id===serTaskId);if(!task)return{ok:!1,reason:`Serialized task ${serTaskId} not found in plan`};if(task.status!=="completed")return{ok:!1,reason:`Serialized task ${serTaskId} not yet completed (status: ${task.status})`}}}if(mergedConfig.integrated_diff_required){let evidencePath=path196.join(directory,".swarm","evidence",String(phase),"lean-turbo-phase.json"),hasDiff=!1;try{let content=fs119.readFileSync(evidencePath,"utf-8");hasDiff=!!JSON.parse(content).integratedDiffSummary}catch{}if(!hasDiff)return{ok:!1,reason:`Integrated diff summary is required but missing for phase ${phase}`}}let reviewerVerdict=runState.lastReviewerVerdict;if(!reviewerVerdict)reviewerVerdict=_internals127.readReviewerEvidence(directory,phase)?.verdict??void 0;if(mergedConfig.phase_reviewer){if(reviewerVerdict!=="APPROVED")return{ok:!1,reason:"Integrated reviewer approval missing or rejected"}}let criticVerdict=runState.lastCriticVerdict;if(!criticVerdict)criticVerdict=_internals127.readCriticEvidence(directory,phase)?.verdict??void 0;if(mergedConfig.phase_critic){if(criticVerdict!=="APPROVED")return{ok:!1,reason:"Integrated critic approval missing or rejected"}}return{ok:!0,reason:`Phase ${phase} is ready to advance`,evidence:{lanes:laneIds,degradedTasks:runState.degradedTasks.map((dt)=>dt.taskId),reviewerVerdict:reviewerVerdict??runState.lastReviewerVerdict,criticVerdict:criticVerdict??runState.lastCriticVerdict}}}init_logger();init_create_tool();init_store();async function runArchitectureSupervisorGate(ctx){let{phase,dir,pluginConfig,agentsDispatched,safeWarn}=ctx,asConfig=pluginConfig.architectural_supervision,summarizeFindings=(findings)=>{if(!Array.isArray(findings)||findings.length===0)return"";let details=findings.map((f)=>f&&typeof f==="object"&&typeof f.description==="string"?f.description:void 0).filter((d)=>Boolean(d));return details.length>0?`
|
|
5892
|
+
`)}function aggregateEvidence(cluster,phaseNumber){let refs=new Set;for(let p of cluster)for(let ref of p.evidenceRefs)refs.add(ref);let list=Array.from(refs).slice(0,19);return list.push(`consolidation:phase-${phaseNumber}`),list}async function runConsolidationPass(input,deps){let{phaseNumber,runId,config:config3}=input,consolidation=config3.consolidation,base={skipped:!0,phaseNumber,clusterCount:0,clustersDeferred:0,decisionsEmitted:0,added:0,superseded:0,contradictionsDetected:0,deduped:0,proposed:0,memoriesDecayed:0,errored:0};if(!config3.enabled||!consolidation.enabled||!deps.gateway.isEnabled())return{...base,skipReason:"disabled"};let priorLog=await deps.readLog();if(priorLog.some((r)=>r.phaseNumber===phaseNumber))return{...base,skipReason:"already_consolidated"};let processedBefore=new Set(priorLog.flatMap((r)=>r.processedProposalIds)),startedAt=deps.now().toISOString(),logKey=runId??"unknown";await deps.logEvent({event:"consolidation_started",runId:logKey,phaseNumber,timestamp:startedAt});let pendingProposals=(await deps.gateway.listProposals({status:"pending"})).filter((p)=>p.proposedBy?.agentRole!==CONSOLIDATION_AGENT_ROLE&&!processedBefore.has(p.id)).sort((a,b)=>a.id.localeCompare(b.id)),existingMemories=await deps.gateway.listMemories({}),clusters=clusterByJaccard(pendingProposals,(p)=>p.proposedRecord?.text??p.rationale,consolidation.jaccardThreshold),processable=clusters.slice(0,consolidation.maxClustersPerPass),clustersDeferred=Math.max(0,clusters.length-processable.length);await deps.logEvent({event:"cluster_count",runId:logKey,phaseNumber,clusterCount:clusters.length});let result={...base,skipped:!1,clusterCount:clusters.length,clustersDeferred},processedProposalIds=new Set;if(!deps.llmDelegate){if(result.memoriesDecayed=await applyDecay(existingMemories,input,deps),deps.signal?.aborted)return{...result,skipped:!0,skipReason:"aborted"};return await finalize2(input,deps,result,startedAt,processedProposalIds),{...result,skipReason:"no_llm_delegate_decay_only"}}let seenFactTexts=new Set;for(let cluster of processable){if(deps.signal?.aborted)return{...result,skipped:!0,skipReason:"aborted"};for(let p of cluster)processedProposalIds.add(p.id);let raw;try{let prompt=buildDistillationPrompt(cluster,existingMemories);raw=await deps.llmDelegate("",prompt,deps.signal)}catch{result.errored++;continue}let facts=parseDistillationOutput(raw),evidenceRefs=aggregateEvidence(cluster,phaseNumber);for(let fact of facts){let normalized=fact.text.replace(/\s+/g," ").trim().toLowerCase();if(seenFactTexts.has(normalized))continue;seenFactTexts.add(normalized);let plan=deriveDecision(fact,existingMemories,{autoApplyMinConfidence:consolidation.autoApplyMinConfidence,jaccardThreshold:consolidation.jaccardThreshold});try{await executePlan(plan,evidenceRefs,input,deps,result)}catch{result.errored++}}}if(deps.signal?.aborted)return{...result,skipped:!0,skipReason:"aborted"};if(result.memoriesDecayed=await applyDecay(existingMemories,input,deps),deps.signal?.aborted)return{...result,skipped:!0,skipReason:"aborted"};return await finalize2(input,deps,result,startedAt,processedProposalIds),result}async function executePlan(plan,evidenceRefs,input,deps,result){let{phaseNumber}=input;if(plan.type==="skip")return;if(plan.type==="dedup"){result.deduped++;return}let newRecord={kind:plan.fact.kind,text:plan.fact.text,confidence:plan.fact.confidence,stability:"durable",source:sourceForDistilled(evidenceRefs,phaseNumber),metadata:{consolidatedFromPhase:phaseNumber}},rationale=`consolidation phase ${phaseNumber}`;if(((plan.type==="add"||plan.type==="supersede")&&EVIDENCE_REQUIRED_KINDS.has(plan.fact.kind)&&!hasRealEvidence(evidenceRefs)?"proposal":plan.type)==="proposal"){await deps.gateway.propose({operation:plan.type==="supersede"?"supersede":"add",kind:plan.fact.kind,text:plan.fact.text,rationale:plan.type==="proposal"?`${rationale}: ${plan.reason}`:`${rationale}: evidence-required kind lacks real evidence source`,evidenceRefs,...plan.type==="supersede"?{targetMemoryId:plan.oldMemoryId}:{}}),result.proposed++;return}if(plan.type==="supersede"){let proposal2=await deps.gateway.propose({operation:"supersede",kind:plan.fact.kind,text:plan.fact.text,targetMemoryId:plan.oldMemoryId,rationale,evidenceRefs});if(proposal2.status!=="pending"){result.proposed++;return}await deps.gateway.applyCuratorDecision({action:"supersede",proposalId:proposal2.id,oldMemoryId:plan.oldMemoryId,replacement:newRecord,reason:`contradiction superseded during phase ${phaseNumber} consolidation`}),result.superseded++,result.contradictionsDetected++,result.decisionsEmitted++;return}let proposal=await deps.gateway.propose({operation:"add",kind:plan.fact.kind,text:plan.fact.text,rationale,evidenceRefs});if(proposal.status!=="pending"){result.proposed++;return}await deps.gateway.applyCuratorDecision({action:"add",proposalId:proposal.id,memory:newRecord}),result.added++,result.decisionsEmitted++}async function applyDecay(memories,input,deps){let decayed=0,halfLives=input.config.consolidation.decayHalfLifeDays,now=deps.now();for(let memory of memories){if(deps.signal?.aborted)break;if(memory.metadata.deleted===!0||memory.supersededBy)continue;if(isPastDecayHorizon(memory,halfLives,now))continue;let nextExpiry=computeDecayExpiry(memory,halfLives,now);if(!nextExpiry)continue;try{await deps.gateway.upsertCurated({...memory,expiresAt:nextExpiry}),decayed++}catch{}}return decayed}async function finalize2(input,deps,result,startedAt,processedProposalIds){let{phaseNumber,runId}=input,logKey=runId??"unknown",completedAt=deps.now().toISOString();await deps.logEvent({event:"decisions_emitted",runId:logKey,phaseNumber,decisionsEmitted:result.decisionsEmitted}),await deps.logEvent({event:"contradictions_detected",runId:logKey,phaseNumber,contradictionsDetected:result.contradictionsDetected}),await deps.logEvent({event:"memories_decayed",runId:logKey,phaseNumber,memoriesDecayed:result.memoriesDecayed}),await deps.logEvent({event:"consolidation_completed",runId:logKey,phaseNumber,clusterCount:result.clusterCount,decisionsEmitted:result.decisionsEmitted,contradictionsDetected:result.contradictionsDetected,memoriesDecayed:result.memoriesDecayed,timestamp:completedAt}),await deps.appendLog({phaseNumber,runId,startedAt,completedAt,clusterCount:result.clusterCount,clustersDeferred:result.clustersDeferred,decisionsEmitted:result.decisionsEmitted,added:result.added,superseded:result.superseded,contradictionsDetected:result.contradictionsDetected,deduped:result.deduped,proposed:result.proposed,memoriesDecayed:result.memoriesDecayed,errored:result.errored,processedProposalIds:Array.from(processedProposalIds)})}init_consolidation_log();init_gateway();init_run_log();var CONSOLIDATION_TIMEOUT_MS=300000,runningByDirectory2=new Map;async function runMemoryConsolidation(req){let existing=runningByDirectory2.get(req.directory);if(existing)return existing;let run=(async()=>{if(!req.config.enabled||!req.config.consolidation.enabled)return{started:!1,reason:"disabled"};let gateway=createMemoryGateway({directory:req.directory,sessionID:req.sessionId,runId:req.sessionId,agentRole:"curator_consolidation"},{config:req.config}),controller=new AbortController,timer=setTimeout(()=>controller.abort(),CONSOLIDATION_TIMEOUT_MS);timer.unref?.();try{if(!gateway.isEnabled())return{started:!1,reason:"disabled"};let llmDelegate=createCuratorLLMDelegate(req.directory,"consolidation",req.sessionId),result=await runConsolidationPass({directory:req.directory,phaseNumber:req.phase,runId:req.sessionId,config:req.config},{gateway,llmDelegate,now:()=>new Date,logEvent:(event)=>appendMemoryRunLog(req.directory,req.sessionId,event),readLog:()=>readConsolidationLog(req.directory),appendLog:(record3)=>appendConsolidationLog(req.directory,record3),signal:controller.signal});return{started:!result.skipped,reason:result.skipReason,result}}finally{clearTimeout(timer),await gateway.dispose()}})();runningByDirectory2.set(req.directory,run);try{return await run}finally{runningByDirectory2.delete(req.directory)}}function runMemoryConsolidationFireAndForget(req,onComplete,onError){queueMicrotask(()=>{runMemoryConsolidation(req).then(onComplete).catch(onError)})}init_skill_consolidation();init_snapshot_writer();init_state2();init_telemetry();init_state();init_file_locks();import*as fs119 from"node:fs";import*as path196 from"node:path";init_state4();var DEFAULT_CONFIG3={phase_reviewer:!0,phase_critic:!0,integrated_diff_required:!1};function defaultReadPlanJson(dir){try{let planPath=path196.join(dir,".swarm","plan.json");if(!fs119.existsSync(planPath))return null;let raw=fs119.readFileSync(planPath,"utf-8"),plan=JSON.parse(raw);if(typeof plan!=="object"||plan===null||!Array.isArray(plan.phases))return null;return plan}catch{return null}}function readReviewerEvidenceFromFile(directory,phase){try{let evidencePath=path196.join(directory,".swarm","evidence",String(phase),"lean-turbo-reviewer.json");if(!fs119.existsSync(evidencePath))return null;let raw=fs119.readFileSync(evidencePath,"utf-8"),parsed=JSON.parse(raw);if(typeof parsed!=="object"||parsed===null||typeof parsed.verdict!=="string")return null;let verdict=parsed.verdict;if(verdict!=="APPROVED"&&verdict!=="NEEDS_REVISION"&&verdict!=="REJECTED")return null;return parsed}catch{return null}}function readCriticEvidenceFromFile(directory,phase){try{let evidencePath=path196.join(directory,".swarm","evidence",String(phase),"lean-turbo-critic.json");if(!fs119.existsSync(evidencePath))return null;let raw=fs119.readFileSync(evidencePath,"utf-8"),parsed=JSON.parse(raw);if(typeof parsed!=="object"||parsed===null||typeof parsed.verdict!=="string")return null;let verdict=parsed.verdict;if(verdict!=="APPROVED"&&verdict!=="NEEDS_REVISION"&&verdict!=="REJECTED"&&verdict!=="ESCALATE_TO_HUMAN")return null;return parsed}catch{return null}}function listLaneEvidenceSync(directory,phase){let evidenceDir=path196.join(directory,".swarm","evidence",String(phase),"lean-turbo"),entries;try{entries=fs119.readdirSync(evidenceDir)}catch{return[]}entries.sort();let laneIds=[];for(let entry of entries){if(!entry.endsWith(".json")||entry==="lean-turbo-phase.json")continue;laneIds.push(entry.slice(0,-5))}return laneIds}var _internals127={listActiveLocks,readPersisted:readPersisted3,readPlanJson:defaultReadPlanJson,readReviewerEvidence:readReviewerEvidenceFromFile,readCriticEvidence:readCriticEvidenceFromFile,listLaneEvidence,listLaneEvidenceSync,verifyLeanTurboPhaseReady};function validatePersistedShape(persisted){if(typeof persisted!=="object"||persisted===null)return!1;if(Array.isArray(persisted))return!1;if(typeof persisted.sessions!=="object")return!1;if(persisted.sessions===null)return!1;if(Array.isArray(persisted.sessions))return!1;return!0}function validateLanesArray(lanes){if(!Array.isArray(lanes))return!1;for(let lane of lanes){if(typeof lane!=="object"||lane===null)return!1;if(typeof lane.laneId!=="string")return!1;if(typeof lane.status!=="string")return!1}return!0}function validateDegradedTasksArray(degradedTasks){if(!Array.isArray(degradedTasks))return!1;for(let dt of degradedTasks){if(typeof dt!=="object"||dt===null)return!1;if(typeof dt.taskId!=="string")return!1}return!0}function verifyLeanTurboPhaseReady(directory,phase,sessionIDOrConfig,config3){let sessionID=typeof sessionIDOrConfig==="string"?sessionIDOrConfig:void 0,mergedConfig={...DEFAULT_CONFIG3,...typeof sessionIDOrConfig==="object"&&sessionIDOrConfig!==null?sessionIDOrConfig:config3??DEFAULT_CONFIG3},statePath=path196.join(directory,".swarm","turbo-state.json");if(!fs119.existsSync(statePath))return{ok:!1,reason:"Lean Turbo state unreadable or missing"};let persisted=_internals127.readPersisted(directory);if(!persisted)return{ok:!1,reason:"Lean Turbo state unreadable or missing"};if(!validatePersistedShape(persisted))return{ok:!1,reason:"Lean Turbo state unreadable or missing"};let runState=null;for(let sessionState of Object.values(persisted.sessions))if(typeof sessionState==="object"&&sessionState!==null&&sessionState.status==="running"&&sessionState.phase===phase&&sessionState.strategy==="lean"&&sessionState.sessionID===sessionID){runState=sessionState;break}if(!runState&&sessionID===void 0){for(let sessionState of Object.values(persisted.sessions))if(typeof sessionState==="object"&&sessionState!==null&&sessionState.status==="running"&&sessionState.phase===phase&&sessionState.strategy==="lean"){runState=sessionState;break}}if(!runState)return{ok:!1,reason:sessionID?`No active Lean Turbo session for phase ${phase} and session ${sessionID}`:`No active Lean Turbo session for phase ${phase}`};if(!validateLanesArray(runState.lanes))return{ok:!1,reason:`No active Lean Turbo session for phase ${phase}`};if(!validateDegradedTasksArray(runState.degradedTasks))return{ok:!1,reason:`No active Lean Turbo session for phase ${phase}`};if(runState.lanes.length===0&&(!Array.isArray(runState.serializedTasks)||runState.serializedTasks.length===0)&&(!Array.isArray(runState.degradedTasks)||runState.degradedTasks.length===0))return{ok:!1,reason:`No lane plan or fallback tasks found for phase ${phase}`};let laneIds=runState.lanes.map((l)=>l.laneId);if(runState.lanes.length>0){for(let lane of runState.lanes)if(lane.status!=="completed"&&lane.status!=="failed")return{ok:!1,reason:`Lane ${lane.laneId} is not completed (status: ${lane.status})`}}if(runState.lanes.length>0){let evidenceLaneIds=new Set(_internals127.listLaneEvidenceSync(directory,phase));for(let lane of runState.lanes)if((lane.status==="completed"||lane.status==="failed")&&!evidenceLaneIds.has(lane.laneId))return{ok:!1,reason:`Lane ${lane.laneId} is ${lane.status} but lane evidence file is missing`}}let activeLocks=_internals127.listActiveLocks(directory),phaseLaneIds=new Set(laneIds);for(let lock of activeLocks)if(lock.laneId&&phaseLaneIds.has(lock.laneId))return{ok:!1,reason:`Active locks remain for lane ${lock.laneId}`};let laneTaskIds=new Set;for(let lane of runState.lanes)if(Array.isArray(lane.taskIds))for(let taskId of lane.taskIds)laneTaskIds.add(taskId);let serialDegradedTasks=runState.degradedTasks.filter((dt)=>!laneTaskIds.has(dt.taskId));if(serialDegradedTasks.length>0){let plan=_internals127.readPlanJson(directory);if(!plan)return{ok:!1,reason:"Cannot verify degraded task status: plan.json unreadable or malformed"};for(let dt of serialDegradedTasks){if(!Array.isArray(plan.phases))return{ok:!1,reason:`Cannot verify degraded task ${dt.taskId}: plan.json malformed (phases is not an array)`};let planPhase=plan.phases.find((p)=>p&&typeof p==="object"&&p!==null&&p.id===phase);if(!planPhase)return{ok:!1,reason:`Cannot verify degraded task ${dt.taskId}: phase ${phase} not found in plan.json`};if(!Array.isArray(planPhase.tasks))return{ok:!1,reason:`Cannot verify degraded task ${dt.taskId}: plan.json malformed (phase ${phase} tasks is not an array)`};let task=planPhase.tasks.find((t)=>t&&typeof t==="object"&&t!==null&&t.id===dt.taskId);if(!task)return{ok:!1,reason:`Degraded task ${dt.taskId} not found in plan`};if(task.status!=="completed")return{ok:!1,reason:`Degraded task ${dt.taskId} not yet completed via standard flow`}}}let serializedTasks=runState.serializedTasks;if(Array.isArray(serializedTasks)&&serializedTasks.length>0){let plan=_internals127.readPlanJson(directory);if(!plan)return{ok:!1,reason:"Cannot verify serialized task status: plan.json unreadable or malformed"};if(!Array.isArray(plan.phases))return{ok:!1,reason:"Cannot verify serialized tasks: plan.json malformed (phases is not an array)"};let planPhase=plan.phases.find((p)=>p&&typeof p==="object"&&p!==null&&p.id===phase);if(!planPhase)return{ok:!1,reason:`Cannot verify serialized tasks: phase ${phase} not found in plan.json`};if(!Array.isArray(planPhase.tasks))return{ok:!1,reason:`Cannot verify serialized tasks: plan.json malformed (phase ${phase} tasks is not an array)`};for(let serTaskId of serializedTasks){let task=planPhase.tasks.find((t)=>t&&typeof t==="object"&&t!==null&&t.id===serTaskId);if(!task)return{ok:!1,reason:`Serialized task ${serTaskId} not found in plan`};if(task.status!=="completed")return{ok:!1,reason:`Serialized task ${serTaskId} not yet completed (status: ${task.status})`}}}if(mergedConfig.integrated_diff_required){let evidencePath=path196.join(directory,".swarm","evidence",String(phase),"lean-turbo-phase.json"),hasDiff=!1;try{let content=fs119.readFileSync(evidencePath,"utf-8");hasDiff=!!JSON.parse(content).integratedDiffSummary}catch{}if(!hasDiff)return{ok:!1,reason:`Integrated diff summary is required but missing for phase ${phase}`}}let reviewerVerdict=runState.lastReviewerVerdict;if(!reviewerVerdict)reviewerVerdict=_internals127.readReviewerEvidence(directory,phase)?.verdict??void 0;if(mergedConfig.phase_reviewer){if(reviewerVerdict!=="APPROVED")return{ok:!1,reason:"Integrated reviewer approval missing or rejected"}}let criticVerdict=runState.lastCriticVerdict;if(!criticVerdict)criticVerdict=_internals127.readCriticEvidence(directory,phase)?.verdict??void 0;if(mergedConfig.phase_critic){if(criticVerdict!=="APPROVED")return{ok:!1,reason:"Integrated critic approval missing or rejected"}}return{ok:!0,reason:`Phase ${phase} is ready to advance`,evidence:{lanes:laneIds,degradedTasks:runState.degradedTasks.map((dt)=>dt.taskId),reviewerVerdict:reviewerVerdict??runState.lastReviewerVerdict,criticVerdict:criticVerdict??runState.lastCriticVerdict}}}init_logger();init_create_tool();init_store();async function runArchitectureSupervisorGate(ctx){let{phase,dir,pluginConfig,agentsDispatched,safeWarn}=ctx,asConfig=pluginConfig.architectural_supervision,summarizeFindings=(findings)=>{if(!Array.isArray(findings)||findings.length===0)return"";let details=findings.map((f)=>f&&typeof f==="object"&&typeof f.description==="string"?f.description:void 0).filter((d)=>Boolean(d));return details.length>0?`
|
|
5893
5893
|
Findings: ${details.join("; ")}`:""},asBlocked=(reason,message)=>({blocked:!0,reason,message,agentsDispatched,agentsMissing:[],warnings:[]}),asEntry=null;try{asEntry=readSupervisorReportRaw(dir,phase)}catch(asError){return asBlocked("ARCH_SUPERVISOR_ERROR",`Phase ${phase} cannot be completed: architecture supervisor gate encountered an error. Error: ${String(asError)}`)}if(!asEntry)return asBlocked("ARCH_SUPERVISOR_REQUIRED",`Phase ${phase} cannot be completed: architectural_supervision gate mode is enabled and no architecture supervisor evidence was found at .swarm/evidence/${phase}/architecture-supervisor.json. Dispatch critic_architecture_supervisor with the phase + agent summaries, then call write_architecture_supervisor_evidence.`);let now=new Date,asTime=asEntry.timestamp?new Date(asEntry.timestamp):null;if(!asTime||Number.isNaN(asTime.getTime()))return asBlocked("ARCH_SUPERVISOR_INVALID_TIMESTAMP",`Phase ${phase} cannot be completed: architecture supervisor evidence has a missing or invalid timestamp.`);if(asTime.getTime()>now.getTime())return asBlocked("ARCH_SUPERVISOR_FUTURE_TIMESTAMP",`Phase ${phase} cannot be completed: architecture supervisor evidence timestamp is in the future.`);if(now.getTime()-asTime.getTime()>86400000)return asBlocked("ARCH_SUPERVISOR_STALE_EVIDENCE",`Phase ${phase} cannot be completed: architecture supervisor evidence is older than 24 hours. Re-run the supervisor for fresh review.`);if(typeof asEntry.phase_number!=="number"||asEntry.phase_number!==phase)return asBlocked("ARCH_SUPERVISOR_PHASE_MISMATCH",`Phase ${phase} cannot be completed: architecture supervisor evidence is for phase ${String(asEntry.phase_number)}, not phase ${phase}.`);let gateWarnings=[];if(asConfig?.provenance_verify===!0){let provenance=asEntry.provenance;if(!provenance||!provenance.agent_name&&!provenance.session_id)return asBlocked("ARCH_SUPERVISOR_MISSING_PROVENANCE",`Phase ${phase} cannot be completed: architecture supervisor evidence lacks provenance (agent_name or session_id). Evidence provenance verification is enabled.`)}else if(!asEntry.provenance||!asEntry.provenance.agent_name&&!asEntry.provenance.session_id){let msg=`Architecture supervisor evidence lacks provenance for phase ${phase}. Enable 'provenance_verify' in architectural_supervision config to enforce provenance verification.`;gateWarnings.push(msg),safeWarn(`[phase_complete] ${msg}`,void 0)}let asVerdict=asEntry.verdict;if(asVerdict==="REJECT")return asBlocked("ARCH_SUPERVISOR_REJECTED",`Phase ${phase} cannot be completed: architecture supervisor returned verdict 'REJECT'. Address the system-level findings before completing the phase.${summarizeFindings(asEntry.findings)}`);if(asVerdict==="CONCERNS"){if(asConfig?.allow_concerns_to_complete===!1)return asBlocked("ARCH_SUPERVISOR_CONCERNS",`Phase ${phase} cannot be completed: architecture supervisor returned verdict 'CONCERNS' and allow_concerns_to_complete is disabled.${summarizeFindings(asEntry.findings)}`);safeWarn(`[phase_complete] Architecture supervisor returned CONCERNS for phase ${phase} — proceeding (allow_concerns_to_complete is enabled)`,void 0)}else if(asVerdict!=="APPROVE")return asBlocked("ARCH_SUPERVISOR_INVALID",`Phase ${phase} cannot be completed: architecture supervisor evidence contains unrecognized verdict '${String(asVerdict)}'. Expected one of: APPROVE, CONCERNS, REJECT.`);return{blocked:!1,agentsDispatched,agentsMissing:[],warnings:gateWarnings}}async function runCompletionVerifyGate(ctx){let{phase,dir,agentsDispatched,safeWarn}=ctx;try{let completionResultRaw=await executeCompletionVerify({phase},dir),completionResult=JSON.parse(completionResultRaw);if(completionResult.status==="blocked")return{blocked:!0,reason:"COMPLETION_INCOMPLETE",message:`Phase ${phase} cannot be completed: ${completionResult.reason}`,agentsDispatched,agentsMissing:[],warnings:completionResult.blockedTasks?[`Blocked tasks: ${completionResult.blockedTasks.map((t)=>t.task_id).join(", ")}`]:[]};return{blocked:!1,agentsDispatched,agentsMissing:[],warnings:[]}}catch(completionError){return safeWarn("[phase_complete] Completion verify error (non-blocking):",completionError),{blocked:!1,agentsDispatched,agentsMissing:[],warnings:[]}}}init_effective_spec();import*as fs120 from"node:fs";import*as path197 from"node:path";init_qa_gate_profile();init_ledger();init_manager();init_utils3();init_state2();async function resolveGatePreamble(dir,sessionID){let plan=await loadPlan(dir);if(!plan)return{resolved:!1};let planId=derivePlanId(plan),planHash=computePlanHash(plan),profile=getProfile(dir,planId),overrides=(sessionID?swarmState.agentSessions.get(sessionID):void 0)?.qaGateSessionOverrides??{};if(!profile){let hasOverrides=Object.keys(overrides).length>0;return{resolved:hasOverrides,plan,planId,planHash,effectiveGates:hasOverrides?{...DEFAULT_QA_GATES,...overrides}:void 0}}let effective=getEffectiveGates(profile,overrides);return{resolved:!0,plan,planId,planHash,effectiveGates:effective}}async function runDriftGate(ctx){let{phase,dir,sessionID,agentsDispatched,safeWarn}=ctx,gateWarnings=[],driftCheckEnabled=!0,driftHasEffectiveSpec=!1;try{driftHasEffectiveSpec=readEffectiveSpecSync(dir)!==null;let preamble=await resolveGatePreamble(dir,sessionID);if(preamble.resolved)driftCheckEnabled=preamble.effectiveGates?.drift_check===!0}catch(gateLoadError){safeWarn("[phase_complete] QA gate profile load error, drift_check defaults to enabled:",gateLoadError)}if(!driftCheckEnabled)return{blocked:!1,agentsDispatched,agentsMissing:[],warnings:[`drift_check gate is disabled. Drift verification was skipped for phase ${phase}.`]};let phaseType;try{let planPath=path197.join(dir,".swarm","plan.json");if(fs120.existsSync(planPath)){let planRaw=fs120.readFileSync(planPath,"utf-8");phaseType=JSON.parse(planRaw).phases?.find((p)=>p.id===phase)?.type}}catch{}if(phaseType==="non-code")return{blocked:!1,agentsDispatched,agentsMissing:[],warnings:[`Phase ${phase} is annotated as 'non-code'. Drift verification was skipped per phase type annotation.`]};try{let driftEvidencePath=path197.join(dir,".swarm","evidence",String(phase),"drift-verifier.json"),driftVerdictFound=!1,driftVerdictApproved=!1;try{let driftEvidenceContent=fs120.readFileSync(driftEvidencePath,"utf-8"),entries=JSON.parse(driftEvidenceContent).entries??[];for(let entry of entries)if(typeof entry.type==="string"&&entry.type.includes("drift")&&typeof entry.verdict==="string"){if(driftVerdictFound=!0,!entry.provenance||!entry.provenance.agent_name&&!entry.provenance.session_id){let msg=`Drift verification evidence lacks provenance for phase ${phase}. Evidence should include agent_name or session_id for verification.`;gateWarnings.push(msg),safeWarn(`[phase_complete] ${msg}`,void 0)}if(entry.verdict==="approved")driftVerdictApproved=!0;if(entry.verdict==="rejected"||typeof entry.summary==="string"&&entry.summary.includes("NEEDS_REVISION"))return{blocked:!0,reason:"DRIFT_VERIFICATION_REJECTED",message:`Phase ${phase} cannot be completed: drift verifier returned verdict '${entry.verdict}'. Address the drift issues before completing the phase.`,agentsDispatched,agentsMissing:[],warnings:[]}}}catch(readError){if(readError.code!=="ENOENT")safeWarn("[phase_complete] Drift verifier evidence unreadable:",readError);driftVerdictFound=!1}if(!driftVerdictFound)if(!driftHasEffectiveSpec){let incompleteTaskCount=0,planParseable=!1;try{let planPath=path197.join(dir,".swarm","plan.json");if(fs120.existsSync(planPath)){let planRaw=fs120.readFileSync(planPath,"utf-8"),plan=JSON.parse(planRaw);planParseable=!0;let planPhase=plan.phases?.find((p)=>p.id===phase);if(planPhase?.tasks)incompleteTaskCount=planPhase.tasks.filter((t)=>t.status!=="completed"&&t.status!=="closed").length}}catch{}if(!planParseable)return{blocked:!1,agentsDispatched,agentsMissing:[],warnings:["No effective spec found and drift verification evidence missing — consider running critic_drift_verifier before phase completion."]};else if(incompleteTaskCount>0)return{blocked:!1,agentsDispatched,agentsMissing:[],warnings:[`No effective spec found and drift verification evidence missing. Phase ${phase} has ${incompleteTaskCount} incomplete task(s) in plan.json — consider running critic_drift_verifier before phase completion.`]};else return{blocked:!1,agentsDispatched,agentsMissing:[],warnings:[`No effective spec found. Phase ${phase} tasks are all completed in plan.json. Drift verification was skipped.`]}}else return{blocked:!0,reason:"DRIFT_VERIFICATION_MISSING",message:`Phase ${phase} cannot be completed: drift_check is enabled and drift verifier evidence not found at .swarm/evidence/${phase}/drift-verifier.json. Run drift verification before completing the phase.`,agentsDispatched,agentsMissing:[],warnings:[]};if(!driftVerdictApproved&&driftVerdictFound)return{blocked:!0,reason:"DRIFT_VERIFICATION_REJECTED",message:`Phase ${phase} cannot be completed: drift verifier verdict is not approved.`,agentsDispatched,agentsMissing:[],warnings:[]};return{blocked:!1,agentsDispatched,agentsMissing:[],warnings:gateWarnings}}catch(driftError){return{blocked:!0,reason:"DRIFT_VERIFICATION_ERROR",message:`Phase ${phase} cannot be completed: drift verification encountered an error: ${driftError instanceof Error?driftError.message:String(driftError)}. This is a hard block — resolve the error before completing the phase.`,agentsDispatched,agentsMissing:[],warnings:[]}}}init_qa_gate_profile();init_utils3();init_state2();import*as fs121 from"node:fs";import*as path198 from"node:path";function parseTimestampMs(value){if(typeof value!=="string")return null;let parsed=new Date(value).getTime();return Number.isNaN(parsed)?null:parsed}function latestRetroTimestampMsFromBundle(bundle,phase){if(!bundle)return null;let timestamps=[parseTimestampMs(bundle.created_at),parseTimestampMs(bundle.updated_at),...(bundle.entries??[]).filter((entry)=>entry.type==="retrospective"&&entry.phase_number===phase).map((entry)=>parseTimestampMs(entry.timestamp))].filter((timestamp)=>timestamp!==null);return timestamps.length>0?Math.max(...timestamps):null}function readLatestRetroTimestampMs(dir,phase){let baseDir=path198.normalize(path198.resolve(dir,".swarm")),retroPath=path198.normalize(path198.join(baseDir,"evidence",`retro-${phase}`,"evidence.json"));if(!(process.platform==="win32"?retroPath.toLowerCase().startsWith(baseDir.toLowerCase()+path198.sep)||retroPath.toLowerCase()===baseDir.toLowerCase():retroPath.startsWith(baseDir+path198.sep)||retroPath===baseDir))return null;try{let content=fs121.readFileSync(retroPath,"utf-8");return latestRetroTimestampMsFromBundle(JSON.parse(content),phase)}catch{return null}}function sessionHasEnabledFinalCouncil(sessionID){if(!sessionID)return!1;return swarmState.agentSessions.get(sessionID)?.qaGateSessionOverrides?.final_council===!0}async function runFinalCouncilGate(ctx){let{phase,dir,sessionID,agentsDispatched,safeWarn}=ctx,finalCouncilEnabled=!1,gateWarnings=[];try{let preamble=await resolveGatePreamble(dir,sessionID);if(!preamble.resolved||!preamble.plan){if(hasAnyProfileWithEnabledGate(dir,"final_council")||sessionHasEnabledFinalCouncil(sessionID))return{blocked:!0,reason:"FINAL_COUNCIL_PLAN_REQUIRED",message:`Phase ${phase} cannot be completed: final_council is enabled but plan.json is missing or invalid, so the final council gate cannot verify the current plan identity. Restore a valid .swarm/plan.json and re-run the final council.`,agentsDispatched,agentsMissing:[],warnings:[]};let warning="Final council gate: plan.json is missing and no enabled final_council profile was found. If final_council is required, the gate cannot be verified.";return gateWarnings.push(warning),safeWarn(`[phase_complete] ${warning}`,void 0),{blocked:!1,agentsDispatched,agentsMissing:[],warnings:[warning]}}if(preamble.resolved&&preamble.plan){let lastPhaseId=preamble.plan.phases[preamble.plan.phases.length-1]?.id;if(lastPhaseId!==void 0&&phase===lastPhaseId){if(preamble.effectiveGates?.final_council===!0){finalCouncilEnabled=!0;let fcPath=path198.join(dir,".swarm","evidence","final-council.json"),fcVerdictFound=!1,_fcVerdict;try{let fcContent=fs121.readFileSync(fcPath,"utf-8"),fcBundle=JSON.parse(fcContent);for(let entry of fcBundle.entries??[])if(typeof entry.type==="string"&&entry.type==="final-council"&&typeof entry.verdict==="string"){fcVerdictFound=!0,_fcVerdict=entry.verdict;let now=new Date,fcTimeMs=parseTimestampMs(entry.timestamp);if(fcTimeMs===null)return{blocked:!0,reason:"FINAL_COUNCIL_TIMESTAMP_REQUIRED",message:`Phase ${phase} cannot be completed: final council evidence is missing a valid timestamp. Re-run the final council to generate fresh evidence.`,agentsDispatched,agentsMissing:[],warnings:[]};if(fcTimeMs>now.getTime())return{blocked:!0,reason:"FINAL_COUNCIL_FUTURE_TIMESTAMP",message:`Phase ${phase} cannot be completed: final council evidence timestamp is in the future.`,agentsDispatched,agentsMissing:[],warnings:[]};if(now.getTime()-fcTimeMs>86400000)return{blocked:!0,reason:"FINAL_COUNCIL_STALE_EVIDENCE",message:`Phase ${phase} cannot be completed: final council evidence is older than 24 hours. Re-run the final council for fresh review.`,agentsDispatched,agentsMissing:[],warnings:[]};let latestRetroTimestampMs=latestRetroTimestampMsFromBundle(ctx.loadedRetroBundle,phase)??readLatestRetroTimestampMs(dir,phase);if(latestRetroTimestampMs!==null&&fcTimeMs<latestRetroTimestampMs)return{blocked:!0,reason:"FINAL_COUNCIL_STALE_EVIDENCE",message:`Phase ${phase} cannot be completed: final council evidence predates the current phase retrospective. Re-run the final council after the latest project evidence is available.`,agentsDispatched,agentsMissing:[],warnings:[]};if(preamble.plan){let currentPlanId=preamble.planId;if(entry.plan_id&&entry.plan_id!==currentPlanId)return{blocked:!0,reason:"final_council_plan_mismatch",message:`Final council evidence belongs to a different plan (evidence: ${entry.plan_id}, current: ${currentPlanId}). Re-run the final council.`,agentsDispatched,agentsMissing:[],warnings:[]};if(!entry.plan_id)return{blocked:!0,reason:"FINAL_COUNCIL_PLAN_ID_REQUIRED",message:`Phase ${phase} (last phase) cannot be completed: final council evidence is missing plan_id binding. Re-run the final council to generate evidence with plan identity.`,agentsDispatched,agentsMissing:[],warnings:[]};if(entry.plan_hash!==preamble.planHash)return{blocked:!0,reason:entry.plan_hash?"FINAL_COUNCIL_STALE_PLAN":"FINAL_COUNCIL_PLAN_HASH_REQUIRED",message:entry.plan_hash?`Phase ${phase} cannot be completed: final council evidence was produced for an older plan hash. Re-run the final council for the current plan.`:`Phase ${phase} cannot be completed: final council evidence is missing plan_hash binding. Re-run the final council to generate evidence tied to the current plan content.`,agentsDispatched,agentsMissing:[],warnings:[]};let currentIdentityHash=derivePlanIdentityHash(preamble.plan);if(entry.plan_identity_hash!==currentIdentityHash)return{blocked:!0,reason:entry.plan_identity_hash?"FINAL_COUNCIL_PLAN_IDENTITY_MISMATCH":"FINAL_COUNCIL_PLAN_IDENTITY_REQUIRED",message:entry.plan_identity_hash?`Phase ${phase} cannot be completed: final council evidence belongs to a different raw plan identity. Re-run the final council.`:`Phase ${phase} cannot be completed: final council evidence is missing plan_identity_hash binding. Re-run the final council to generate collision-resistant plan identity evidence.`,agentsDispatched,agentsMissing:[],warnings:[]}}if(typeof entry.quorumSize!=="number"||!Number.isFinite(entry.quorumSize)||entry.quorumSize<5)return{blocked:!0,reason:"FINAL_COUNCIL_MISSING_QUORUM",message:`Phase ${phase} (last phase) cannot be completed: final council evidence is missing valid quorum metadata. Re-run the project-scoped five-member final council and call write_final_council_evidence to generate quorumed evidence.`,agentsDispatched,agentsMissing:[],warnings:[]};let requiredFinalCouncilMembers=["critic","reviewer","sme","test_engineer","explorer"],membersVoted=Array.isArray(entry.membersVoted)?entry.membersVoted.filter((member)=>typeof member==="string"):[],membersAbsent=Array.isArray(entry.membersAbsent)?entry.membersAbsent.filter((member)=>typeof member==="string"):[],distinctMembersVoted=new Set(membersVoted);if(!(requiredFinalCouncilMembers.every((member)=>distinctMembersVoted.has(member))&&distinctMembersVoted.size===requiredFinalCouncilMembers.length&&membersAbsent.length===0))return{blocked:!0,reason:"FINAL_COUNCIL_MISSING_QUORUM",message:`Phase ${phase} (last phase) cannot be completed: final council evidence does not prove all five required members voted. Re-run the project-scoped five-member final council and call write_final_council_evidence to generate complete evidence.`,agentsDispatched,agentsMissing:[],warnings:[]};if(entry.verdict==="rejected"||entry.verdict==="REJECTED")return{blocked:!0,reason:"FINAL_COUNCIL_REJECTED",message:`Phase ${phase} (last phase) cannot be completed: final council returned verdict 'REJECTED'. Address the required fixes before completing the project.`,agentsDispatched,agentsMissing:[],warnings:[]};if(entry.verdict==="concerns"||entry.verdict==="CONCERNS"){let advisoryNotes=Array.isArray(entry.advisoryNotes)?entry.advisoryNotes.filter((note)=>typeof note==="string"):[],warning=advisoryNotes.length>0?`Final council returned CONCERNS (non-blocking): ${advisoryNotes.join("; ")}`:"Final council returned CONCERNS (non-blocking).";gateWarnings.push(warning),safeWarn(`[phase_complete] ${warning}`,void 0)}if(entry.verdict!=="approved"&&entry.verdict!=="APPROVED"&&entry.verdict!=="concerns"&&entry.verdict!=="CONCERNS")return{blocked:!0,reason:"FINAL_COUNCIL_INVALID_VERDICT",message:`Phase ${phase} (last phase) cannot be completed: final council evidence contains unrecognized verdict '${entry.verdict}'. Expected one of: approved, concerns, rejected.`,agentsDispatched,agentsMissing:[],warnings:[]}}}catch(readErr){if(readErr.code!=="ENOENT")safeWarn("[phase_complete] Final council evidence unreadable:",readErr);fcVerdictFound=!1}if(!fcVerdictFound)return{blocked:!0,reason:"FINAL_COUNCIL_REQUIRED",final_council_required:!0,message:`Phase ${phase} (last phase) cannot be completed: final_council is enabled and final council evidence not found at .swarm/evidence/final-council.json. Dispatch critic, reviewer, sme, test_engineer, and explorer with project-scoped context, collect their CouncilMemberVerdict JSON, and call write_final_council_evidence before completing the project. Do not use convene_general_council for this gate.`,agentsDispatched,agentsMissing:[],warnings:["Final council required - dispatch the five project-scoped council members, then call write_final_council_evidence to persist quorumed evidence."]}}}}}catch(fcError){if(finalCouncilEnabled)return{blocked:!0,reason:"FINAL_COUNCIL_ERROR",message:`Phase ${phase} (last phase) cannot be completed: final council gate encountered an error. Error: ${String(fcError)}`,agentsDispatched,agentsMissing:[],warnings:[`FINAL_COUNCIL_ERROR: ${String(fcError)}`]};else safeWarn("[phase_complete] Final council gate error (non-blocking):",fcError)}return{blocked:!1,agentsDispatched,agentsMissing:[],warnings:gateWarnings}}import*as fs122 from"node:fs";import*as path199 from"node:path";async function runHallucinationGate(ctx){let{phase,dir,sessionID,agentsDispatched,safeWarn}=ctx;try{let preamble=await resolveGatePreamble(dir,sessionID);if(preamble.resolved&&preamble.effectiveGates?.hallucination_guard===!0){let hgPath=path199.join(dir,".swarm","evidence",String(phase),"hallucination-guard.json"),hgVerdictFound=!1,hgVerdictApproved=!1;try{let hgContent=fs122.readFileSync(hgPath,"utf-8"),hgBundle=JSON.parse(hgContent);for(let entry of hgBundle.entries??[])if(typeof entry.type==="string"&&entry.type.includes("hallucination")&&typeof entry.verdict==="string"){if(hgVerdictFound=!0,entry.verdict==="approved")hgVerdictApproved=!0;if(entry.verdict==="rejected"||typeof entry.summary==="string"&&entry.summary.includes("NEEDS_REVISION"))return{blocked:!0,reason:"HALLUCINATION_VERIFICATION_REJECTED",message:`Phase ${phase} cannot be completed: hallucination verifier returned verdict '${entry.verdict}'. Remove fabricated APIs/signatures and fix broken citations before completing the phase.`,agentsDispatched,agentsMissing:[],warnings:[]}}}catch(readErr){if(readErr.code!=="ENOENT")safeWarn("[phase_complete] Hallucination guard evidence unreadable:",readErr);hgVerdictFound=!1}if(!hgVerdictFound)return{blocked:!0,reason:"HALLUCINATION_VERIFICATION_MISSING",message:`Phase ${phase} cannot be completed: hallucination_guard is enabled and evidence not found at .swarm/evidence/${phase}/hallucination-guard.json. Delegate to critic_hallucination_verifier and call write_hallucination_evidence before completing the phase.`,agentsDispatched,agentsMissing:[],warnings:[]};if(!hgVerdictApproved)return{blocked:!0,reason:"HALLUCINATION_VERIFICATION_REJECTED",message:`Phase ${phase} cannot be completed: hallucination verifier verdict is not approved.`,agentsDispatched,agentsMissing:[],warnings:[]}}}catch(hgError){safeWarn("[phase_complete] Hallucination guard error (non-blocking):",hgError)}return{blocked:!1,agentsDispatched,agentsMissing:[],warnings:[]}}import*as fs123 from"node:fs";import*as path200 from"node:path";async function runMutationGate(ctx){let{phase,dir,sessionID,agentsDispatched,safeWarn}=ctx;try{let preamble=await resolveGatePreamble(dir,sessionID);if(preamble.resolved&&preamble.effectiveGates?.mutation_test===!0){let mgPath=path200.join(dir,".swarm","evidence",String(phase),"mutation-gate.json"),mgVerdictFound=!1,mgVerdict;try{let mgContent=fs123.readFileSync(mgPath,"utf-8"),mgBundle=JSON.parse(mgContent);for(let entry of mgBundle.entries??[])if(typeof entry.type==="string"&&entry.type==="mutation-gate"&&typeof entry.verdict==="string"){if(mgVerdictFound=!0,mgVerdict=entry.verdict,entry.verdict==="fail")return{blocked:!0,reason:"MUTATION_GATE_FAIL",message:`Phase ${phase} cannot be completed: mutation gate returned verdict 'fail'. Resolve surviving mutants or lower the kill-rate threshold before completing the phase.`,agentsDispatched,agentsMissing:[],warnings:[]};else if(!["pass","warn","skip"].includes(entry.verdict))return{blocked:!0,reason:"MUTATION_GATE_FAIL",message:`Phase ${phase} cannot be completed: mutation gate evidence contains unrecognized verdict '${entry.verdict}'. Expected one of: pass, warn, fail, skip.`,agentsDispatched,agentsMissing:[],warnings:[]}}}catch(readErr){if(readErr.code!=="ENOENT")safeWarn("[phase_complete] Mutation gate evidence unreadable:",readErr);mgVerdictFound=!1}if(!mgVerdictFound)return{blocked:!0,reason:"MUTATION_GATE_MISSING",message:`Phase ${phase} cannot be completed: mutation_test is enabled and evidence not found at .swarm/evidence/${phase}/mutation-gate.json. Run mutation_test, then call write_mutation_evidence before completing the phase.`,agentsDispatched,agentsMissing:[],warnings:[]};if(mgVerdict==="warn")safeWarn(`[phase_complete] Mutation gate verdict is 'warn' for phase ${phase} — proceeding with warning`,void 0)}}catch(mgError){safeWarn("[phase_complete] Mutation gate error (non-blocking):",mgError)}return{blocked:!1,agentsDispatched,agentsMissing:[],warnings:[]}}import*as fs124 from"node:fs";import*as path201 from"node:path";async function runPhaseCouncilGate(ctx){let{phase,dir,sessionID,pluginConfig,agentsDispatched,safeWarn}=ctx,gateWarnings=[],councilModeEnabled=!1;try{let preamble=await resolveGatePreamble(dir,sessionID);if(preamble.resolved&&preamble.effectiveGates?.phase_council===!0&&pluginConfig.council?.enabled===!0){councilModeEnabled=!0;let pcPath=path201.join(dir,".swarm","evidence",String(phase),"phase-council.json"),pcVerdictFound=!1,_pcVerdict,pcQuorumSize,pcTimestamp,pcPhaseNumber;try{let pcContent=fs124.readFileSync(pcPath,"utf-8"),pcBundle=JSON.parse(pcContent);for(let entry of pcBundle.entries??[])if(typeof entry.type==="string"&&entry.type==="phase-council"&&typeof entry.verdict==="string"){pcVerdictFound=!0,_pcVerdict=entry.verdict,pcQuorumSize=typeof entry.quorumSize==="number"?entry.quorumSize:void 0,pcTimestamp=typeof entry.timestamp==="string"?entry.timestamp:void 0,pcPhaseNumber=typeof entry.phase_number==="number"?entry.phase_number:typeof entry.phase==="number"?entry.phase:void 0;let now=new Date,pcTime=pcTimestamp?new Date(pcTimestamp):null;if(!pcTime||Number.isNaN(pcTime.getTime()))return{blocked:!0,reason:"PHASE_COUNCIL_INVALID_TIMESTAMP",message:`Phase ${phase} cannot be completed: phase council evidence has missing or invalid timestamp.`,agentsDispatched,agentsMissing:[],warnings:[]};let maxAge=86400000;if(pcTime.getTime()>now.getTime())return{blocked:!0,reason:"PHASE_COUNCIL_FUTURE_TIMESTAMP",message:`Phase ${phase} cannot be completed: phase council evidence timestamp is in the future.`,agentsDispatched,agentsMissing:[],warnings:[]};if(now.getTime()-pcTime.getTime()>maxAge)return{blocked:!0,reason:"PHASE_COUNCIL_STALE_EVIDENCE",message:`Phase ${phase} cannot be completed: phase council evidence is older than 24 hours. Re-convene council for fresh review.`,agentsDispatched,agentsMissing:[],warnings:[]};if(!entry.provenance||!entry.provenance.agent_name&&!entry.provenance.session_id){let msg=`Phase council evidence lacks provenance for phase ${phase}. Evidence should include agent_name or session_id for verification.`;gateWarnings.push(msg),safeWarn(`[phase_complete] ${msg}`,void 0)}if(entry.verdict==="REJECT"||entry.verdict==="reject"){let requiredFixes=entry.requiredFixes??entry.required_fixes??[],fixesDetail=Array.isArray(requiredFixes)&&requiredFixes.length>0?`
|
|
5894
5894
|
Required fixes: ${requiredFixes.map((f)=>f.detail??JSON.stringify(f)).join("; ")}`:"";return{blocked:!0,reason:"PHASE_COUNCIL_REJECTED",message:`Phase ${phase} cannot be completed: phase council returned verdict 'REJECT'. Address the required fixes before completing the phase.${fixesDetail}`,agentsDispatched,agentsMissing:[],warnings:[]}}if(entry.verdict==="CONCERNS"||entry.verdict==="concerns"){if(!(pluginConfig.council?.phaseConcernsAllowComplete??!0)){let advisoryNotes=entry.advisoryNotes??entry.advisory_notes??[],notesDetail=Array.isArray(advisoryNotes)&&advisoryNotes.length>0?`
|
|
5895
5895
|
Advisory notes: ${advisoryNotes.join("; ")}`:"";return{blocked:!0,reason:"PHASE_COUNCIL_CONCERNS",message:`Phase ${phase} cannot be completed: phase council returned verdict 'CONCERNS'.${notesDetail}`,agentsDispatched,agentsMissing:[],warnings:[]}}safeWarn(`[phase_complete] Phase council returned CONCERNS for phase ${phase} — proceeding (phaseConcernsAllowComplete is enabled)`,void 0)}if(entry.verdict!=="APPROVE"&&entry.verdict!=="approve"&&entry.verdict!=="CONCERNS"&&entry.verdict!=="concerns")return{blocked:!0,reason:"PHASE_COUNCIL_INVALID",message:`Phase ${phase} cannot be completed: phase council evidence contains unrecognized verdict '${entry.verdict}'. Expected one of: APPROVE, CONCERNS, REJECT.`,agentsDispatched,agentsMissing:[],warnings:[]}}}catch(readErr){if(readErr.code!=="ENOENT")safeWarn("[phase_complete] Phase council evidence unreadable:",readErr);pcVerdictFound=!1}if(!pcVerdictFound)return{blocked:!0,reason:"PHASE_COUNCIL_REQUIRED",phase_council_required:!0,message:`Phase ${phase} cannot be completed: phase_council is enabled and phase council evidence not found at .swarm/evidence/${phase}/phase-council.json. Convene a phase-level council (dispatch 5 members, collect verdicts, call submit_phase_council_verdicts) before completing the phase.`,agentsDispatched,agentsMissing:[],warnings:["Phase council required — convene 5 council members (critic, reviewer, sme, test_engineer, explorer) for holistic phase review. Call submit_phase_council_verdicts to synthesize verdicts and write phase-council.json evidence."]};if(pcQuorumSize===void 0||typeof pcQuorumSize!=="number")return{blocked:!0,reason:"PHASE_COUNCIL_MISSING_QUORUM",message:`Phase ${phase} cannot be completed: phase council evidence is missing quorumSize field.`,agentsDispatched,agentsMissing:[],warnings:[]};if(pcQuorumSize<3)return{blocked:!0,reason:"PHASE_COUNCIL_INSUFFICIENT_QUORUM",message:`Phase ${phase} cannot be completed: phase council quorum (${pcQuorumSize}) is below minimum (3). Re-convene council with sufficient members.`,agentsDispatched,agentsMissing:[],warnings:[]};if(pcPhaseNumber===void 0||typeof pcPhaseNumber!=="number")return{blocked:!0,reason:"PHASE_COUNCIL_MISSING_PHASE",message:`Phase ${phase} cannot be completed: phase council evidence is missing phase_number field.`,agentsDispatched,agentsMissing:[],warnings:[]};if(pcPhaseNumber!==phase)return{blocked:!0,reason:"PHASE_COUNCIL_PHASE_MISMATCH",message:`Phase ${phase} cannot be completed: phase council evidence is for phase ${pcPhaseNumber}, not phase ${phase}. Run council for the correct phase.`,agentsDispatched,agentsMissing:[],warnings:[]}}}catch(pcError){if(councilModeEnabled)return{blocked:!0,reason:"PHASE_COUNCIL_ERROR",message:`Phase ${phase} cannot be completed: phase council gate encountered an error when phase_council was enabled. Error: ${String(pcError)}`,agentsDispatched,agentsMissing:[],warnings:[`PHASE_COUNCIL_ERROR: ${String(pcError)}`]};else safeWarn("[phase_complete] Phase council gate error (non-blocking):",pcError)}return{blocked:!1,agentsDispatched,agentsMissing:[],warnings:gateWarnings}}init_resolve_working_directory();function safeWarn(message,error93){try{warn(message,error93 instanceof Error?error93.message:String(error93))}catch{}}var MAX_OUTPUT_BYTES6=512000,TASK_GATE_INFERABLE_AGENTS=new Set(["coder","reviewer","test_engineer"]);function canInferMissingAgentsFromTaskGates(agentsMissing){return agentsMissing.every((agent)=>TASK_GATE_INFERABLE_AGENTS.has(agent))}async function allCompletedTasksHavePassedGateEvidence(directory,tasks){for(let task of tasks){if(task.status!=="completed")return!1;if(!await hasPassedAllGates(directory,task.id))return!1}return tasks.length>0}function collectCrossSessionDispatchedAgents(phaseReferenceTimestamp,callerSessionId){let agents=new Set,contributorSessionIds=[],callerSession=swarmState.agentSessions.get(callerSessionId);if(callerSession){if(contributorSessionIds.push(callerSessionId),callerSession.phaseAgentsDispatched)for(let agent of callerSession.phaseAgentsDispatched)agents.add(agent);for(let delegation of _getDelegationsSince(callerSessionId,phaseReferenceTimestamp))agents.add(stripKnownSwarmPrefix(delegation.from)),agents.add(stripKnownSwarmPrefix(delegation.to))}for(let[sessionId,session]of swarmState.agentSessions){if(sessionId===callerSessionId)continue;let hasRecentToolCalls=session.lastToolCallTime>=phaseReferenceTimestamp,hasRecentDelegations=swarmState.delegationChains.get(sessionId)?.some((d)=>d.timestamp>=phaseReferenceTimestamp)??!1,hasRestoredAgents=(session.phaseAgentsDispatched?.size??0)>0&&session.lastPhaseCompleteTimestamp===phaseReferenceTimestamp;if(hasRecentToolCalls||hasRecentDelegations||hasRestoredAgents){if(contributorSessionIds.push(sessionId),session.phaseAgentsDispatched)for(let agent of session.phaseAgentsDispatched)agents.add(agent);for(let delegation of _getDelegationsSince(sessionId,phaseReferenceTimestamp))agents.add(stripKnownSwarmPrefix(delegation.from)),agents.add(stripKnownSwarmPrefix(delegation.to))}}return{agents,contributorSessionIds}}async function fallbackWritePlanWithTrace(dir,planPath,candidate,phase,warnings){let validation2=PlanSchema.safeParse(candidate);if(!validation2.success){let detail=validation2.error.issues.slice(0,5).map((issue3)=>`${issue3.path.join(".")||"<root>"}: ${issue3.message}`).join("; ");return warn("[phase_complete] Last-resort plan.json write aborted — mutated plan failed PlanSchema validation:",detail),warnings.push(`Warning: last-resort plan.json write skipped — mutated plan failed schema validation (${detail})`),!1}await atomicWriteFile(planPath,JSON.stringify(validation2.data,null,2));try{let traceEvent={event:"phase_complete_fallback_write",phase,timestamp:new Date().toISOString()},eventsPath=validateSwarmPath(dir,"events.jsonl");fs126.appendFileSync(eventsPath,`${JSON.stringify(traceEvent)}
|