opencode-swarm 7.141.0 → 7.141.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/{config-doctor-ayer8jwj.js → config-doctor-xs2p0xy3.js} +2 -2
- package/dist/cli/{core-yep18rkf.js → core-znrxk8gw.js} +1 -1
- package/dist/cli/{curator-fkwhph34.js → curator-a95x81ek.js} +17 -17
- package/dist/cli/{curator-llm-factory-b1wtbwwv.js → curator-llm-factory-ak7p0scv.js} +17 -17
- package/dist/cli/{dispatch-y8rergph.js → dispatch-rd10kdk1.js} +1 -1
- package/dist/cli/{evidence-summary-service-8e6594tg.js → evidence-summary-service-2gk48s5s.js} +4 -4
- package/dist/cli/{guardrail-explain-fhx1kft6.js → guardrail-explain-4st3vc3d.js} +18 -18
- package/dist/cli/{guardrail-log-x94s1jh9.js → guardrail-log-vjexgpfm.js} +3 -3
- package/dist/cli/{hive-promoter-3ay1hffy.js → hive-promoter-g9ad9vad.js} +17 -17
- package/dist/cli/{index-x5kk9gyk.js → index-2ygp3pnx.js} +5 -5
- package/dist/cli/{index-pkby67j3.js → index-39xs96mk.js} +1 -1
- package/dist/cli/{index-m54erqap.js → index-3gfdb0t9.js} +1 -1
- package/dist/cli/{index-9snyxgtf.js → index-44nf5s90.js} +1 -1
- package/dist/cli/{index-nkr3j0j1.js → index-5ykn39wq.js} +2 -2
- package/dist/cli/{index-sd1w4pya.js → index-8056f16v.js} +2 -2
- package/dist/cli/{index-w95sxwfr.js → index-8s4vnqts.js} +1 -1
- package/dist/cli/{index-awwqa1f5.js → index-c6m3t5n2.js} +2 -2
- package/dist/cli/{index-nk2ma3mh.js → index-dx1mdsrj.js} +134 -72
- package/dist/cli/{index-ays8g6cm.js → index-ebwznsfy.js} +54 -14
- package/dist/cli/{index-h375yxj5.js → index-g29r600w.js} +19 -19
- package/dist/cli/{index-fcsf8vjm.js → index-hjf8pjd4.js} +3 -3
- package/dist/cli/{index-xcqst95a.js → index-mr397tze.js} +1 -1
- package/dist/cli/{index-g4w73p1v.js → index-pkxt2rg2.js} +1 -1
- package/dist/cli/{index-acpsb3g1.js → index-ry609ctr.js} +3 -3
- package/dist/cli/{index-ytnm84ed.js → index-vnr917xf.js} +3 -3
- package/dist/cli/{index-b9mwe99e.js → index-w9613ace.js} +4 -4
- package/dist/cli/{index-10zsx1x2.js → index-wbf8sv70.js} +1 -1
- package/dist/cli/{index-1dwa96x7.js → index-ysapwztd.js} +2 -2
- package/dist/cli/{index-fckf6g01.js → index-z8yr1yra.js} +1 -1
- package/dist/cli/{index-rx33k785.js → index-zqshpey0.js} +1 -1
- package/dist/cli/index.js +17 -17
- package/dist/cli/{knowledge-escalator-53m3sh8p.js → knowledge-escalator-5xg6vmr4.js} +6 -6
- package/dist/cli/{knowledge-events-s5pmx5h3.js → knowledge-events-qvzpqt5b.js} +4 -4
- package/dist/cli/{knowledge-store-dv70gxxc.js → knowledge-store-k5td1vqx.js} +1 -1
- package/dist/cli/{knowledge-validator-je30smbr.js → knowledge-validator-zz26gk5d.js} +2 -2
- package/dist/cli/{scan-cursor-tcdcjbp9.js → scan-cursor-nhcpebh5.js} +2 -2
- package/dist/cli/{schema-6cg2smxx.js → schema-6ecb0xhn.js} +1 -1
- package/dist/cli/{scope-persistence-v51d74j2.js → scope-persistence-yet1hvmq.js} +4 -4
- package/dist/cli/{skill-generator-7kp8s0ne.js → skill-generator-j0mbd2pp.js} +7 -7
- package/dist/cli/{worktree-isolation-g6t99t0x.js → worktree-isolation-445zjngp.js} +17 -17
- package/dist/index.js +12 -12
- package/dist/lang/backend.d.ts +1 -0
- package/dist/tools/test-runner.d.ts +3 -2
- 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.141.0",description:"Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",main:"dist/index.js",types:"dist/index.d.ts",exports:{".":{types:"./dist/index.d.ts",default:"./dist/index.js"},"./package.json":"./package.json"},bin:{"opencode-swarm":"./dist/cli/index.js"},type:"module",engines:{bun:">=1.3.13"},license:"MIT",repository:{type:"git",url:"https://github.com/ZaxbyHub/opencode-swarm.git"},publishConfig:{access:"public",registry:"https://registry.npmjs.org/"},keywords:["opencode","opencode-plugin","ai","agents","orchestration","swarm","multi-agent","llm"],files:["dist","dist/lang/grammars","binaries","evaluation-fixtures",".opencode/skills/brainstorm",".opencode/skills/specify",".opencode/skills/clarify-spec",".opencode/skills/resume",".opencode/skills/clarify",".opencode/skills/discover",".opencode/skills/consult",".opencode/skills/pre-phase-briefing",".opencode/skills/council",".opencode/skills/deep-dive",".opencode/skills/deep-research",".opencode/skills/codebase-review-swarm",".opencode/skills/swarm-implement",".opencode/skills/design-docs",".opencode/skills/swarm-pr-review",".opencode/skills/swarm",".opencode/skills/swarm-pr-feedback",".opencode/skills/swarm-pr-subscribe",".opencode/skills/swarm-ci-monitor",".opencode/skills/issue-ingest",".opencode/skills/plan",".opencode/skills/critic-gate",".opencode/skills/execute",".opencode/skills/phase-wrap",".opencode/skills/loop",".opencode/skills/writing-tests",".opencode/skills/running-tests",".opencode/skills/engineering-conventions",".opencode/skills/commit-pr",".opencode/skills/ci-failure-batching",".opencode/skills/gate-attribution",".opencode/skills/merge-queue-readiness",".opencode/skills/skill-edit-validation",".opencode/skills/worktree-retry-cleanup",".opencode/skills/test-file-split",".opencode/skills/fork-pr-operations",".opencode/skills/parallel-work-check",".opencode/skills/ci-fix-monitor",".opencode/skills/issue-tracer",".opencode/skills/orchestrating-subagents",".opencode/skills/durable-session-state","tests/fixtures/memory-recall","README.md","LICENSE"],scripts:{clean:`bun -e "require('fs').rmSync('dist',{recursive:true,force:true})"`,build:"bun run clean && bun run scripts/copy-grammars.ts && bun build src/index.ts --outdir dist --target node --format esm --external web-tree-sitter --minify-whitespace --minify-syntax && bun build src/cli/index.ts --outdir dist/cli --target bun --format esm --external bash-parser --splitting && bun run scripts/copy-grammars.ts --to-dist && tsc --emitDeclarationOnly",typecheck:"tsc --noEmit",test:"bun test",lint:"biome lint .","lint:ci":"biome ci .","test:unit:ci":"bun scripts/ci/run-unit-tests-local.ts","drift:check":"bun run scripts/drift-check.ts","check:runtime-src-refs":"bun run scripts/check-runtime-src-refs.ts","drift:fix":"bun run scripts/drift-check.ts --fix --confirm","skills:sync":"bun run scripts/sync-qa-gate-skills.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","repro:1873":"bun build scripts/repro-1873-entry.ts --outdir dist-build-test/repro-1873 --target node --format esm && node scripts/repro-1873.mjs","check:events":"bun run scripts/check-event-contract.ts","check:test-file-cap":"bun run scripts/check-test-file-cap.ts","check:gate-portability":"bun run scripts/check-gate-portability.ts"},dependencies:{"@opencode-ai/plugin":"^1.18.3","@opencode-ai/sdk":"^1.18.3","@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","critic_finding_validator"],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]});function getPrWorkflowToolCapability(toolName,mode){let metadata=TOOL_METADATA[toolName];if(!metadata?.prWorkflow?.modes.includes(mode))return null;return metadata.prWorkflow.capability}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_finding_validator","critic_oversight","coder","test_engineer"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},diff_summary:{description:"filter classified AST changes by category, risk level, or file for reviewer drill-down",agents:["architect","reviewer","critic_finding_validator","critic_oversight"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},syntax_check:{description:"check syntax of source files using tree-sitter parsers across multiple languages, returning per-file errors",agents:["architect","coder","test_engineer"],prWorkflow:{modes:["PR_REVIEW"],capability:"validate"}},placeholder_scan:{description:"todo and FIXME comment detection",agents:["architect","reviewer","critic_finding_validator"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},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_finding_validator","critic","coder","test_engineer"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},lint:{description:"run project linter in check or fix mode; supports biome, eslint, ruff, clippy, and more, returns structured results",agents:["architect","reviewer","critic_finding_validator","coder"],prWorkflow:{modes:["PR_REVIEW"],capability:"validate"}},secretscan:{description:"scan for secrets (API keys, tokens, passwords) via regex and entropy; returns redacted previews, excludes common dirs",agents:["architect","reviewer","critic_finding_validator","critic_oversight"],prWorkflow:{modes:["PR_REVIEW"],capability:"validate"}},sast_scan:{description:"static analysis security scan",agents:["architect","reviewer","critic_finding_validator","critic_oversight"],prWorkflow:{modes:["PR_REVIEW"],capability:"validate"}},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","critic_finding_validator"]},quality_budget:{description:"code quality budget check",agents:["architect"],prWorkflow:{modes:["PR_REVIEW"],capability:"validate"}},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_finding_validator","critic","coder","test_engineer"]},complexity_hotspots:{description:"git churn × complexity risk map",agents:["architect","sme","researcher","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","reviewer","critic_finding_validator","critic","critic_oversight","explorer","test_engineer"]},schema_drift:{description:"OpenAPI spec vs route drift",agents:["architect","sme","researcher","docs","explorer"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},todo_extract:{description:"structured TODO/FIXME extraction",agents:["architect","researcher","docs","explorer"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},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"]},complete_pr_workflow:{description:"validate terminal PR workflow evidence and clear its durable session gate",agents:["architect"]},abort_pr_workflow:{description:"abort an unrecoverable PR_REVIEW/PR_FEEDBACK mechanical gate and clear its durable session state",agents:["architect"]},approve_plan_critic:{description:"record a MANUAL plan_critic_gate approval snapshot to unblock the ratchet-tighter critic_pre_plan execution gate when the critic already returned APPROVED but the mechanical recorder failed to persist it (issue #2012)",agents:["architect"]},prepare_pr_workflow_checkout:{description:"prepare an auditable PR workflow checkout or restore its exact original branch/HEAD and preserved stash after terminal cleanup",agents:["architect"]},record_implementation_review:{description:"record fresh-context reviewer + critic APPROVE verdicts for the implementation diff so the /swarm issue --trace workflow can satisfy its review gate before commit-pr handoff",agents:["architect"]},record_issue_publication:{description:"record a publication receipt so the /swarm issue --trace workflow reaches its terminal published state after the PR is created/updated",agents:["architect"]},record_issue_reproduction:{description:"record the reproduction outcome for the current traced issue so the /swarm issue --trace workflow can satisfy its reproduction gate and transition to PLAN",agents:["architect"]},record_recurrence_sweep:{description:"record the recurrence sweep (defect class, predicates, hit dispositions, guardrail proof) so the /swarm issue --trace workflow can satisfy its recurrence gate before commit-pr handoff",agents:["architect"]},rebind_pr_feedback_head:{description:"rebind a PR_FEEDBACK workflow to a new verified remote PR head after merge/rebase/conflict repair, invalidating ancestry-bound receipts so the mechanical ladder re-runs",agents:["architect"]},run_pr_feedback_stage_a:{description:"execute and persist mandatory PR-feedback Stage A checks on a content-bound revision",agents:["architect"]},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_finding_validator","critic_oversight","test_engineer"],prWorkflow:{modes:["PR_REVIEW"],capability:"validate"}},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"]},plan_conflict_check:{description:"read-only advisory check (#1656): compute a pairwise file-conflict matrix for N proposed parallel task groups using declared scopes and optional git co-change; returns a verdict (all_disjoint / conflicts_present / unknown_scopes), per-pair evidence, and a suggested serialization order. Writes nothing — the execution gate independently recomputes the verdict inline at dispatch time via the same helper. Call BEFORE attempting parallel dispatch to confirm disjointness.",agents:["architect"]},write_pr_review_trigger_eval:{description:"persist the complete PR-review trigger evaluation with exact-set validation, dispatch provenance, and live merge-base verification",agents:["architect"]},write_pr_review_artifact:{description:"persist schema-validated PR-review findings checkpoints and exact actionable feedback handoffs under the active run",agents:["architect"]},prepare_pr_feedback_scope:{description:"prepare an exact file scope for one PR-feedback coder Task after immutable feedback verification settles",agents:["architect"]},test_runner:{description:"auto-detect and run tests",agents:["architect","reviewer","critic_finding_validator","test_engineer"],prWorkflow:{modes:["PR_REVIEW"],capability:"validate"}},test_impact:{description:"identify test files impacted by changed source files via import analysis",agents:["architect","reviewer","critic_finding_validator","critic_oversight","test_engineer"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},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","critic_finding_validator","explorer","architect"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},gitingest:{description:"fetch a GitHub repository full content via gitingest.com",agents:["architect","docs","explorer"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},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_finding_validator","critic","coder","test_engineer"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},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"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},extract_code_blocks:{description:"extract code blocks from text content and save them to files",agents:["docs","docs_design","designer","spec_writer","coder","test_engineer"]},phase_complete:{description:"mark a phase as complete and track dispatched agents",agents:["architect"]},save_plan:{description:"save a structured implementation plan",agents:["architect"]},update_task_status:{description:"mark tasks complete, track phase progress",agents:["architect"]},lint_spec:{description:"validate .swarm/spec.md format and required fields",agents:["architect","spec_writer"]},write_retro:{description:"document phase retrospectives via phase_complete workflow, capture lessons learned",agents:["architect"]},write_drift_evidence:{description:"write drift verification evidence for a completed phase",agents:["architect"]},write_hallucination_evidence:{description:"write hallucination verification evidence for a completed phase",agents:["architect"]},write_mutation_evidence:{description:"write mutation gate evidence for a completed phase; normalizes PASS/WARN/FAIL/SKIP verdicts and writes .swarm/evidence/{phase}/mutation-gate.json",agents:["architect"]},declare_scope:{description:"declare file scope for next coder delegation",agents:["architect"]},knowledge_query:{description:"query swarm or hive knowledge with optional filters",agents:["architect","skill_improver","spec_writer"]},doc_scan:{description:"scan project documentation files and build an index manifest",agents:["architect","docs_design","skill_improver","spec_writer","explorer"]},doc_extract:{description:"extract actionable constraints from project documentation",agents:["architect","docs_design","skill_improver","spec_writer"]},curator_analyze:{description:"run curator phase analysis and optionally apply knowledge recommendations",agents:["architect"]},consensus_mine:{description:"mine cross-run consensus from existing .swarm evidence into an immutable proposals-only report; also deletes its own reports past consensus.report_retention, appends to the shared recommendation dedup ledger (in the shared cohort root, outside this project, when a knowledge link is active), and mirrors proposals into pending swarm-memory proposals when memory is enabled",agents:["architect","curator_phase","curator_postmortem"]},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_finding_validator","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_finding_validator","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"],prWorkflow:{modes:["PR_REVIEW"],capability:"validate"}},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"],prWorkflow:{modes:["PR_REVIEW"],capability:"validate"}},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"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},pr_workflow_status:{description:"Read-only architect observation of local git state (HEAD, branch, clean/dirty with a bounded changed-file list, remotes) plus a session-pinned PR workflow gate summary. Use to observe state under the fail-closed PR_REVIEW/PR_FEEDBACK gate. Never executes PR-controlled scripts and never reads another session gate.",agents:["architect"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},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_finding_validator","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","critic_finding_validator"]},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_finding_validator","critic","critic_oversight","explorer","coder"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},get_qa_gate_profile:{description:"retrieve the QA gate profile for the current or exact future plan identity: 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 and never creates state.",agents:["architect"]},set_qa_gates:{description:"configure the QA gate profile for the current plan or bootstrap an exact future plan with swarm_id and plan_title. Architect-only. The initial selection may set explicit true/false values over defaults; later changes are ratchet-tighter and rejected once 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, plus adopt_legacy_binding_only for exact-binding recovery without mutating gates.",agents:["architect"]},web_search:{description:"External web search (Tavily or Brave) for architect-driven council research, SME domain research, researcher auto-research, and skill-improver research. Returns titled results with snippets, URLs, normalized query metadata, temporal intent, freshness, and removed stale years. Config-gated on council.general.enabled in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides. Requires a search API key. Used by the architect in MODE: COUNCIL to gather a RESEARCH CONTEXT before dispatching council agents, by SME for opt-in external skill/source evaluation, and by the researcher agent for multi-source auto-research.",agents:["sme","researcher","skill_improver"]},web_fetch:{description:"Fetch the readable text of a single http(s) URL (architect-only). Returns decoded page text, document title, final URL after redirects, and an evidence reference. Reads primary sources that web_search only surfaces as snippets. Config-gated on council.general.enabled. Blocks private/loopback/link-local/metadata addresses (re-validated and re-pinned across redirects); enforces timeout and body size cap.",agents:[]},convene_general_council:{description:"Synthesize responses from a multi-model General Council. Accepts parallel member responses (Round 1, optionally Round 2), detects disagreements, and returns consensus points, persisting disagreements, and a structured synthesis. Architect-only. Config-gated on council.general.enabled in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides.",agents:[]},write_final_council_evidence:{description:"Persist project-scoped final council evidence to .swarm/evidence/final-council.json. PREREQUISITE: dispatch critic, reviewer, sme, test_engineer, and explorer as project-scoped Agent tasks and collect their CouncilMemberVerdict JSON — this tool synthesizes only. Rejects on insufficient quorum or CONCERNS with unresolved requiredFixes; normalizes verdicts to approved/concerns/rejected. Architect-only.",agents:[]},skill_generate:{description:"compile knowledge entries into a structured SKILL.md draft",agents:["skill_improver"]},skill_list:{description:"list generated skill files and their status",agents:["skill_improver"]},skill_apply:{description:"activate a draft skill proposal",agents:[]},skill_inspect:{description:"inspect the content and source entries of a skill file",agents:["skill_improver"]},run_stale_reconciliation:{description:"reconcile skills against the knowledge store: mark skills stale when source knowledge is archived or deleted, or clear stale markers",agents:["architect"]},skill_regenerate:{description:"regenerate an active skill by re-clustering its source knowledge entries and updating the SKILL.md in place",agents:[]},skill_retire:{description:"retire a generated skill by adding a retired.marker file; retired skills are excluded from scoring and injection",agents:[]},skill_improve:{description:"run the skill_improver agent to review and refine skills",agents:["skill_improver"]},spec_write:{description:"author or update .swarm/spec.md for the current project",agents:["spec_writer"]},knowledge_receipt:{description:"file a receipt for retrieved knowledge (applied/ignored/contradicted + new lessons), recorded as immutable knowledge events",agents:["architect","sme","docs","docs_design","designer","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","critic_architecture_supervisor","curator_init","curator_phase","skill_improver","spec_writer","reviewer","critic_finding_validator","critic","coder","test_engineer"]},knowledge_archive:{description:"archive (default), quarantine, or purge a swarm or hive knowledge entry by ID with an immutable audit tombstone; purge requires an admin flag",agents:["architect"]},swarm_memory_recall:{description:"recall scoped Swarm memory for the current repository as untrusted background",agents:[]},swarm_memory_propose:{description:"create a pending Swarm memory proposal; does not write durable memory directly",agents:[]},swarm_command:{description:"run supported /swarm commands through the canonical command registry",agents:["architect","sme","researcher","docs","docs_design","designer","reviewer","critic_finding_validator","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. Inline output for a settled lane is delivered only once: later polls of the same lane set output_omitted_repeat: true and omit output, but still include output_ref for recovery via retrieve_lane_output.",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)}var MAX_MERGE_DEPTH=10;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,SUMMARIZER_EXEMPT_TOOL_NAMES,DEFAULT_MODELS,DEFAULT_AGENT_CONFIGS,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.141.1",description:"Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",main:"dist/index.js",types:"dist/index.d.ts",exports:{".":{types:"./dist/index.d.ts",default:"./dist/index.js"},"./package.json":"./package.json"},bin:{"opencode-swarm":"./dist/cli/index.js"},type:"module",engines:{bun:">=1.3.13"},license:"MIT",repository:{type:"git",url:"https://github.com/ZaxbyHub/opencode-swarm.git"},publishConfig:{access:"public",registry:"https://registry.npmjs.org/"},keywords:["opencode","opencode-plugin","ai","agents","orchestration","swarm","multi-agent","llm"],files:["dist","dist/lang/grammars","binaries","evaluation-fixtures",".opencode/skills/brainstorm",".opencode/skills/specify",".opencode/skills/clarify-spec",".opencode/skills/resume",".opencode/skills/clarify",".opencode/skills/discover",".opencode/skills/consult",".opencode/skills/pre-phase-briefing",".opencode/skills/council",".opencode/skills/deep-dive",".opencode/skills/deep-research",".opencode/skills/codebase-review-swarm",".opencode/skills/swarm-implement",".opencode/skills/design-docs",".opencode/skills/swarm-pr-review",".opencode/skills/swarm",".opencode/skills/swarm-pr-feedback",".opencode/skills/swarm-pr-subscribe",".opencode/skills/swarm-ci-monitor",".opencode/skills/issue-ingest",".opencode/skills/plan",".opencode/skills/critic-gate",".opencode/skills/execute",".opencode/skills/phase-wrap",".opencode/skills/loop",".opencode/skills/writing-tests",".opencode/skills/running-tests",".opencode/skills/engineering-conventions",".opencode/skills/commit-pr",".opencode/skills/ci-failure-batching",".opencode/skills/gate-attribution",".opencode/skills/merge-queue-readiness",".opencode/skills/skill-edit-validation",".opencode/skills/worktree-retry-cleanup",".opencode/skills/test-file-split",".opencode/skills/fork-pr-operations",".opencode/skills/parallel-work-check",".opencode/skills/ci-fix-monitor",".opencode/skills/issue-tracer",".opencode/skills/orchestrating-subagents",".opencode/skills/durable-session-state","tests/fixtures/memory-recall","README.md","LICENSE"],scripts:{clean:`bun -e "require('fs').rmSync('dist',{recursive:true,force:true})"`,build:"bun run clean && bun run scripts/copy-grammars.ts && bun build src/index.ts --outdir dist --target node --format esm --external web-tree-sitter --minify-whitespace --minify-syntax && bun build src/cli/index.ts --outdir dist/cli --target bun --format esm --external bash-parser --splitting && bun run scripts/copy-grammars.ts --to-dist && tsc --emitDeclarationOnly",typecheck:"tsc --noEmit",test:"bun test",lint:"biome lint .","lint:ci":"biome ci .","test:unit:ci":"bun scripts/ci/run-unit-tests-local.ts","drift:check":"bun run scripts/drift-check.ts","check:runtime-src-refs":"bun run scripts/check-runtime-src-refs.ts","drift:fix":"bun run scripts/drift-check.ts --fix --confirm","skills:sync":"bun run scripts/sync-qa-gate-skills.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","repro:1873":"bun build scripts/repro-1873-entry.ts --outdir dist-build-test/repro-1873 --target node --format esm && node scripts/repro-1873.mjs","check:events":"bun run scripts/check-event-contract.ts","check:test-file-cap":"bun run scripts/check-test-file-cap.ts","check:gate-portability":"bun run scripts/check-gate-portability.ts"},dependencies:{"@opencode-ai/plugin":"^1.18.3","@opencode-ai/sdk":"^1.18.3","@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","critic_finding_validator"],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]});function getPrWorkflowToolCapability(toolName,mode){let metadata=TOOL_METADATA[toolName];if(!metadata?.prWorkflow?.modes.includes(mode))return null;return metadata.prWorkflow.capability}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_finding_validator","critic_oversight","coder","test_engineer"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},diff_summary:{description:"filter classified AST changes by category, risk level, or file for reviewer drill-down",agents:["architect","reviewer","critic_finding_validator","critic_oversight"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},syntax_check:{description:"check syntax of source files using tree-sitter parsers across multiple languages, returning per-file errors",agents:["architect","coder","test_engineer"],prWorkflow:{modes:["PR_REVIEW"],capability:"validate"}},placeholder_scan:{description:"todo and FIXME comment detection",agents:["architect","reviewer","critic_finding_validator"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},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_finding_validator","critic","coder","test_engineer"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},lint:{description:"run project linter in check or fix mode; supports biome, eslint, ruff, clippy, and more, returns structured results",agents:["architect","reviewer","critic_finding_validator","coder"],prWorkflow:{modes:["PR_REVIEW"],capability:"validate"}},secretscan:{description:"scan for secrets (API keys, tokens, passwords) via regex and entropy; returns redacted previews, excludes common dirs",agents:["architect","reviewer","critic_finding_validator","critic_oversight"],prWorkflow:{modes:["PR_REVIEW"],capability:"validate"}},sast_scan:{description:"static analysis security scan",agents:["architect","reviewer","critic_finding_validator","critic_oversight"],prWorkflow:{modes:["PR_REVIEW"],capability:"validate"}},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","critic_finding_validator"]},quality_budget:{description:"code quality budget check",agents:["architect"],prWorkflow:{modes:["PR_REVIEW"],capability:"validate"}},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_finding_validator","critic","coder","test_engineer"]},complexity_hotspots:{description:"git churn × complexity risk map",agents:["architect","sme","researcher","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","reviewer","critic_finding_validator","critic","critic_oversight","explorer","test_engineer"]},schema_drift:{description:"OpenAPI spec vs route drift",agents:["architect","sme","researcher","docs","explorer"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},todo_extract:{description:"structured TODO/FIXME extraction",agents:["architect","researcher","docs","explorer"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},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"]},complete_pr_workflow:{description:"validate terminal PR workflow evidence and clear its durable session gate",agents:["architect"]},abort_pr_workflow:{description:"abort an unrecoverable PR_REVIEW/PR_FEEDBACK mechanical gate and clear its durable session state",agents:["architect"]},approve_plan_critic:{description:"record a MANUAL plan_critic_gate approval snapshot to unblock the ratchet-tighter critic_pre_plan execution gate when the critic already returned APPROVED but the mechanical recorder failed to persist it (issue #2012)",agents:["architect"]},prepare_pr_workflow_checkout:{description:"prepare an auditable PR workflow checkout or restore its exact original branch/HEAD and preserved stash after terminal cleanup",agents:["architect"]},record_implementation_review:{description:"record fresh-context reviewer + critic APPROVE verdicts for the implementation diff so the /swarm issue --trace workflow can satisfy its review gate before commit-pr handoff",agents:["architect"]},record_issue_publication:{description:"record a publication receipt so the /swarm issue --trace workflow reaches its terminal published state after the PR is created/updated",agents:["architect"]},record_issue_reproduction:{description:"record the reproduction outcome for the current traced issue so the /swarm issue --trace workflow can satisfy its reproduction gate and transition to PLAN",agents:["architect"]},record_recurrence_sweep:{description:"record the recurrence sweep (defect class, predicates, hit dispositions, guardrail proof) so the /swarm issue --trace workflow can satisfy its recurrence gate before commit-pr handoff",agents:["architect"]},rebind_pr_feedback_head:{description:"rebind a PR_FEEDBACK workflow to a new verified remote PR head after merge/rebase/conflict repair, invalidating ancestry-bound receipts so the mechanical ladder re-runs",agents:["architect"]},run_pr_feedback_stage_a:{description:"execute and persist mandatory PR-feedback Stage A checks on a content-bound revision",agents:["architect"]},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_finding_validator","critic_oversight","test_engineer"],prWorkflow:{modes:["PR_REVIEW"],capability:"validate"}},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"]},plan_conflict_check:{description:"read-only advisory check (#1656): compute a pairwise file-conflict matrix for N proposed parallel task groups using declared scopes and optional git co-change; returns a verdict (all_disjoint / conflicts_present / unknown_scopes), per-pair evidence, and a suggested serialization order. Writes nothing — the execution gate independently recomputes the verdict inline at dispatch time via the same helper. Call BEFORE attempting parallel dispatch to confirm disjointness.",agents:["architect"]},write_pr_review_trigger_eval:{description:"persist the complete PR-review trigger evaluation with exact-set validation, dispatch provenance, and live merge-base verification",agents:["architect"]},write_pr_review_artifact:{description:"persist schema-validated PR-review findings checkpoints and exact actionable feedback handoffs under the active run",agents:["architect"]},prepare_pr_feedback_scope:{description:"prepare an exact file scope for one PR-feedback coder Task after immutable feedback verification settles",agents:["architect"]},test_runner:{description:"auto-detect and run tests",agents:["architect","reviewer","critic_finding_validator","test_engineer"],prWorkflow:{modes:["PR_REVIEW"],capability:"validate"}},test_impact:{description:"identify test files impacted by changed source files via import analysis",agents:["architect","reviewer","critic_finding_validator","critic_oversight","test_engineer"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},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","critic_finding_validator","explorer","architect"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},gitingest:{description:"fetch a GitHub repository full content via gitingest.com",agents:["architect","docs","explorer"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},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_finding_validator","critic","coder","test_engineer"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},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"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},extract_code_blocks:{description:"extract code blocks from text content and save them to files",agents:["docs","docs_design","designer","spec_writer","coder","test_engineer"]},phase_complete:{description:"mark a phase as complete and track dispatched agents",agents:["architect"]},save_plan:{description:"save a structured implementation plan",agents:["architect"]},update_task_status:{description:"mark tasks complete, track phase progress",agents:["architect"]},lint_spec:{description:"validate .swarm/spec.md format and required fields",agents:["architect","spec_writer"]},write_retro:{description:"document phase retrospectives via phase_complete workflow, capture lessons learned",agents:["architect"]},write_drift_evidence:{description:"write drift verification evidence for a completed phase",agents:["architect"]},write_hallucination_evidence:{description:"write hallucination verification evidence for a completed phase",agents:["architect"]},write_mutation_evidence:{description:"write mutation gate evidence for a completed phase; normalizes PASS/WARN/FAIL/SKIP verdicts and writes .swarm/evidence/{phase}/mutation-gate.json",agents:["architect"]},declare_scope:{description:"declare file scope for next coder delegation",agents:["architect"]},knowledge_query:{description:"query swarm or hive knowledge with optional filters",agents:["architect","skill_improver","spec_writer"]},doc_scan:{description:"scan project documentation files and build an index manifest",agents:["architect","docs_design","skill_improver","spec_writer","explorer"]},doc_extract:{description:"extract actionable constraints from project documentation",agents:["architect","docs_design","skill_improver","spec_writer"]},curator_analyze:{description:"run curator phase analysis and optionally apply knowledge recommendations",agents:["architect"]},consensus_mine:{description:"mine cross-run consensus from existing .swarm evidence into an immutable proposals-only report; also deletes its own reports past consensus.report_retention, appends to the shared recommendation dedup ledger (in the shared cohort root, outside this project, when a knowledge link is active), and mirrors proposals into pending swarm-memory proposals when memory is enabled",agents:["architect","curator_phase","curator_postmortem"]},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_finding_validator","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_finding_validator","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"],prWorkflow:{modes:["PR_REVIEW"],capability:"validate"}},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"],prWorkflow:{modes:["PR_REVIEW"],capability:"validate"}},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"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},pr_workflow_status:{description:"Read-only architect observation of local git state (HEAD, branch, clean/dirty with a bounded changed-file list, remotes) plus a session-pinned PR workflow gate summary. Use to observe state under the fail-closed PR_REVIEW/PR_FEEDBACK gate. Never executes PR-controlled scripts and never reads another session gate.",agents:["architect"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},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_finding_validator","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","critic_finding_validator"]},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_finding_validator","critic","critic_oversight","explorer","coder"],prWorkflow:{modes:["PR_REVIEW","PR_FEEDBACK"],capability:"observe"}},get_qa_gate_profile:{description:"retrieve the QA gate profile for the current or exact future plan identity: 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 and never creates state.",agents:["architect"]},set_qa_gates:{description:"configure the QA gate profile for the current plan or bootstrap an exact future plan with swarm_id and plan_title. Architect-only. The initial selection may set explicit true/false values over defaults; later changes are ratchet-tighter and rejected once 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, plus adopt_legacy_binding_only for exact-binding recovery without mutating gates.",agents:["architect"]},web_search:{description:"External web search (Tavily or Brave) for architect-driven council research, SME domain research, researcher auto-research, and skill-improver research. Returns titled results with snippets, URLs, normalized query metadata, temporal intent, freshness, and removed stale years. Config-gated on council.general.enabled in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides. Requires a search API key. Used by the architect in MODE: COUNCIL to gather a RESEARCH CONTEXT before dispatching council agents, by SME for opt-in external skill/source evaluation, and by the researcher agent for multi-source auto-research.",agents:["sme","researcher","skill_improver"]},web_fetch:{description:"Fetch the readable text of a single http(s) URL (architect-only). Returns decoded page text, document title, final URL after redirects, and an evidence reference. Reads primary sources that web_search only surfaces as snippets. Config-gated on council.general.enabled. Blocks private/loopback/link-local/metadata addresses (re-validated and re-pinned across redirects); enforces timeout and body size cap.",agents:[]},convene_general_council:{description:"Synthesize responses from a multi-model General Council. Accepts parallel member responses (Round 1, optionally Round 2), detects disagreements, and returns consensus points, persisting disagreements, and a structured synthesis. Architect-only. Config-gated on council.general.enabled in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides.",agents:[]},write_final_council_evidence:{description:"Persist project-scoped final council evidence to .swarm/evidence/final-council.json. PREREQUISITE: dispatch critic, reviewer, sme, test_engineer, and explorer as project-scoped Agent tasks and collect their CouncilMemberVerdict JSON — this tool synthesizes only. Rejects on insufficient quorum or CONCERNS with unresolved requiredFixes; normalizes verdicts to approved/concerns/rejected. Architect-only.",agents:[]},skill_generate:{description:"compile knowledge entries into a structured SKILL.md draft",agents:["skill_improver"]},skill_list:{description:"list generated skill files and their status",agents:["skill_improver"]},skill_apply:{description:"activate a draft skill proposal",agents:[]},skill_inspect:{description:"inspect the content and source entries of a skill file",agents:["skill_improver"]},run_stale_reconciliation:{description:"reconcile skills against the knowledge store: mark skills stale when source knowledge is archived or deleted, or clear stale markers",agents:["architect"]},skill_regenerate:{description:"regenerate an active skill by re-clustering its source knowledge entries and updating the SKILL.md in place",agents:[]},skill_retire:{description:"retire a generated skill by adding a retired.marker file; retired skills are excluded from scoring and injection",agents:[]},skill_improve:{description:"run the skill_improver agent to review and refine skills",agents:["skill_improver"]},spec_write:{description:"author or update .swarm/spec.md for the current project",agents:["spec_writer"]},knowledge_receipt:{description:"file a receipt for retrieved knowledge (applied/ignored/contradicted + new lessons), recorded as immutable knowledge events",agents:["architect","sme","docs","docs_design","designer","critic_sounding_board","critic_drift_verifier","critic_hallucination_verifier","critic_architecture_supervisor","curator_init","curator_phase","skill_improver","spec_writer","reviewer","critic_finding_validator","critic","coder","test_engineer"]},knowledge_archive:{description:"archive (default), quarantine, or purge a swarm or hive knowledge entry by ID with an immutable audit tombstone; purge requires an admin flag",agents:["architect"]},swarm_memory_recall:{description:"recall scoped Swarm memory for the current repository as untrusted background",agents:[]},swarm_memory_propose:{description:"create a pending Swarm memory proposal; does not write durable memory directly",agents:[]},swarm_command:{description:"run supported /swarm commands through the canonical command registry",agents:["architect","sme","researcher","docs","docs_design","designer","reviewer","critic_finding_validator","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. Inline output for a settled lane is delivered only once: later polls of the same lane set output_omitted_repeat: true and omit output, but still include output_ref for recovery via retrieve_lane_output.",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)}var MAX_MERGE_DEPTH=10;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,SUMMARIZER_EXEMPT_TOOL_NAMES,DEFAULT_MODELS,DEFAULT_AGENT_CONFIGS,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
|
|
|
@@ -2036,19 +2036,19 @@ ${USAGE8}`;let councilFlag=parsed.council?"council=true":"council=false",signal=
|
|
|
2036
2036
|
... (output truncated)`,NODE_MODULES="node_modules",BIN_DIRECTORY=".bin",MAX_PACKAGE_MANIFEST_BYTES=262144,MAX_PATH_SHIM_BYTES=65536,UNSAFE_SHELL_WRAPPER_EXTENSIONS,WINDOWS_BATCH_WRAPPER_EXTENSIONS,WINDOWS_CMD_UNSAFE_TOKEN,LINTER_PACKAGES,lint,_internals119;var init_lint=__esm(()=>{init_zod();init_discovery();init_utils();init_external_tool_runner();init_create_tool();init_path_security();SUPPORTED_LINTERS=["biome","eslint"],UNSAFE_SHELL_WRAPPER_EXTENSIONS=new Set([".bat",".cmd",".ps1"]),WINDOWS_BATCH_WRAPPER_EXTENSIONS=[".cmd",".bat"],WINDOWS_CMD_UNSAFE_TOKEN=/["%!^&|<>\r\n]/,LINTER_PACKAGES={biome:"@biomejs/biome",eslint:"eslint"};lint=createSwarmTool({description:"Run project linter in check or fix mode. Supports biome, eslint (JS/TS), ruff (Python), clippy (Rust), golangci-lint (Go), checkstyle (Java), ktlint (Kotlin), dotnet-format (C#), cppcheck (C/C++), swiftlint (Swift), dart analyze (Dart), and rubocop (Ruby). Returns JSON with success status, exit code, and output for architect pre-reviewer gate. Use check mode for CI/linting and fix mode to automatically apply fixes.",args:{mode:exports_external.enum(["fix","check"]).describe('Linting mode: "check" for read-only lint check, "fix" to automatically apply fixes')},async execute(args2,directory,ctx){if(!validateArgs(args2))return JSON.stringify({success:!1,mode:"check",error:'Invalid arguments: mode must be "fix" or "check"'},null,2);if(!directory||typeof directory!=="string"||directory.trim()==="")return JSON.stringify({success:!1,mode:"check",error:"project directory is required but was not provided"},null,2);let{mode}=args2,cwd=directory,resolvedLinter=await _internals119.detectResolvedLinter(directory,ctx?.abort);if(resolvedLinter){let result=await _internals119.runResolvedLint(resolvedLinter,mode,directory,ctx?.abort);return JSON.stringify(result,null,2)}let additionalLinter=_internals119.detectAdditionalLinter(cwd);if(additionalLinter){warn(`[lint] Using ${additionalLinter} linter for this project`);let result=await _internals119.runAdditionalLint(additionalLinter,mode,cwd,ctx?.abort);return JSON.stringify(result,null,2)}return JSON.stringify({success:!1,mode,error:"No linter found. Install biome or eslint for JS/TS projects, or a supported linter for your language (ruff, cargo clippy, golangci-lint, ktlint, dotnet format, cppcheck, swiftlint, dart analyze, rubocop).",message:`For JS/TS: npm install -D @biomejs/biome eslint
|
|
2037
2037
|
For Python: pip install ruff
|
|
2038
2038
|
For Rust: rustup component add clippy`},null,2)}}),_internals119={MAX_PACKAGE_MANIFEST_BYTES,MAX_PATH_SHIM_BYTES,arch:()=>process.arch,closeSync:fs74.closeSync,comSpec:()=>process.env.ComSpec,detectAdditionalLinter,detectAvailableLinter,detectResolvedLinter,execPath:()=>process.execPath,existsSync:fs74.existsSync,fstatSync:fs74.fstatSync,isCommandAvailable,openSync:fs74.openSync,pathEnv:()=>process.env.PATH??"",platform:()=>process.platform,readFileSync:fs74.readFileSync,readSync:fs74.readSync,readdirSync:fs74.readdirSync,realpathSync:fs74.realpathSync,resolveLinterCommand,runAdditionalLint,runExternalTool,runLint,runResolvedLint,statSync:fs74.statSync}});import*as fs75 from"node:fs";import*as path153 from"node:path";function calculateShannonEntropy(str){if(str.length===0)return 0;let freq=new Map;for(let char of str)freq.set(char,(freq.get(char)||0)+1);let entropy=0;for(let count of freq.values()){let p=count/str.length;entropy-=p*Math.log2(p)}return entropy}function isHighEntropyString(str){if(str.length<20)return!1;if(str.replace(/[^a-zA-Z0-9]/g,"").length/str.length<0.25)return!1;return calculateShannonEntropy(str)>4}function validateExcludePattern(exc){if(exc.length===0)return null;if(exc.length>MAX_FILE_PATH_LENGTH)return`invalid exclude path: exceeds maximum length of ${MAX_FILE_PATH_LENGTH}`;if(containsControlChars(exc))return"invalid exclude path: contains path traversal or control characters";if(containsPathTraversal(exc))return"invalid exclude path: contains path traversal or control characters";if(exc.startsWith("!"))return"invalid exclude path: negation patterns are not supported";if(exc.startsWith("/")||exc.startsWith("\\"))return"invalid exclude path: absolute paths are not supported";return null}function isGlobOrPathPattern(pattern){return pattern.includes("/")||pattern.includes("\\")||/[*?[\]{}]/.test(pattern)}function loadSecretScanIgnore(scanDir){let ignorePath=path153.join(scanDir,".secretscanignore");try{if(!fs75.existsSync(ignorePath))return[];let content=fs75.readFileSync(ignorePath,"utf8"),patterns=[];for(let rawLine of content.split(/\r?\n/)){let line=rawLine.trim();if(!line||line.startsWith("#"))continue;if(validateExcludePattern(line)===null)patterns.push(line)}return patterns}catch{return[]}}function isExcluded(entry,relPath,exactNames,globPatterns){if(exactNames.has(entry))return!0;for(let pattern of globPatterns)if(path153.matchesGlob(relPath,pattern))return!0;return!1}function validateDirectoryInput(dir){if(!dir||dir.length===0)return"directory is required";if(dir.length>MAX_FILE_PATH_LENGTH)return`directory exceeds maximum length of ${MAX_FILE_PATH_LENGTH}`;if(containsControlChars(dir))return"directory contains control characters";if(containsPathTraversal(dir))return"directory contains path traversal";return null}function isBinaryFile(filePath,buffer){let ext=path153.extname(filePath).toLowerCase();if(DEFAULT_EXCLUDE_EXTENSIONS.has(ext))return!0;if(buffer.length>=BINARY_PREFIX_BYTES){let uint323=buffer.subarray(0,BINARY_PREFIX_BYTES).readUInt32BE(0);for(let sig of BINARY_SIGNATURES)if(uint323===sig)return!0}let nullCount=0,checkLen=Math.min(buffer.length,BINARY_NULL_CHECK_BYTES);for(let i=0;i<checkLen;i++)if(buffer[i]===0)nullCount++;return nullCount>checkLen*BINARY_NULL_THRESHOLD}function scanLineForSecrets(line,_lineNum){let results=[];for(let pattern of SECRET_PATTERNS2){pattern.regex.lastIndex=0;for(let match=pattern.regex.exec(line);match!==null;match=pattern.regex.exec(line)){let fullMatch=match[0],redacted=pattern.redactTemplate(fullMatch);if(results.push({type:pattern.type,confidence:pattern.confidence,severity:pattern.severity,redacted,matchStart:match.index,matchEnd:match.index+fullMatch.length}),match.index===pattern.regex.lastIndex)pattern.regex.lastIndex++}}let valueMatch=line.match(/((?:secret|key|token|password|cred|credential))\s*[=:]\s*["']?([a-zA-Z0-9+/=_-]{20,100})["']?/i);if(valueMatch&&isHighEntropyString(valueMatch[2])){let matchStart=valueMatch.index||0,matchEnd=matchStart+valueMatch[0].length;if(!results.some((r)=>!(r.matchEnd<=matchStart||r.matchStart>=matchEnd)))results.push({type:"high_entropy",confidence:"low",severity:"medium",redacted:`${valueMatch[1]}=[HIGH_ENTROPY]`,matchStart,matchEnd})}return results}function createRedactedContext(line,findings){if(findings.length===0)return"";let sorted=[...findings].sort((a,b)=>a.matchStart-b.matchStart),result="",lastEnd=0;for(let finding of sorted){if(finding.matchEnd<=lastEnd)continue;if(finding.matchStart>=lastEnd)result+=line.slice(lastEnd,finding.matchStart),result+="[REDACTED]";lastEnd=Math.max(lastEnd,finding.matchEnd)}if(result+=line.slice(lastEnd),result.length<=MAX_CONTEXT_CHARS)return result;let truncationMarker="...[context truncated]...",edgeLength=Math.floor((MAX_CONTEXT_CHARS-truncationMarker.length)/2),remaining=MAX_CONTEXT_CHARS-truncationMarker.length-edgeLength;return`${result.slice(0,edgeLength)}${truncationMarker}${result.slice(-remaining)}`}function getStableFileIdentity(stat15){let{dev,ino}=stat15;if(dev<0n||ino<0n||dev===0n&&ino===0n)return null;return`${dev}:${ino}`}function readBoundedFile2(filePath,expectedPathStat){let expectedIdentity=getStableFileIdentity(expectedPathStat);if(expectedIdentity===null)return{status:"incomplete",reason:"read_error"};let fd=null;try{let flags=fs75.constants.O_RDONLY|(O_NOFOLLOW!==void 0?O_NOFOLLOW:0);fd=_internals120.openFile(filePath,flags)}catch{return{status:"incomplete",reason:"read_error"}}let outcome,closeFailed=!1;try{let stat15=_internals120.fstatFile(fd),descriptorIdentity=getStableFileIdentity(stat15),initialSize=stat15.size;if(!stat15.isFile())outcome={status:"incomplete",reason:"non_file"};else if(descriptorIdentity===null||descriptorIdentity!==expectedIdentity)outcome={status:"incomplete",reason:"read_error"};else{let bufferLength=initialSize>=BigInt(MAX_FILE_SIZE_BYTES3)?MAX_FILE_SIZE_BYTES3+1:Number(initialSize)+1,buffer=Buffer.allocUnsafe(bufferLength),bytesRead=0;while(bytesRead<buffer.length){let count=_internals120.readFileChunk(fd,buffer,bytesRead,buffer.length-bytesRead,null);if(count===0)break;bytesRead+=count}let postStat=_internals120.fstatFile(fd),postDescriptorIdentity=getStableFileIdentity(postStat),postPathStat=_internals120.lstatFile(filePath),postPathIdentity=getStableFileIdentity(postPathStat);if(!postStat.isFile()||postDescriptorIdentity===null||postDescriptorIdentity!==descriptorIdentity||postPathStat.isSymbolicLink()||!postPathStat.isFile()||postPathIdentity===null||postPathIdentity!==descriptorIdentity)outcome={status:"incomplete",reason:"read_error"};else if(postStat.size!==initialSize)outcome={status:"incomplete",reason:postStat.size>BigInt(MAX_FILE_SIZE_BYTES3)?"oversized":"read_error"};else outcome={status:"ok",buffer:buffer.subarray(0,bytesRead),truncated:initialSize>MAX_FILE_SIZE_BYTES3}}}catch{outcome={status:"incomplete",reason:"read_error"}}finally{if(fd!==null)try{_internals120.closeFile(fd)}catch{closeFailed=!0}}if(closeFailed)return{status:"incomplete",reason:"read_error"};return outcome}function scanFileForSecrets(filePath,mode){let findings=[];try{let lstat7=_internals120.lstatFile(filePath);if(lstat7.isSymbolicLink())return mode==="explicit"?{status:"incomplete",reason:"symlink"}:{status:"skipped",reason:"symlink"};if(!lstat7.isFile())return{status:"incomplete",reason:"non_file"};let readOutcome=readBoundedFile2(filePath,lstat7);if(readOutcome.status==="incomplete")return readOutcome;let{buffer,truncated}=readOutcome;if(isBinaryFile(filePath,buffer))return{status:"skipped",reason:"binary"};if(truncated)return{status:"incomplete",reason:"oversized"};let content;if(buffer.length>=3&&buffer[0]===239&&buffer[1]===187&&buffer[2]===191)content=buffer.slice(3).toString("utf-8");else content=buffer.toString("utf-8");if(content.includes("\x00"))return{status:"skipped",reason:"binary"};let lines=content.split(`
|
|
2039
|
-
`);for(let i=0;i<lines.length;i++){if(mode==="standalone"&&lines[i].length>MAX_LONG_LINE_CHARS)continue;let lineResults=scanLineForSecrets(lines[i],i+1),context=createRedactedContext(lines[i],lineResults);for(let result of lineResults)findings.push({path:filePath,line:i+1,type:result.type,confidence:result.confidence,severity:result.severity,redacted:result.redacted,context})}return{status:"scanned",findings}}catch{return{status:"incomplete",reason:"read_error"}}}function assertNever3(value){throw Error(`Unhandled secretscan outcome: ${String(value)}`)}async function yieldToEventLoop2(){await new Promise((resolve63)=>setImmediate(resolve63))}function serializeSecretscanResult(result){let findings=result.findings,candidate=result,json3=JSON.stringify(candidate,null,2);while(Buffer.byteLength(json3,"utf8")>MAX_OUTPUT_BYTES3&&findings.length>0)findings=findings.slice(0,Math.floor(findings.length/2)),candidate={...result,findings,message:"Output truncated due to size limits."},json3=JSON.stringify(candidate,null,2);if(Buffer.byteLength(json3,"utf8")>MAX_OUTPUT_BYTES3)candidate={...result,findings:[],message:"Output truncated due to size limits."},json3=JSON.stringify(candidate,null,2);return json3}function isSymlinkLoop(realPath,visited){if(visited.has(realPath))return!0;return visited.add(realPath),!1}function isPathWithinScope(realPath,scanDir){let resolvedScanDir=path153.resolve(scanDir),resolvedRealPath=path153.resolve(realPath);return resolvedRealPath===resolvedScanDir||resolvedRealPath.startsWith(resolvedScanDir+path153.sep)||resolvedRealPath.startsWith(`${resolvedScanDir}/`)||resolvedRealPath.startsWith(`${resolvedScanDir}\\`)}function toSafeRelativePath(rootDir,targetPath){let relative33=path153.relative(rootDir,targetPath).replace(/\\/g,"/");if(!relative33||relative33===".")return".";if(relative33.startsWith("..")||path153.isAbsolute(relative33))return path153.basename(targetPath).replace(/\\/g,"/")||".";return relative33}function recordIncompletePath(target,rootDir,targetPath,reason){if(target.length>=MAX_INCOMPLETE_PATHS){target[MAX_INCOMPLETE_PATHS-1]={path:".",reason:"truncated"};return}target.push({path:toSafeRelativePath(rootDir,targetPath),reason})}function compareFilePaths(a,b){let aLower=a.toLowerCase(),bLower=b.toLowerCase();if(aLower<bLower)return-1;if(aLower>bLower)return 1;if(a<b)return-1;if(a>b)return 1;return 0}function addBoundedCandidate(state,filePath){state.totalCandidates++;let heap=state.files;if(heap.length<MAX_FILES_SCANNED2){heap.push(filePath);let index2=heap.length-1;while(index2>0){let parent=Math.floor((index2-1)/2);if(compareFilePaths(heap[parent],heap[index2])>=0)break;[heap[parent],heap[index2]]=[heap[index2],heap[parent]],index2=parent}return}if(compareFilePaths(filePath,heap[0])>=0)return;heap[0]=filePath;let index=0;while(!0){let left=index*2+1,right=left+1,largest=index;if(left<heap.length&&compareFilePaths(heap[left],heap[largest])>0)largest=left;if(right<heap.length&&compareFilePaths(heap[right],heap[largest])>0)largest=right;if(largest===index)break;[heap[index],heap[largest]]=[heap[largest],heap[index]],index=largest}}async function collectScannableFiles(dir,excludeExact,excludeGlobs,scanDir,visited,stats2,state){let pending=[dir];while(pending.length>0){if(state.deadlineExceeded||state.cleanupFailed)return;let currentDir=pending.pop();if(!currentDir)continue;let directory;try{directory=fs75.opendirSync(currentDir)}catch{stats2.fileErrors++,recordIncompletePath(state.incompletePaths,scanDir,currentDir,"read_error");continue}let stoppedEarly=!1;try{while(!0){if(state.entriesSinceYield>=DISCOVERY_YIELD_INTERVAL){if(state.entriesSinceYield=0,await _internals120.yieldToEventLoop(),_internals120.now()>=state.deadline){state.deadlineExceeded=!0,recordIncompletePath(state.incompletePaths,scanDir,currentDir,"deadline"),stoppedEarly=!0;break}}let entry=directory.readSync();if(!entry)break;state.entriesSinceYield++;let fullPath=path153.join(currentDir,entry.name),relPath=path153.relative(scanDir,fullPath).replace(/\\/g,"/");if(isExcluded(entry.name,relPath,excludeExact,excludeGlobs)){stats2.skippedDirs++;continue}let lstat7;try{lstat7=fs75.lstatSync(fullPath)}catch{stats2.fileErrors++,recordIncompletePath(state.incompletePaths,scanDir,fullPath,"read_error");continue}if(lstat7.isSymbolicLink()){stats2.symlinkSkipped++;continue}if(lstat7.isDirectory()){if(state.directoriesQueued>=MAX_DISCOVERY_DIRECTORIES){state.unexaminedDirectories++,recordIncompletePath(state.incompletePaths,scanDir,fullPath,"directory_limit");continue}let realPath;try{realPath=fs75.realpathSync(fullPath)}catch{stats2.fileErrors++,recordIncompletePath(state.incompletePaths,scanDir,fullPath,"read_error");continue}if(isSymlinkLoop(realPath,visited)||!isPathWithinScope(realPath,scanDir)){stats2.symlinkSkipped++;continue}pending.push(fullPath),state.directoriesQueued++}else if(lstat7.isFile()){let ext=path153.extname(fullPath).toLowerCase();if(!DEFAULT_EXCLUDE_EXTENSIONS.has(ext))addBoundedCandidate(state,fullPath);else stats2.skippedFiles++}else stats2.fileErrors++,recordIncompletePath(state.incompletePaths,scanDir,fullPath,"non_file")}}finally{try{_internals120.closeDirectory(directory)}catch(error93){if(error93.code!=="ERR_DIR_CLOSED")state.cleanupFailed=!0,recordIncompletePath(state.incompletePaths,scanDir,currentDir,"cleanup_failed")}}if(stoppedEarly)break}}async function runSecretscan(directory){try{let result=await _internals120.secretscan.execute({directory},{}),jsonStr=typeof result==="string"?result:result.output;return JSON.parse(jsonStr)}catch(e){return{error:e instanceof Error?`scan failed: ${e.message}`:"scan failed: unknown error",scan_dir:directory,findings:[],count:0,files_scanned:0,skipped_files:0}}}async function runSecretscanOnFiles(files,directory){try{let findings=[],filesScanned=0,skippedFiles=0,incompletePaths=[],rawRoot=path153.resolve(directory),canonicalRoot=(()=>{try{return fs75.realpathSync(rawRoot)}catch{return rawRoot}})(),rootStat;try{rootStat=fs75.lstatSync(canonicalRoot)}catch(error93){let err=error93;return{error:err.code==="ENOENT"?"directory not found":`scan failed: ${err.message||"unable to inspect directory"}`,scan_dir:directory,findings:[],count:0,files_scanned:0,skipped_files:0}}if(!rootStat.isDirectory())throw Error("target must be a directory");let filesToScan=files.slice(0,MAX_EXPLICIT_FILES_SCANNED),incompleteFiles=Math.max(0,files.length-filesToScan.length);if(files.length>filesToScan.length)recordIncompletePath(incompletePaths,canonicalRoot,canonicalRoot,"max_files");let deadline=_internals120.now()+SCAN_TIME_BUDGET_MS;await _internals120.yieldToEventLoop();for(let index=0;index<filesToScan.length;index++){if(_internals120.now()>=deadline){for(let remaining of filesToScan.slice(index)){let remainingPath=path153.isAbsolute(remaining)?path153.resolve(remaining):path153.resolve(rawRoot,remaining);recordIncompletePath(incompletePaths,canonicalRoot,remainingPath,"deadline")}incompleteFiles+=filesToScan.length-index;break}if(findings.length>=MAX_FINDINGS2){recordIncompletePath(incompletePaths,canonicalRoot,canonicalRoot,"truncated"),incompleteFiles+=filesToScan.length-index;break}let file3=filesToScan[index];if(typeof file3!=="string"){skippedFiles++;continue}let resolvedPath=path153.isAbsolute(file3)?path153.resolve(file3):path153.resolve(rawRoot,file3);if(!isPathWithinScope(resolvedPath,rawRoot)){skippedFiles++,incompleteFiles++,recordIncompletePath(incompletePaths,canonicalRoot,resolvedPath,"scope_escape");continue}let lstat7;try{lstat7=_internals120.lstatFile(resolvedPath)}catch(error93){if(error93.code==="ENOENT"){skippedFiles++;continue}skippedFiles++,incompleteFiles++,recordIncompletePath(incompletePaths,canonicalRoot,resolvedPath,"read_error");continue}if(lstat7.isSymbolicLink()){skippedFiles++,incompleteFiles++,recordIncompletePath(incompletePaths,canonicalRoot,resolvedPath,"symlink");continue}if(!lstat7.isFile()){skippedFiles++,incompleteFiles++,recordIncompletePath(incompletePaths,canonicalRoot,resolvedPath,"non_file");continue}let ext=path153.extname(resolvedPath).toLowerCase();if(DEFAULT_EXCLUDE_EXTENSIONS.has(ext)){skippedFiles++;continue}let scanPath=resolvedPath;try{scanPath=fs75.realpathSync(resolvedPath)}catch(error93){if(error93.code==="ENOENT"){skippedFiles++;continue}skippedFiles++,incompleteFiles++,recordIncompletePath(incompletePaths,canonicalRoot,resolvedPath,"read_error");continue}if(!isPathWithinScope(scanPath,canonicalRoot)){skippedFiles++,incompleteFiles++,recordIncompletePath(incompletePaths,canonicalRoot,scanPath,"scope_escape");continue}let outcome=scanFileForSecrets(scanPath,"explicit");switch(outcome.status){case"scanned":if(filesScanned++,findings.push(...outcome.findings),findings.length>MAX_FINDINGS2)findings.length=MAX_FINDINGS2;break;case"skipped":skippedFiles++;break;case"incomplete":skippedFiles++,incompleteFiles++,recordIncompletePath(incompletePaths,canonicalRoot,scanPath,outcome.reason);break;default:assertNever3(outcome)}if(index+1<filesToScan.length)await _internals120.yieldToEventLoop()}return findings.sort((a,b)=>{if(a.path<b.path)return-1;if(a.path>b.path)return 1;return a.line-b.line}),{scan_dir:directory,findings,count:findings.length,files_scanned:filesScanned,skipped_files:skippedFiles,incomplete_files:incompleteFiles,incomplete_paths:incompletePaths}}catch(e){return{error:e instanceof Error?`scan failed: ${e.message}`:"scan failed: unknown error",scan_dir:directory,findings:[],count:0,files_scanned:0,skipped_files:0}}}var MAX_FILE_PATH_LENGTH=500,MAX_FILE_SIZE_BYTES3=524288,MAX_FILES_SCANNED2=1000,MAX_EXPLICIT_FILES_SCANNED=100,MAX_FINDINGS2=100,MAX_OUTPUT_BYTES3=512000,MAX_CONTEXT_CHARS=1000,MAX_LONG_LINE_CHARS=1e4,MAX_INCOMPLETE_PATHS=25,MAX_DISCOVERY_DIRECTORIES=1e4,SCAN_TIME_BUDGET_MS=55000,BINARY_SIGNATURES,BINARY_PREFIX_BYTES=4,BINARY_NULL_CHECK_BYTES=8192,BINARY_NULL_THRESHOLD=0.1,DEFAULT_EXCLUDE_DIRS,DEFAULT_EXCLUDE_EXTENSIONS,SECRET_PATTERNS2,O_NOFOLLOW,DISCOVERY_YIELD_INTERVAL=100,secretscan,_internals120;var init_secretscan=__esm(()=>{init_zod();init_path_security();init_create_tool();BINARY_SIGNATURES=[0,2303741511,4292411360,1195984440,626017350,1347093252],DEFAULT_EXCLUDE_DIRS=new Set(["node_modules",".git","dist","build","out","coverage",".next",".nuxt",".cache","vendor",".svn",".hg",".gradle","target","__pycache__",".pytest_cache",".venv","venv",".env",".idea",".vscode"]),DEFAULT_EXCLUDE_EXTENSIONS=new Set([".png",".jpg",".jpeg",".gif",".ico",".svg",".pdf",".zip",".tar",".gz",".rar",".7z",".wasm",".exe",".dll",".so",".dylib",".bin",".dat",".db",".sqlite",".lock",".log",".md"]),SECRET_PATTERNS2=[{type:"aws_access_key",regex:/(?:AWS_ACCESS_KEY_ID|AWS_SECRET_ACCESS_KEY|aws_access_key_id|aws_secret_access_key)\s*[=:]\s*['"]?([A-Z0-9]{20})['"]?/gi,confidence:"high",severity:"critical",redactTemplate:()=>"AKIA[REDACTED]"},{type:"aws_secret_key",regex:/(?:AWS_SECRET_ACCESS_KEY|aws_secret_access_key)\s*[=:]\s*['"]?([A-Za-z0-9+/=]{40})['"]?/gi,confidence:"high",severity:"critical",redactTemplate:()=>"[REDACTED_AWS_SECRET]"},{type:"api_key",regex:/(?:api[_-]?key|apikey|API[_-]?KEY)\s*[=:]\s*['"]?([a-zA-Z0-9_-]{16,64})['"]?/gi,confidence:"medium",severity:"high",redactTemplate:(m)=>{let key=m.match(/[a-zA-Z0-9_-]{16,64}/)?.[0]||"";return`api_key=${key.slice(0,4)}...${key.slice(-4)}`}},{type:"bearer_token",regex:/(?:bearer\s+|Bearer\s+)([a-zA-Z0-9_\-.]{1,200})[\s"'<]/gi,confidence:"medium",severity:"high",redactTemplate:()=>"bearer [REDACTED]"},{type:"basic_auth",regex:/(?:basic\s+|Basic\s+)([a-zA-Z0-9+/=]{1,200})[\s"'<]/gi,confidence:"medium",severity:"high",redactTemplate:()=>"basic [REDACTED]"},{type:"database_url",regex:/(?:mysql|postgres|postgresql|mongodb|redis):\/\/[^\s"'/:]+:[^\s"'/:]+@[^\s"']+/gi,confidence:"high",severity:"critical",redactTemplate:()=>"mysql://[user]:[password]@[host]"},{type:"github_token",regex:/(?:ghp|gho|ghu|ghs|ghr)_[a-zA-Z0-9]{36,}/gi,confidence:"high",severity:"critical",redactTemplate:()=>"ghp_[REDACTED]"},{type:"generic_token",regex:/(?:token|TOKEN)\s*[=:]\s*['"]?([a-zA-Z0-9_\-.]{20,80})['"]?/gi,confidence:"low",severity:"medium",redactTemplate:(m)=>{return`token=${(m.match(/[a-zA-Z0-9_\-.]{20,80}/)?.[0]||"").slice(0,4)}...`}},{type:"password",regex:/(?:password|passwd|pwd|PASSWORD|PASSWD)\s*[=:]\s*['"]?([^\s'"]{4,100})['"]?/gi,confidence:"medium",severity:"high",redactTemplate:()=>"password=[REDACTED]"},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----/gi,confidence:"high",severity:"critical",redactTemplate:()=>"-----BEGIN PRIVATE KEY-----"},{type:"jwt",regex:/eyJ[a-zA-Z0-9_-]*\.eyJ[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*/g,confidence:"high",severity:"high",redactTemplate:(m)=>`eyJ...${m.slice(-10)}`},{type:"stripe_key",regex:/(?:sk|pk)_(?:live|test)_[a-zA-Z0-9]{24,}/gi,confidence:"high",severity:"critical",redactTemplate:()=>"sk_live_[REDACTED]"},{type:"slack_token",regex:/xox[baprs]-[0-9]{10,13}-[0-9]{10,13}[a-zA-Z0-9-]*/g,confidence:"high",severity:"critical",redactTemplate:()=>"xoxb-[REDACTED]"},{type:"sendgrid_key",regex:/SG\.[a-zA-Z0-9_-]{22}\.[a-zA-Z0-9_-]{43}/g,confidence:"high",severity:"critical",redactTemplate:()=>"SG.[REDACTED]"},{type:"twilio_key",regex:/SK[a-f0-9]{32}/gi,confidence:"high",severity:"critical",redactTemplate:()=>"SK[REDACTED]"}];O_NOFOLLOW=process.platform!=="win32"?fs75.constants.O_NOFOLLOW:void 0;secretscan=createSwarmTool({description:"Scan directory for potential secrets (API keys, tokens, passwords) using regex patterns and entropy heuristics. Returns metadata-only findings with redacted previews - NEVER returns raw secrets. Excludes common directories (node_modules, .git, dist, etc.) by default. Supports glob patterns (e.g. **/.svelte-kit/**, **/*.test.ts) and reads .secretscanignore at the scan root.",args:{directory:exports_external.string().describe('Directory to scan for secrets (e.g., "." or "./src")'),exclude:exports_external.array(exports_external.string()).optional().describe("Patterns to exclude: plain directory names (e.g. node_modules), relative paths, or globs (e.g. **/.svelte-kit/**, **/*.test.ts). Added to default exclusions.")},async execute(args2,_directory,_ctx){let typedArgs=args2,directory,exclude;try{if(typedArgs&&typeof typedArgs==="object")directory=typedArgs.directory,exclude=typedArgs.exclude}catch{}if(directory===void 0)return JSON.stringify({error:"invalid arguments: directory is required",scan_dir:"",findings:[],count:0,files_scanned:0,skipped_files:0},null,2);let dirValidationError=validateDirectoryInput(directory);if(dirValidationError){let errorResult={error:`invalid directory: ${dirValidationError}`,scan_dir:directory,findings:[],count:0,files_scanned:0,skipped_files:0};return JSON.stringify(errorResult,null,2)}if(exclude)for(let exc of exclude){let err=validateExcludePattern(exc);if(err)return JSON.stringify({error:err,scan_dir:directory,findings:[],count:0,files_scanned:0,skipped_files:0},null,2)}try{let scanDirRaw=path153.resolve(directory),scanDir=(()=>{try{return fs75.realpathSync(scanDirRaw)}catch{return scanDirRaw}})(),dirStat;try{dirStat=fs75.lstatSync(scanDir)}catch(error93){let err=error93,errorResult={error:err.code==="ENOENT"?"directory not found":`scan failed: ${err.message||"unable to inspect directory"}`,scan_dir:directory,findings:[],count:0,files_scanned:0,skipped_files:0};return JSON.stringify(errorResult,null,2)}if(!dirStat.isDirectory())return JSON.stringify({error:"target must be a directory, not a file",scan_dir:directory,findings:[],count:0,files_scanned:0,skipped_files:0},null,2);let excludeExact=new Set(DEFAULT_EXCLUDE_DIRS),excludeGlobs=[],ignoreFilePatterns=loadSecretScanIgnore(scanDir),allUserPatterns=[...exclude??[],...ignoreFilePatterns];for(let exc of allUserPatterns){if(exc.length===0)continue;if(isGlobOrPathPattern(exc))excludeGlobs.push(exc);else excludeExact.add(exc)}let stats2={skippedDirs:0,skippedFiles:0,fileErrors:0,symlinkSkipped:0},visited=new Set,deadline=_internals120.now()+SCAN_TIME_BUDGET_MS,discovery={files:[],totalCandidates:0,deadline,deadlineExceeded:!1,cleanupFailed:!1,entriesSinceYield:0,incompletePaths:[],directoriesQueued:1,unexaminedDirectories:0};await _internals120.yieldToEventLoop(),await collectScannableFiles(scanDir,excludeExact,excludeGlobs,scanDir,visited,stats2,discovery);let files=discovery.files;files.sort(compareFilePaths);let filesToScan=files;if(discovery.totalCandidates>filesToScan.length)recordIncompletePath(discovery.incompletePaths,scanDir,scanDir,"max_files");if(discovery.deadlineExceeded)recordIncompletePath(discovery.incompletePaths,scanDir,scanDir,"deadline");if(discovery.cleanupFailed)recordIncompletePath(discovery.incompletePaths,scanDir,scanDir,"cleanup_failed");let allFindings=[],filesScanned=0,skippedFiles=stats2.skippedFiles,incompleteFiles=stats2.fileErrors+Math.max(0,discovery.totalCandidates-filesToScan.length)+(discovery.deadlineExceeded||discovery.cleanupFailed?1:0)+discovery.unexaminedDirectories;for(let index=0;index<filesToScan.length;index++){if(_internals120.now()>=deadline){for(let remaining of filesToScan.slice(index))recordIncompletePath(discovery.incompletePaths,scanDir,remaining,"deadline");incompleteFiles+=filesToScan.length-index;break}if(allFindings.length>=MAX_FINDINGS2){recordIncompletePath(discovery.incompletePaths,scanDir,scanDir,"truncated"),incompleteFiles+=filesToScan.length-index;break}let outcome=scanFileForSecrets(filesToScan[index],"standalone");switch(outcome.status){case"scanned":filesScanned++;break;case"skipped":skippedFiles++;break;case"incomplete":skippedFiles++,incompleteFiles++,recordIncompletePath(discovery.incompletePaths,scanDir,filesToScan[index],outcome.reason);break;default:assertNever3(outcome)}if(outcome.status==="scanned")for(let finding of outcome.findings){if(allFindings.length>=MAX_FINDINGS2)break;allFindings.push(finding)}if(index+1<filesToScan.length)await _internals120.yieldToEventLoop()}allFindings.sort((a,b)=>{let aPathLower=a.path.toLowerCase(),bPathLower=b.path.toLowerCase();if(aPathLower<bPathLower)return-1;if(aPathLower>bPathLower)return 1;if(a.path<b.path)return-1;if(a.path>b.path)return 1;return a.line-b.line});let result={scan_dir:directory,findings:allFindings,count:allFindings.length,files_scanned:filesScanned,skipped_files:skippedFiles+stats2.fileErrors+stats2.symlinkSkipped,incomplete_files:incompleteFiles,incomplete_paths:discovery.incompletePaths},parts=[];if(discovery.totalCandidates>MAX_FILES_SCANNED2)parts.push(`Found ${discovery.totalCandidates} files, selected ${MAX_FILES_SCANNED2}`);if(discovery.deadlineExceeded)parts.push("Discovery stopped at the scan deadline");if(discovery.cleanupFailed)parts.push("Discovery directory cleanup failed");if(allFindings.length>=MAX_FINDINGS2)parts.push(`Results limited to ${MAX_FINDINGS2} findings`);if(incompleteFiles>0)parts.push(`${incompleteFiles} files were not completely scanned`);if(skippedFiles>0||stats2.fileErrors>0||stats2.symlinkSkipped>0)parts.push(`${skippedFiles+stats2.fileErrors+stats2.symlinkSkipped} files skipped (binary/oversized/symlinks/errors)`);if(parts.length>0)result.message=`${parts.join("; ")}.`;return serializeSecretscanResult(result)}catch(e){let errorResult={error:e instanceof Error?`scan failed: ${e.message||"internal error"}`:"scan failed: unknown error",scan_dir:directory,findings:[],count:0,files_scanned:0,skipped_files:0};return JSON.stringify(errorResult,null,2)}}});_internals120={secretscan,runSecretscan,runSecretscanOnFiles,SECRET_PATTERNS:SECRET_PATTERNS2,now:Date.now,yieldToEventLoop:yieldToEventLoop2,openFile:fs75.openSync,fstatFile:(fd)=>fs75.fstatSync(fd,{bigint:!0}),readFileChunk:fs75.readSync,closeFile:fs75.closeSync,lstatFile:(path154)=>fs75.lstatSync(path154,{bigint:!0}),closeDirectory:(directory)=>directory.closeSync()}});import*as fs76 from"node:fs";import*as path154 from"node:path";function detectFileExists(dir,pattern){if(pattern.includes("*")||pattern.includes("?"))try{let files=fs76.readdirSync(dir),regex=new RegExp(`^${pattern.replace(/\./g,"\\.").replace(/\*/g,".*").replace(/\?/g,".")}$`);return files.some((f)=>regex.test(f))}catch{return!1}try{return fs76.accessSync(path154.join(dir,pattern)),!0}catch{return!1}}function tokenizeCommand(cmd){let out=[],buf="",quote=null;for(let ch of cmd){if(quote){if(ch===quote)quote=null;else buf+=ch;continue}if(ch==='"'||ch==="'"){quote=ch;continue}if(ch===" "||ch==="\t"){if(buf.length>0)out.push(buf),buf="";continue}buf+=ch}if(buf.length>0)out.push(buf);return out}async function defaultSelectTestFramework(profile,dir){let sorted=[...profile.test.frameworks].sort((a,b)=>b.priority-a.priority);for(let fw of sorted){if(!detectFileExists(dir,fw.detect))continue;let argv=tokenizeCommand(fw.cmd);if(argv.length===0)continue;if(!isCommandAvailable(argv[0]))continue;return{name:fw.name,cmd:argv,cwd:dir,detectedVia:fw.detect,filesIgnored:!1}}return null}function defaultBuildTestCommand(profile,framework,files,dir=".",opts={}){let scope=opts.scope??"all",coverage=opts.coverage??!1,bail=opts.bail??!1,nativeTarget=opts.nativeTarget;if(nativeTarget){if(nativeTarget.framework!==framework)return null;return buildNativeTargetCommand(nativeTarget)}switch(framework){case"bun":{let args2=["bun","test"];if(coverage)args2.push("--coverage");if(bail)args2.push("--bail");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"vitest":{let args2=["npx","vitest","run","--reporter=json","--outputFile",".swarm/cache/test-runner-vitest.json"];if(coverage)args2.push("--coverage");if(bail)args2.push("--bail");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"jest":{let args2=["npx","jest","--json"];if(coverage)args2.push("--coverage");if(bail)args2.push("--bail");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"mocha":{let args2=["npx","mocha"];if(bail)args2.push("--bail");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"pytest":{let args2=process.platform==="win32"?["python","-m","pytest"]:["python3","-m","pytest"];if(coverage)args2.push("--cov=.","--cov-report=term-missing");if(bail)args2.push("-x");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"cargo":{let args2=["cargo","test"];if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"pester":{if(scope!=="all"&&files.length>0){let psCommand=`Invoke-Pester -Path @('${files.map((f)=>f.replace(/'/g,"''").replace(/`/g,"``").replace(/\$/g,"`$")).join("','")}')`;return["pwsh","-EncodedCommand",Buffer.from(psCommand,"utf16le").toString("base64")]}return["pwsh","-Command","Invoke-Pester"]}case"go-test":return["go","test","./..."];case"maven":return["mvn","test"];case"gradle":{let isWindows=process.platform==="win32",hasGradlewBat=fs76.existsSync(path154.join(dir,"gradlew.bat")),hasGradlew=fs76.existsSync(path154.join(dir,"gradlew"));if(hasGradlewBat&&isWindows)return["gradlew.bat","test"];if(hasGradlew)return["./gradlew","test"];return["gradle","test"]}case"dotnet-test":return["dotnet","test"];case"ctest":return["ctest","--test-dir",["build","_build","cmake-build-debug","cmake-build-release","out"].find((d)=>fs76.existsSync(path154.join(dir,d,"CMakeCache.txt")))??"build"];case"swift-test":return["swift","test"];case"dart-test":return isCommandAvailable("flutter")?["flutter","test",...files]:["dart","test",...files];case"rspec":{let args2=isCommandAvailable("bundle")?["bundle","exec","rspec"]:["rspec"];if(bail)args2.push("--fail-fast");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"minitest":if(scope!=="all"&&files.length>0)return["ruby","-Itest","-e",files.map((f)=>`require_relative '${f.replace(/\\/g,"/").replace(/'/g,"\\'")}'`).join("; ")];return["ruby","-Itest","-e",'Dir.glob("test/**/*_test.rb").sort.each { |f| require_relative f }'];case"pest":{let args2=[phpVendorBin("pest")];if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"phpunit":{let args2=[phpVendorBin("phpunit")];if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"php-artisan":{let args2=["php","artisan","test"];if(scope!=="all"&&files.length>0)args2.push(...files);return args2}default:{let fw=profile.test.frameworks.find((f)=>f.name===framework);if(!fw)return null;let argv=tokenizeCommand(fw.cmd);if(argv.length===0)return null;if(files.length===0)return argv;return[...argv,...files]}}}function escapeRegexLiteral(value){return value.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function buildNativeTargetCommand(target){if(target.framework==="ctest")return["ctest","--test-dir",target.path,"-R",`^${escapeRegexLiteral(target.name)}$`];let selector=target.name.split("/").map((part)=>`^${escapeRegexLiteral(part)}$`).join("/"),packagePath=target.path==="."?".":target.path.startsWith("./")?target.path:`./${target.path.replace(/\\/g,"/")}`;return["go","test","-v","-run",selector,packagePath]}function phpVendorBin(name){return path154.join("vendor","bin",process.platform==="win32"?`${name}.bat`:name)}function defaultParseTestOutput(framework,stdout,stderr,exitCode){let output=stdout&&stderr?`${stdout}
|
|
2039
|
+
`);for(let i=0;i<lines.length;i++){if(mode==="standalone"&&lines[i].length>MAX_LONG_LINE_CHARS)continue;let lineResults=scanLineForSecrets(lines[i],i+1),context=createRedactedContext(lines[i],lineResults);for(let result of lineResults)findings.push({path:filePath,line:i+1,type:result.type,confidence:result.confidence,severity:result.severity,redacted:result.redacted,context})}return{status:"scanned",findings}}catch{return{status:"incomplete",reason:"read_error"}}}function assertNever3(value){throw Error(`Unhandled secretscan outcome: ${String(value)}`)}async function yieldToEventLoop2(){await new Promise((resolve63)=>setImmediate(resolve63))}function serializeSecretscanResult(result){let findings=result.findings,candidate=result,json3=JSON.stringify(candidate,null,2);while(Buffer.byteLength(json3,"utf8")>MAX_OUTPUT_BYTES3&&findings.length>0)findings=findings.slice(0,Math.floor(findings.length/2)),candidate={...result,findings,message:"Output truncated due to size limits."},json3=JSON.stringify(candidate,null,2);if(Buffer.byteLength(json3,"utf8")>MAX_OUTPUT_BYTES3)candidate={...result,findings:[],message:"Output truncated due to size limits."},json3=JSON.stringify(candidate,null,2);return json3}function isSymlinkLoop(realPath,visited){if(visited.has(realPath))return!0;return visited.add(realPath),!1}function isPathWithinScope(realPath,scanDir){let resolvedScanDir=path153.resolve(scanDir),resolvedRealPath=path153.resolve(realPath);return resolvedRealPath===resolvedScanDir||resolvedRealPath.startsWith(resolvedScanDir+path153.sep)||resolvedRealPath.startsWith(`${resolvedScanDir}/`)||resolvedRealPath.startsWith(`${resolvedScanDir}\\`)}function toSafeRelativePath(rootDir,targetPath){let relative33=path153.relative(rootDir,targetPath).replace(/\\/g,"/");if(!relative33||relative33===".")return".";if(relative33.startsWith("..")||path153.isAbsolute(relative33))return path153.basename(targetPath).replace(/\\/g,"/")||".";return relative33}function recordIncompletePath(target,rootDir,targetPath,reason){if(target.length>=MAX_INCOMPLETE_PATHS){target[MAX_INCOMPLETE_PATHS-1]={path:".",reason:"truncated"};return}target.push({path:toSafeRelativePath(rootDir,targetPath),reason})}function compareFilePaths(a,b){let aLower=a.toLowerCase(),bLower=b.toLowerCase();if(aLower<bLower)return-1;if(aLower>bLower)return 1;if(a<b)return-1;if(a>b)return 1;return 0}function addBoundedCandidate(state,filePath){state.totalCandidates++;let heap=state.files;if(heap.length<MAX_FILES_SCANNED2){heap.push(filePath);let index2=heap.length-1;while(index2>0){let parent=Math.floor((index2-1)/2);if(compareFilePaths(heap[parent],heap[index2])>=0)break;[heap[parent],heap[index2]]=[heap[index2],heap[parent]],index2=parent}return}if(compareFilePaths(filePath,heap[0])>=0)return;heap[0]=filePath;let index=0;while(!0){let left=index*2+1,right=left+1,largest=index;if(left<heap.length&&compareFilePaths(heap[left],heap[largest])>0)largest=left;if(right<heap.length&&compareFilePaths(heap[right],heap[largest])>0)largest=right;if(largest===index)break;[heap[index],heap[largest]]=[heap[largest],heap[index]],index=largest}}async function collectScannableFiles(dir,excludeExact,excludeGlobs,scanDir,visited,stats2,state){let pending=[dir];while(pending.length>0){if(state.deadlineExceeded||state.cleanupFailed)return;let currentDir=pending.pop();if(!currentDir)continue;let directory;try{directory=fs75.opendirSync(currentDir)}catch{stats2.fileErrors++,recordIncompletePath(state.incompletePaths,scanDir,currentDir,"read_error");continue}let stoppedEarly=!1;try{while(!0){if(state.entriesSinceYield>=DISCOVERY_YIELD_INTERVAL){if(state.entriesSinceYield=0,await _internals120.yieldToEventLoop(),_internals120.now()>=state.deadline){state.deadlineExceeded=!0,recordIncompletePath(state.incompletePaths,scanDir,currentDir,"deadline"),stoppedEarly=!0;break}}let entry=directory.readSync();if(!entry)break;state.entriesSinceYield++;let fullPath=path153.join(currentDir,entry.name),relPath=path153.relative(scanDir,fullPath).replace(/\\/g,"/");if(isExcluded(entry.name,relPath,excludeExact,excludeGlobs)){stats2.skippedDirs++;continue}let lstat7;try{lstat7=fs75.lstatSync(fullPath)}catch{stats2.fileErrors++,recordIncompletePath(state.incompletePaths,scanDir,fullPath,"read_error");continue}if(lstat7.isSymbolicLink()){stats2.symlinkSkipped++;continue}if(lstat7.isDirectory()){if(state.directoriesQueued>=MAX_DISCOVERY_DIRECTORIES){state.unexaminedDirectories++,recordIncompletePath(state.incompletePaths,scanDir,fullPath,"directory_limit");continue}let realPath;try{realPath=fs75.realpathSync(fullPath)}catch{stats2.fileErrors++,recordIncompletePath(state.incompletePaths,scanDir,fullPath,"read_error");continue}if(isSymlinkLoop(realPath,visited)||!isPathWithinScope(realPath,scanDir)){stats2.symlinkSkipped++;continue}pending.push(fullPath),state.directoriesQueued++}else if(lstat7.isFile()){let ext=path153.extname(fullPath).toLowerCase();if(!DEFAULT_EXCLUDE_EXTENSIONS.has(ext))addBoundedCandidate(state,fullPath);else stats2.skippedFiles++}else stats2.fileErrors++,recordIncompletePath(state.incompletePaths,scanDir,fullPath,"non_file")}}finally{try{_internals120.closeDirectory(directory)}catch(error93){if(error93.code!=="ERR_DIR_CLOSED")state.cleanupFailed=!0,recordIncompletePath(state.incompletePaths,scanDir,currentDir,"cleanup_failed")}}if(stoppedEarly)break}}async function runSecretscan(directory){try{let result=await _internals120.secretscan.execute({directory},{}),jsonStr=typeof result==="string"?result:result.output;return JSON.parse(jsonStr)}catch(e){return{error:e instanceof Error?`scan failed: ${e.message}`:"scan failed: unknown error",scan_dir:directory,findings:[],count:0,files_scanned:0,skipped_files:0}}}async function runSecretscanOnFiles(files,directory){try{let findings=[],filesScanned=0,skippedFiles=0,incompletePaths=[],rawRoot=path153.resolve(directory),canonicalRoot=(()=>{try{return fs75.realpathSync(rawRoot)}catch{return rawRoot}})(),rootStat;try{rootStat=fs75.lstatSync(canonicalRoot)}catch(error93){let err=error93;return{error:err.code==="ENOENT"?"directory not found":`scan failed: ${err.message||"unable to inspect directory"}`,scan_dir:directory,findings:[],count:0,files_scanned:0,skipped_files:0}}if(!rootStat.isDirectory())throw Error("target must be a directory");let filesToScan=files.slice(0,MAX_EXPLICIT_FILES_SCANNED),incompleteFiles=Math.max(0,files.length-filesToScan.length);if(files.length>filesToScan.length)recordIncompletePath(incompletePaths,canonicalRoot,canonicalRoot,"max_files");let deadline=_internals120.now()+SCAN_TIME_BUDGET_MS;await _internals120.yieldToEventLoop();for(let index=0;index<filesToScan.length;index++){if(_internals120.now()>=deadline){for(let remaining of filesToScan.slice(index)){let remainingPath=path153.isAbsolute(remaining)?path153.resolve(remaining):path153.resolve(rawRoot,remaining);recordIncompletePath(incompletePaths,canonicalRoot,remainingPath,"deadline")}incompleteFiles+=filesToScan.length-index;break}if(findings.length>=MAX_FINDINGS2){recordIncompletePath(incompletePaths,canonicalRoot,canonicalRoot,"truncated"),incompleteFiles+=filesToScan.length-index;break}let file3=filesToScan[index];if(typeof file3!=="string"){skippedFiles++;continue}let resolvedPath=path153.isAbsolute(file3)?path153.resolve(file3):path153.resolve(rawRoot,file3);if(!isPathWithinScope(resolvedPath,rawRoot)){skippedFiles++,incompleteFiles++,recordIncompletePath(incompletePaths,canonicalRoot,resolvedPath,"scope_escape");continue}let lstat7;try{lstat7=_internals120.lstatFile(resolvedPath)}catch(error93){if(error93.code==="ENOENT"){skippedFiles++;continue}skippedFiles++,incompleteFiles++,recordIncompletePath(incompletePaths,canonicalRoot,resolvedPath,"read_error");continue}if(lstat7.isSymbolicLink()){skippedFiles++,incompleteFiles++,recordIncompletePath(incompletePaths,canonicalRoot,resolvedPath,"symlink");continue}if(!lstat7.isFile()){skippedFiles++,incompleteFiles++,recordIncompletePath(incompletePaths,canonicalRoot,resolvedPath,"non_file");continue}let ext=path153.extname(resolvedPath).toLowerCase();if(DEFAULT_EXCLUDE_EXTENSIONS.has(ext)){skippedFiles++;continue}let scanPath=resolvedPath;try{scanPath=fs75.realpathSync(resolvedPath)}catch(error93){if(error93.code==="ENOENT"){skippedFiles++;continue}skippedFiles++,incompleteFiles++,recordIncompletePath(incompletePaths,canonicalRoot,resolvedPath,"read_error");continue}if(!isPathWithinScope(scanPath,canonicalRoot)){skippedFiles++,incompleteFiles++,recordIncompletePath(incompletePaths,canonicalRoot,scanPath,"scope_escape");continue}let outcome=scanFileForSecrets(scanPath,"explicit");switch(outcome.status){case"scanned":if(filesScanned++,findings.push(...outcome.findings),findings.length>MAX_FINDINGS2)findings.length=MAX_FINDINGS2;break;case"skipped":skippedFiles++;break;case"incomplete":skippedFiles++,incompleteFiles++,recordIncompletePath(incompletePaths,canonicalRoot,scanPath,outcome.reason);break;default:assertNever3(outcome)}if(index+1<filesToScan.length)await _internals120.yieldToEventLoop()}return findings.sort((a,b)=>{if(a.path<b.path)return-1;if(a.path>b.path)return 1;return a.line-b.line}),{scan_dir:directory,findings,count:findings.length,files_scanned:filesScanned,skipped_files:skippedFiles,incomplete_files:incompleteFiles,incomplete_paths:incompletePaths}}catch(e){return{error:e instanceof Error?`scan failed: ${e.message}`:"scan failed: unknown error",scan_dir:directory,findings:[],count:0,files_scanned:0,skipped_files:0}}}var MAX_FILE_PATH_LENGTH=500,MAX_FILE_SIZE_BYTES3=524288,MAX_FILES_SCANNED2=1000,MAX_EXPLICIT_FILES_SCANNED=100,MAX_FINDINGS2=100,MAX_OUTPUT_BYTES3=512000,MAX_CONTEXT_CHARS=1000,MAX_LONG_LINE_CHARS=1e4,MAX_INCOMPLETE_PATHS=25,MAX_DISCOVERY_DIRECTORIES=1e4,SCAN_TIME_BUDGET_MS=55000,BINARY_SIGNATURES,BINARY_PREFIX_BYTES=4,BINARY_NULL_CHECK_BYTES=8192,BINARY_NULL_THRESHOLD=0.1,DEFAULT_EXCLUDE_DIRS,DEFAULT_EXCLUDE_EXTENSIONS,SECRET_PATTERNS2,O_NOFOLLOW,DISCOVERY_YIELD_INTERVAL=100,secretscan,_internals120;var init_secretscan=__esm(()=>{init_zod();init_path_security();init_create_tool();BINARY_SIGNATURES=[0,2303741511,4292411360,1195984440,626017350,1347093252],DEFAULT_EXCLUDE_DIRS=new Set(["node_modules",".git","dist","build","out","coverage",".next",".nuxt",".cache","vendor",".svn",".hg",".gradle","target","__pycache__",".pytest_cache",".venv","venv",".env",".idea",".vscode"]),DEFAULT_EXCLUDE_EXTENSIONS=new Set([".png",".jpg",".jpeg",".gif",".ico",".svg",".pdf",".zip",".tar",".gz",".rar",".7z",".wasm",".exe",".dll",".so",".dylib",".bin",".dat",".db",".sqlite",".lock",".log",".md"]),SECRET_PATTERNS2=[{type:"aws_access_key",regex:/(?:AWS_ACCESS_KEY_ID|AWS_SECRET_ACCESS_KEY|aws_access_key_id|aws_secret_access_key)\s*[=:]\s*['"]?([A-Z0-9]{20})['"]?/gi,confidence:"high",severity:"critical",redactTemplate:()=>"AKIA[REDACTED]"},{type:"aws_secret_key",regex:/(?:AWS_SECRET_ACCESS_KEY|aws_secret_access_key)\s*[=:]\s*['"]?([A-Za-z0-9+/=]{40})['"]?/gi,confidence:"high",severity:"critical",redactTemplate:()=>"[REDACTED_AWS_SECRET]"},{type:"api_key",regex:/(?:api[_-]?key|apikey|API[_-]?KEY)\s*[=:]\s*['"]?([a-zA-Z0-9_-]{16,64})['"]?/gi,confidence:"medium",severity:"high",redactTemplate:(m)=>{let key=m.match(/[a-zA-Z0-9_-]{16,64}/)?.[0]||"";return`api_key=${key.slice(0,4)}...${key.slice(-4)}`}},{type:"bearer_token",regex:/(?:bearer\s+|Bearer\s+)([a-zA-Z0-9_\-.]{1,200})[\s"'<]/gi,confidence:"medium",severity:"high",redactTemplate:()=>"bearer [REDACTED]"},{type:"basic_auth",regex:/(?:basic\s+|Basic\s+)([a-zA-Z0-9+/=]{1,200})[\s"'<]/gi,confidence:"medium",severity:"high",redactTemplate:()=>"basic [REDACTED]"},{type:"database_url",regex:/(?:mysql|postgres|postgresql|mongodb|redis):\/\/[^\s"'/:]+:[^\s"'/:]+@[^\s"']+/gi,confidence:"high",severity:"critical",redactTemplate:()=>"mysql://[user]:[password]@[host]"},{type:"github_token",regex:/(?:ghp|gho|ghu|ghs|ghr)_[a-zA-Z0-9]{36,}/gi,confidence:"high",severity:"critical",redactTemplate:()=>"ghp_[REDACTED]"},{type:"generic_token",regex:/(?:token|TOKEN)\s*[=:]\s*['"]?([a-zA-Z0-9_\-.]{20,80})['"]?/gi,confidence:"low",severity:"medium",redactTemplate:(m)=>{return`token=${(m.match(/[a-zA-Z0-9_\-.]{20,80}/)?.[0]||"").slice(0,4)}...`}},{type:"password",regex:/(?:password|passwd|pwd|PASSWORD|PASSWD)\s*[=:]\s*['"]?([^\s'"]{4,100})['"]?/gi,confidence:"medium",severity:"high",redactTemplate:()=>"password=[REDACTED]"},{type:"private_key",regex:/-----BEGIN (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----/gi,confidence:"high",severity:"critical",redactTemplate:()=>"-----BEGIN PRIVATE KEY-----"},{type:"jwt",regex:/eyJ[a-zA-Z0-9_-]*\.eyJ[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*/g,confidence:"high",severity:"high",redactTemplate:(m)=>`eyJ...${m.slice(-10)}`},{type:"stripe_key",regex:/(?:sk|pk)_(?:live|test)_[a-zA-Z0-9]{24,}/gi,confidence:"high",severity:"critical",redactTemplate:()=>"sk_live_[REDACTED]"},{type:"slack_token",regex:/xox[baprs]-[0-9]{10,13}-[0-9]{10,13}[a-zA-Z0-9-]*/g,confidence:"high",severity:"critical",redactTemplate:()=>"xoxb-[REDACTED]"},{type:"sendgrid_key",regex:/SG\.[a-zA-Z0-9_-]{22}\.[a-zA-Z0-9_-]{43}/g,confidence:"high",severity:"critical",redactTemplate:()=>"SG.[REDACTED]"},{type:"twilio_key",regex:/SK[a-f0-9]{32}/gi,confidence:"high",severity:"critical",redactTemplate:()=>"SK[REDACTED]"}];O_NOFOLLOW=process.platform!=="win32"?fs75.constants.O_NOFOLLOW:void 0;secretscan=createSwarmTool({description:"Scan directory for potential secrets (API keys, tokens, passwords) using regex patterns and entropy heuristics. Returns metadata-only findings with redacted previews - NEVER returns raw secrets. Excludes common directories (node_modules, .git, dist, etc.) by default. Supports glob patterns (e.g. **/.svelte-kit/**, **/*.test.ts) and reads .secretscanignore at the scan root.",args:{directory:exports_external.string().describe('Directory to scan for secrets (e.g., "." or "./src")'),exclude:exports_external.array(exports_external.string()).optional().describe("Patterns to exclude: plain directory names (e.g. node_modules), relative paths, or globs (e.g. **/.svelte-kit/**, **/*.test.ts). Added to default exclusions.")},async execute(args2,_directory,_ctx){let typedArgs=args2,directory,exclude;try{if(typedArgs&&typeof typedArgs==="object")directory=typedArgs.directory,exclude=typedArgs.exclude}catch{}if(directory===void 0)return JSON.stringify({error:"invalid arguments: directory is required",scan_dir:"",findings:[],count:0,files_scanned:0,skipped_files:0},null,2);let dirValidationError=validateDirectoryInput(directory);if(dirValidationError){let errorResult={error:`invalid directory: ${dirValidationError}`,scan_dir:directory,findings:[],count:0,files_scanned:0,skipped_files:0};return JSON.stringify(errorResult,null,2)}if(exclude)for(let exc of exclude){let err=validateExcludePattern(exc);if(err)return JSON.stringify({error:err,scan_dir:directory,findings:[],count:0,files_scanned:0,skipped_files:0},null,2)}try{let scanDirRaw=path153.resolve(directory),scanDir=(()=>{try{return fs75.realpathSync(scanDirRaw)}catch{return scanDirRaw}})(),dirStat;try{dirStat=fs75.lstatSync(scanDir)}catch(error93){let err=error93,errorResult={error:err.code==="ENOENT"?"directory not found":`scan failed: ${err.message||"unable to inspect directory"}`,scan_dir:directory,findings:[],count:0,files_scanned:0,skipped_files:0};return JSON.stringify(errorResult,null,2)}if(!dirStat.isDirectory())return JSON.stringify({error:"target must be a directory, not a file",scan_dir:directory,findings:[],count:0,files_scanned:0,skipped_files:0},null,2);let excludeExact=new Set(DEFAULT_EXCLUDE_DIRS),excludeGlobs=[],ignoreFilePatterns=loadSecretScanIgnore(scanDir),allUserPatterns=[...exclude??[],...ignoreFilePatterns];for(let exc of allUserPatterns){if(exc.length===0)continue;if(isGlobOrPathPattern(exc))excludeGlobs.push(exc);else excludeExact.add(exc)}let stats2={skippedDirs:0,skippedFiles:0,fileErrors:0,symlinkSkipped:0},visited=new Set,deadline=_internals120.now()+SCAN_TIME_BUDGET_MS,discovery={files:[],totalCandidates:0,deadline,deadlineExceeded:!1,cleanupFailed:!1,entriesSinceYield:0,incompletePaths:[],directoriesQueued:1,unexaminedDirectories:0};await _internals120.yieldToEventLoop(),await collectScannableFiles(scanDir,excludeExact,excludeGlobs,scanDir,visited,stats2,discovery);let files=discovery.files;files.sort(compareFilePaths);let filesToScan=files;if(discovery.totalCandidates>filesToScan.length)recordIncompletePath(discovery.incompletePaths,scanDir,scanDir,"max_files");if(discovery.deadlineExceeded)recordIncompletePath(discovery.incompletePaths,scanDir,scanDir,"deadline");if(discovery.cleanupFailed)recordIncompletePath(discovery.incompletePaths,scanDir,scanDir,"cleanup_failed");let allFindings=[],filesScanned=0,skippedFiles=stats2.skippedFiles,incompleteFiles=stats2.fileErrors+Math.max(0,discovery.totalCandidates-filesToScan.length)+(discovery.deadlineExceeded||discovery.cleanupFailed?1:0)+discovery.unexaminedDirectories;for(let index=0;index<filesToScan.length;index++){if(_internals120.now()>=deadline){for(let remaining of filesToScan.slice(index))recordIncompletePath(discovery.incompletePaths,scanDir,remaining,"deadline");incompleteFiles+=filesToScan.length-index;break}if(allFindings.length>=MAX_FINDINGS2){recordIncompletePath(discovery.incompletePaths,scanDir,scanDir,"truncated"),incompleteFiles+=filesToScan.length-index;break}let outcome=scanFileForSecrets(filesToScan[index],"standalone");switch(outcome.status){case"scanned":filesScanned++;break;case"skipped":skippedFiles++;break;case"incomplete":skippedFiles++,incompleteFiles++,recordIncompletePath(discovery.incompletePaths,scanDir,filesToScan[index],outcome.reason);break;default:assertNever3(outcome)}if(outcome.status==="scanned")for(let finding of outcome.findings){if(allFindings.length>=MAX_FINDINGS2)break;allFindings.push(finding)}if(index+1<filesToScan.length)await _internals120.yieldToEventLoop()}allFindings.sort((a,b)=>{let aPathLower=a.path.toLowerCase(),bPathLower=b.path.toLowerCase();if(aPathLower<bPathLower)return-1;if(aPathLower>bPathLower)return 1;if(a.path<b.path)return-1;if(a.path>b.path)return 1;return a.line-b.line});let result={scan_dir:directory,findings:allFindings,count:allFindings.length,files_scanned:filesScanned,skipped_files:skippedFiles+stats2.fileErrors+stats2.symlinkSkipped,incomplete_files:incompleteFiles,incomplete_paths:discovery.incompletePaths},parts=[];if(discovery.totalCandidates>MAX_FILES_SCANNED2)parts.push(`Found ${discovery.totalCandidates} files, selected ${MAX_FILES_SCANNED2}`);if(discovery.deadlineExceeded)parts.push("Discovery stopped at the scan deadline");if(discovery.cleanupFailed)parts.push("Discovery directory cleanup failed");if(allFindings.length>=MAX_FINDINGS2)parts.push(`Results limited to ${MAX_FINDINGS2} findings`);if(incompleteFiles>0)parts.push(`${incompleteFiles} files were not completely scanned`);if(skippedFiles>0||stats2.fileErrors>0||stats2.symlinkSkipped>0)parts.push(`${skippedFiles+stats2.fileErrors+stats2.symlinkSkipped} files skipped (binary/oversized/symlinks/errors)`);if(parts.length>0)result.message=`${parts.join("; ")}.`;return serializeSecretscanResult(result)}catch(e){let errorResult={error:e instanceof Error?`scan failed: ${e.message||"internal error"}`:"scan failed: unknown error",scan_dir:directory,findings:[],count:0,files_scanned:0,skipped_files:0};return JSON.stringify(errorResult,null,2)}}});_internals120={secretscan,runSecretscan,runSecretscanOnFiles,SECRET_PATTERNS:SECRET_PATTERNS2,now:Date.now,yieldToEventLoop:yieldToEventLoop2,openFile:fs75.openSync,fstatFile:(fd)=>fs75.fstatSync(fd,{bigint:!0}),readFileChunk:fs75.readSync,closeFile:fs75.closeSync,lstatFile:(path154)=>fs75.lstatSync(path154,{bigint:!0}),closeDirectory:(directory)=>directory.closeSync()}});import*as fs76 from"node:fs";import*as path154 from"node:path";function detectFileExists(dir,pattern){if(pattern.includes("*")||pattern.includes("?"))try{let files=fs76.readdirSync(dir),regex=new RegExp(`^${pattern.replace(/\./g,"\\.").replace(/\*/g,".*").replace(/\?/g,".")}$`);return files.some((f)=>regex.test(f))}catch{return!1}try{return fs76.accessSync(path154.join(dir,pattern)),!0}catch{return!1}}function tokenizeCommand(cmd){let out=[],buf="",quote=null;for(let ch of cmd){if(quote){if(ch===quote)quote=null;else buf+=ch;continue}if(ch==='"'||ch==="'"){quote=ch;continue}if(ch===" "||ch==="\t"){if(buf.length>0)out.push(buf),buf="";continue}buf+=ch}if(buf.length>0)out.push(buf);return out}async function defaultSelectTestFramework(profile,dir){let sorted=[...profile.test.frameworks].sort((a,b)=>b.priority-a.priority);for(let fw of sorted){if(!detectFileExists(dir,fw.detect))continue;let argv=tokenizeCommand(fw.cmd);if(argv.length===0)continue;if(!isCommandAvailable(argv[0]))continue;return{name:fw.name,cmd:argv,cwd:dir,detectedVia:fw.detect,filesIgnored:!1}}return null}function defaultBuildTestCommand(profile,framework,files,dir=".",opts={}){let scope=opts.scope??"all",coverage=opts.coverage??!1,bail=opts.bail??!1,targets=opts.targets,nativeTarget=opts.nativeTarget;if(nativeTarget){if(nativeTarget.framework!==framework)return null;return buildNativeTargetCommand(nativeTarget)}switch(framework){case"bun":{let args2=["bun","test"];if(coverage)args2.push("--coverage");if(bail)args2.push("--bail");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"vitest":{let args2=["npx","vitest","run","--reporter=json","--outputFile",".swarm/cache/test-runner-vitest.json"];if(coverage)args2.push("--coverage");if(bail)args2.push("--bail");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"jest":{let args2=["npx","jest","--json"];if(coverage)args2.push("--coverage");if(bail)args2.push("--bail");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"mocha":{let args2=["npx","mocha"];if(bail)args2.push("--bail");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"pytest":{let args2=process.platform==="win32"?["python","-m","pytest"]:["python3","-m","pytest"];if(coverage)args2.push("--cov=.","--cov-report=term-missing");if(bail)args2.push("-x");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"cargo":{let args2=["cargo","test"];if(targets&&targets.length>0)args2.push("--",...targets);else if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"pester":{if(scope!=="all"&&files.length>0){let psCommand=`Invoke-Pester -Path @('${files.map((f)=>f.replace(/'/g,"''").replace(/`/g,"``").replace(/\$/g,"`$")).join("','")}')`;return["pwsh","-EncodedCommand",Buffer.from(psCommand,"utf16le").toString("base64")]}return["pwsh","-Command","Invoke-Pester"]}case"go-test":{let args2=["go","test"];if(targets&&targets.length>0)args2.push("-run",targets.join("|"));return args2.push("./..."),args2}case"maven":{let args2=["mvn","test"];if(targets&&targets.length>0)args2.push(`-Dtest=${targets.join(",")}`);return args2}case"gradle":{let isWindows=process.platform==="win32",hasGradlewBat=fs76.existsSync(path154.join(dir,"gradlew.bat")),hasGradlew=fs76.existsSync(path154.join(dir,"gradlew")),args2=[];if(hasGradlewBat&&isWindows)args2.push("gradlew.bat");else if(hasGradlew)args2.push("./gradlew");else args2.push("gradle");if(args2.push("test"),targets&&targets.length>0)for(let target of targets)args2.push("--tests",target);return args2}case"dotnet-test":{let args2=["dotnet","test"];if(targets&&targets.length>0)args2.push("--filter",targets.join("|"));return args2}case"ctest":{let args2=["ctest","--test-dir",["build","_build","cmake-build-debug","cmake-build-release","out"].find((d)=>fs76.existsSync(path154.join(dir,d,"CMakeCache.txt")))??"build"];if(targets&&targets.length>0)args2.push("-R",targets.join("|"));return args2}case"swift-test":{let args2=["swift","test"];if(targets&&targets.length>0)for(let target of targets)args2.push("--filter",target);return args2}case"dart-test":return isCommandAvailable("flutter")?["flutter","test",...files]:["dart","test",...files];case"rspec":{let args2=isCommandAvailable("bundle")?["bundle","exec","rspec"]:["rspec"];if(bail)args2.push("--fail-fast");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"minitest":if(scope!=="all"&&files.length>0)return["ruby","-Itest","-e",files.map((f)=>`require_relative '${f.replace(/\\/g,"/").replace(/'/g,"\\'")}'`).join("; ")];return["ruby","-Itest","-e",'Dir.glob("test/**/*_test.rb").sort.each { |f| require_relative f }'];case"pest":{let args2=[phpVendorBin("pest")];if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"phpunit":{let args2=[phpVendorBin("phpunit")];if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"php-artisan":{let args2=["php","artisan","test"];if(scope!=="all"&&files.length>0)args2.push(...files);return args2}default:{let fw=profile.test.frameworks.find((f)=>f.name===framework);if(!fw)return null;let argv=tokenizeCommand(fw.cmd);if(argv.length===0)return null;if(files.length===0)return argv;return[...argv,...files]}}}function escapeRegexLiteral(value){return value.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function buildNativeTargetCommand(target){if(target.framework==="ctest")return["ctest","--test-dir",target.path,"-R",`^${escapeRegexLiteral(target.name)}$`];let selector=target.name.split("/").map((part)=>`^${escapeRegexLiteral(part)}$`).join("/"),packagePath=target.path==="."?".":target.path.startsWith("./")?target.path:`./${target.path.replace(/\\/g,"/")}`;return["go","test","-v","-run",selector,packagePath]}function phpVendorBin(name){return path154.join("vendor","bin",process.platform==="win32"?`${name}.bat`:name)}function defaultParseTestOutput(framework,stdout,stderr,exitCode){let output=stdout&&stderr?`${stdout}
|
|
2040
2040
|
${stderr}`:stdout||stderr||"",passed=0,failed=0,skipped=0,total,coveragePercent;switch(framework){case"vitest":case"jest":case"bun":{let jsonMatch=output.match(/\{[\s\S]*"testResults"[\s\S]*\}/);if(jsonMatch)try{let parsed=JSON.parse(jsonMatch[0]);if(parsed.numTotalTests!==void 0)passed=parsed.numPassedTests||0,failed=parsed.numFailedTests||0,skipped=parsed.numPendingTests||0,total=parsed.numTotalTests||0;if(parsed.coverage!==void 0)coveragePercent=parsed.coverage}catch{}if(total===void 0||total===0){let passMatch=output.match(/(\d+)\s+pass(ing|ed)?/),failMatch=output.match(/(\d+)\s+fail(ing|ed)?/),skipMatch=output.match(/(\d+)\s+skip(ping|ped)?/);if(passMatch)passed=parseInt(passMatch[1],10);if(failMatch)failed=parseInt(failMatch[1],10);if(skipMatch)skipped=parseInt(skipMatch[1],10);total=passed+failed+skipped}let coverageMatch=output.match(/All files[^\d]*(\d+\.?\d*)\s*%/);if(coveragePercent===void 0&&coverageMatch)coveragePercent=parseFloat(coverageMatch[1]);break}case"mocha":{let passMatch=output.match(/(\d+)\s+passing/),failMatch=output.match(/(\d+)\s+failing/),pendingMatch=output.match(/(\d+)\s+pending/);if(passMatch)passed=parseInt(passMatch[1],10);if(failMatch)failed=parseInt(failMatch[1],10);if(pendingMatch)skipped=parseInt(pendingMatch[1],10);total=passed+failed+skipped;break}case"pytest":{let passMatch=output.match(/(\d+)\s+passed/),failMatch=output.match(/(\d+)\s+failed/),skipMatch=output.match(/(\d+)\s+skipped/);if(passMatch)passed=parseInt(passMatch[1],10);if(failMatch)failed=parseInt(failMatch[1],10);if(skipMatch)skipped=parseInt(skipMatch[1],10);total=passed+failed+skipped;let coverageMatch=output.match(/TOTAL\s+(\d+\.?\d*)\s*%/);if(coverageMatch)coveragePercent=parseFloat(coverageMatch[1]);break}case"cargo":{let passMatch=output.match(/test result: ok\. (\d+) passed/),failMatch=output.match(/test result: FAILED\. (\d+) passed; (\d+) failed/);if(failMatch)passed=parseInt(failMatch[1],10),failed=parseInt(failMatch[2],10);else if(passMatch)passed=parseInt(passMatch[1],10);total=passed+failed;break}case"pester":{let passMatch=output.match(/Passed:\s*(\d+)/),failMatch=output.match(/Failed:\s*(\d+)/),skipMatch=output.match(/Skipped:\s*(\d+)/);if(passMatch)passed=parseInt(passMatch[1],10);if(failMatch)failed=parseInt(failMatch[1],10);if(skipMatch)skipped=parseInt(skipMatch[1],10);total=passed+failed+skipped;break}case"go-test":{let passMatches=[...output.matchAll(/--- PASS:/g)],failMatches=[...output.matchAll(/--- FAIL:/g)],skipMatches=[...output.matchAll(/--- SKIP:/g)];passed=passMatches.length,failed=failMatches.length,skipped=skipMatches.length,total=passed+failed+skipped;let covMatch=output.match(/coverage:\s*(\d+\.?\d*)\s*%/);if(covMatch)coveragePercent=parseFloat(covMatch[1]);break}case"maven":{let mavenMatch=output.match(/Tests run:\s*(\d+),\s*Failures:\s*(\d+),\s*Errors:\s*(\d+),\s*Skipped:\s*(\d+)/);if(mavenMatch){let tot=parseInt(mavenMatch[1],10),failures=parseInt(mavenMatch[2],10),errors5=parseInt(mavenMatch[3],10),sk=parseInt(mavenMatch[4],10);failed=failures+errors5,skipped=sk,passed=tot-failed-sk,total=tot}break}case"gradle":{let gradleMatch=output.match(/(\d+) tests? completed(?:,\s*(\d+) failed)?(?:,\s*(\d+) skipped)?/);if(gradleMatch)total=parseInt(gradleMatch[1],10),failed=gradleMatch[2]?parseInt(gradleMatch[2],10):0,skipped=gradleMatch[3]?parseInt(gradleMatch[3],10):0,passed=total-failed-skipped;break}case"dotnet-test":{let passMatch=output.match(/Passed[!:]?\s*(\d+)/i),failMatch=output.match(/Failed[!:]?\s*(\d+)/i),skipMatch=output.match(/Skipped[!:]?\s*(\d+)/i);if(passMatch)passed=parseInt(passMatch[1],10);if(failMatch)failed=parseInt(failMatch[1],10);if(skipMatch)skipped=parseInt(skipMatch[1],10);total=passed+failed+skipped;break}case"ctest":{let disabledCount=[...output.matchAll(/\*{3}Not Run\s+\(Disabled\)/gi)].length;skipped=disabledCount;let ctestMatch=output.match(/(\d+) tests? failed out of (\d+)/);if(ctestMatch){failed=parseInt(ctestMatch[1],10);let executedTotal=parseInt(ctestMatch[2],10);total=executedTotal+disabledCount,passed=executedTotal-failed}else{let allPassMatch=output.match(/100% tests passed.*?(\d+) tests?/);if(allPassMatch){let executedTotal=parseInt(allPassMatch[1],10);total=executedTotal+disabledCount,passed=executedTotal}else if(disabledCount>0)total=disabledCount}break}case"swift-test":{let swiftMatch=output.match(/Executed (\d+) tests?,\s*with (\d+) failures?/);if(swiftMatch)total=parseInt(swiftMatch[1],10),failed=parseInt(swiftMatch[2],10),passed=total-failed;break}case"dart-test":{let dartPassMatch=output.match(/\+(\d+):\s*All tests passed/),dartMixMatch=output.match(/\+(\d+)\s+-(\d+):/);if(dartPassMatch)passed=parseInt(dartPassMatch[1],10),total=passed;else if(dartMixMatch)passed=parseInt(dartMixMatch[1],10),failed=parseInt(dartMixMatch[2],10),total=passed+failed;break}case"rspec":{let rspecMatch=output.match(/(\d+) examples?,\s*(\d+) failures?(?:,\s*(\d+) pending)?/);if(rspecMatch)total=parseInt(rspecMatch[1],10),failed=parseInt(rspecMatch[2],10),skipped=rspecMatch[3]?parseInt(rspecMatch[3],10):0,passed=total-failed-skipped;break}case"minitest":{let minitestMatch=output.match(/(\d+) runs?,\s*\d+ assertions?,\s*(\d+) failures?,\s*(\d+) errors?,\s*(\d+) skips?/);if(minitestMatch){total=parseInt(minitestMatch[1],10);let failures=parseInt(minitestMatch[2],10),errors5=parseInt(minitestMatch[3],10);skipped=parseInt(minitestMatch[4],10),failed=failures+errors5,passed=total-failed-skipped}break}case"pest":case"phpunit":case"php-artisan":{let phpunitMatch=output.match(/Tests:\s*(\d+),\s*Assertions:\s*\d+(?:,\s*Failures:\s*(\d+))?(?:,\s*Errors:\s*(\d+))?(?:,\s*Skipped:\s*(\d+))?/),okMatch=output.match(/OK\s*\((\d+)\s+tests?/);if(phpunitMatch){total=parseInt(phpunitMatch[1],10);let failures=phpunitMatch[2]?parseInt(phpunitMatch[2],10):0,errors5=phpunitMatch[3]?parseInt(phpunitMatch[3],10):0;skipped=phpunitMatch[4]?parseInt(phpunitMatch[4],10):0,failed=failures+errors5,passed=total-failed-skipped}else if(okMatch)total=parseInt(okMatch[1],10),passed=total;break}default:break}if(total===void 0)total=passed+failed+skipped;return{ok:exitCode===0,raw:{stdout,stderr,exitCode},passed,failed,skipped,total,...coveragePercent!==void 0?{coveragePercent}:{}}}async function defaultDetectProject(profile,dir){for(let f of profile.build.detectFiles)if(detectFileExists(dir,f))return!0;return!1}async function defaultSelectBuildCommand(profile,dir){let sorted=[...profile.build.commands].sort((a,b)=>b.priority-a.priority);for(let cmd of sorted){if(cmd.detectFile&&!detectFileExists(dir,cmd.detectFile))continue;let argv=tokenizeCommand(cmd.cmd);if(argv.length===0)continue;if(!isCommandAvailable(argv[0]))continue;return{name:cmd.name,cmd:argv,cwd:dir,detectedVia:cmd.detectFile??`${profile.id} default`}}return null}async function defaultTestFilesFor(profile,sourceFile,dir){let ext=path154.extname(sourceFile);if(!profile.extensions.includes(ext))return[];let base=path154.basename(sourceFile,ext),rel=path154.relative(dir,sourceFile),stripSrc=path154.dirname(rel).replace(/^src(\/|\\)/,""),candidates=new Set;for(let tDir of["tests","test","__tests__","spec"])for(let suffix of["","_test",".test","_spec",".spec"])candidates.add(path154.join(dir,tDir,stripSrc,`${base}${suffix}${ext}`));let existing=[];for(let c of candidates)try{fs76.accessSync(c),existing.push(c)}catch{}return existing}function defaultExtractImports(){return[]}async function defaultSelectFramework(){return null}async function defaultSelectEntryPoints(){return[]}function defaultBackendFor(profile){return{...profile,detectProject:(dir)=>defaultDetectProject(profile,dir),selectTestFramework:(dir)=>defaultSelectTestFramework(profile,dir),buildTestCommand:(framework,files,dir,opts)=>defaultBuildTestCommand(profile,framework,files,dir,opts),parseTestOutput:(framework,stdout,stderr,exitCode)=>defaultParseTestOutput(framework,stdout,stderr,exitCode),testFilesFor:(sourceFile,dir)=>defaultTestFilesFor(profile,sourceFile,dir),extractImports:()=>defaultExtractImports(),selectBuildCommand:(dir)=>defaultSelectBuildCommand(profile,dir),selectFramework:()=>defaultSelectFramework(),selectEntryPoints:()=>defaultSelectEntryPoints()}}var init_default_backend=__esm(()=>{init_discovery()});import*as fs77 from"node:fs";import*as path155 from"node:path";function extractImports(_sourceFile,source){let out=new Set;IMPORT_REGEX_SINGLE.lastIndex=0;let m=IMPORT_REGEX_SINGLE.exec(source);while(m!==null)out.add(m[1]),m=IMPORT_REGEX_SINGLE.exec(source);IMPORT_REGEX_GROUP.lastIndex=0,m=IMPORT_REGEX_GROUP.exec(source);while(m!==null){let block=m[1];IMPORT_REGEX_GROUP_LINE.lastIndex=0;let inner=IMPORT_REGEX_GROUP_LINE.exec(block);while(inner!==null)out.add(inner[1]),inner=IMPORT_REGEX_GROUP_LINE.exec(block);m=IMPORT_REGEX_GROUP.exec(source)}return[...out]}async function selectFramework(dir){let content;try{content=fs77.readFileSync(path155.join(dir,"go.mod"),"utf-8")}catch{return null}let candidates=[["github.com/gin-gonic/gin","gin"],["github.com/labstack/echo","echo"],["github.com/gofiber/fiber","fiber"],["github.com/gorilla/mux","gorilla"],["github.com/go-chi/chi","chi"]];for(let[pkg,name]of candidates)if(content.includes(pkg))return{name,detectedVia:`go.mod require ${pkg}`};return null}async function selectEntryPoints(dir){let points=[];try{fs77.accessSync(path155.join(dir,"main.go")),points.push("main.go")}catch{}try{let cmdDir=path155.join(dir,"cmd"),subdirs=fs77.readdirSync(cmdDir,{withFileTypes:!0}).filter((d)=>d.isDirectory());for(let sub of subdirs){let main=path155.join("cmd",sub.name,"main.go");try{fs77.accessSync(path155.join(dir,main)),points.push(main)}catch{}}}catch{}return points}function buildGoBackend(){let profile=LANGUAGE_REGISTRY.get(PROFILE_ID);if(!profile)throw Error("buildGoBackend: go profile not in LANGUAGE_REGISTRY. profiles.ts must be imported before this backend.");return{...defaultBackendFor(profile),extractImports,selectFramework,selectEntryPoints}}var PROFILE_ID="go",IMPORT_REGEX_SINGLE,IMPORT_REGEX_GROUP,IMPORT_REGEX_GROUP_LINE,_internals121;var init_go2=__esm(()=>{init_default_backend();init_profiles();IMPORT_REGEX_SINGLE=/^\s*import\s+(?:[a-zA-Z_.][a-zA-Z0-9_]*\s+)?"([^"]+)"/gm,IMPORT_REGEX_GROUP=/^\s*import\s*\(([\s\S]*?)\)/gm,IMPORT_REGEX_GROUP_LINE=/(?:[a-zA-Z_.][a-zA-Z0-9_]*\s+)?"([^"]+)"/g;_internals121={extractImports}});import*as fs78 from"node:fs";import*as path156 from"node:path";function parseImportTargets(rawTargets){let cleaned=rawTargets.replace(/[()]/g,"").split(`
|
|
2041
2041
|
`).map((line)=>line.replace(/#.*$/,"").replace(/\\\s*$/,"")).join(" "),out=[];for(let seg of cleaned.split(",")){let trimmed=seg.trim();if(trimmed.length===0)continue;let name=trimmed.split(/\s+as\s+/)[0].trim();if(/^[\w]+$/.test(name))out.push(name)}return out}function extractImports2(_sourceFile,source){let out=new Set;source=source.replace(/\\\r?\n[ \t]*/g," "),IMPORT_REGEX_FROM_WITH_TARGETS.lastIndex=0;let m=IMPORT_REGEX_FROM_WITH_TARGETS.exec(source);while(m!==null){let fromClause=m[1],targets=parseImportTargets(m[2]);if(fromClause.length>0&&/^\.+$/.test(fromClause)&&targets.length>0)for(let t of targets)out.add(`${fromClause}${t}`);else if(fromClause.length>0)out.add(fromClause);m=IMPORT_REGEX_FROM_WITH_TARGETS.exec(source)}IMPORT_REGEX_IMPORT.lastIndex=0,m=IMPORT_REGEX_IMPORT.exec(source);while(m!==null){let segments=m[1].split(",");for(let seg of segments){let trimmed=seg.trim();if(trimmed.length===0)continue;let mod=trimmed.split(/\s+as\s+/)[0].trim();if(/^[\w.]+$/.test(mod))out.add(mod)}m=IMPORT_REGEX_IMPORT.exec(source)}return[...out]}async function selectFramework2(dir){let candidates=[["django","django"],["flask","flask"],["fastapi","fastapi"],["starlette","starlette"],["tornado","tornado"],["aiohttp","aiohttp"],["bottle","bottle"]];for(let candidate of["pyproject.toml","requirements.txt","setup.py"])try{let lower=fs78.readFileSync(path156.join(dir,candidate),"utf-8").toLowerCase();for(let[pkg,name]of candidates)if(lower.includes(pkg))return{name,detectedVia:candidate}}catch{}return null}async function selectEntryPoints2(dir){let points=new Set;try{let scriptsBlock=fs78.readFileSync(path156.join(dir,"pyproject.toml"),"utf-8").match(/\[project\.scripts\][\s\S]*?(?=\n\[|$)/);if(scriptsBlock)for(let line of scriptsBlock[0].split(`
|
|
2042
2042
|
`)){let m=line.match(/=\s*['"]([^'":]+)/);if(m){let modPath=`${m[1].replace(/\./g,"/")}.py`;points.add(modPath)}}}catch{}for(let name of["manage.py","main.py","app.py","__main__.py"])try{fs78.accessSync(path156.join(dir,name)),points.add(name)}catch{}return[...points]}function buildPythonBackend(){let profile=LANGUAGE_REGISTRY.get(PROFILE_ID2);if(!profile)throw Error("buildPythonBackend: python profile not in LANGUAGE_REGISTRY. profiles.ts must be imported before this backend.");return{...defaultBackendFor(profile),extractImports:extractImports2,selectFramework:selectFramework2,selectEntryPoints:selectEntryPoints2}}var PROFILE_ID2="python",IMPORT_REGEX_FROM_WITH_TARGETS,IMPORT_REGEX_IMPORT,_internals122;var init_python2=__esm(()=>{init_default_backend();init_profiles();IMPORT_REGEX_FROM_WITH_TARGETS=/^\s*from\s+(\.*[\w.]*)\s+import\s+(\([^)]*\)|[^\n#]+)/gm,IMPORT_REGEX_IMPORT=/^\s*import\s+([^\n#]+)/gm;_internals122={extractImports:extractImports2}});import fs79 from"node:fs";import path157 from"node:path";function normalizePath2(p){return p.replace(/\\/g,"/")}function sharedTrailingSegments(a,b){let aParts=normalizePath2(a).split("/").filter(Boolean),bParts=normalizePath2(b).split("/").filter(Boolean),i=aParts.length-1,j=bParts.length-1,shared=0;while(i>=0&&j>=0&&aParts[i]===bParts[j])shared++,i--,j--;return shared}function isCacheStale(impactMap,generatedAtMs){for(let sourcePath of Object.keys(impactMap))try{if(fs79.statSync(sourcePath).mtimeMs>generatedAtMs)return!0}catch{return!0}return!1}function resolveRelativeImport(fromDir,importPath){if(!importPath.startsWith("."))return null;let resolved=path157.resolve(fromDir,importPath);if(path157.extname(resolved)){if(fs79.existsSync(resolved)&&fs79.statSync(resolved).isFile())return normalizePath2(resolved)}else for(let ext of EXTENSIONS_TO_TRY){let withExt=resolved+ext;if(fs79.existsSync(withExt)&&fs79.statSync(withExt).isFile())return normalizePath2(withExt)}return null}function resolvePythonImport(fromDir,module){if(!module.startsWith("."))return null;let leadingDots=module.match(/^\.+/)?.[0].length??0,baseDir=fromDir;for(let i=1;i<leadingDots;i++)baseDir=path157.dirname(baseDir);let rest=module.slice(leadingDots);if(rest.length===0){let initPath=path157.join(baseDir,"__init__.py");if(fs79.existsSync(initPath)&&fs79.statSync(initPath).isFile())return normalizePath2(initPath);return null}let subpath=rest.replace(/\./g,path157.sep),candidates=[`${path157.join(baseDir,subpath)}.py`,path157.join(baseDir,subpath,"__init__.py")];for(let c of candidates)if(fs79.existsSync(c)&&fs79.statSync(c).isFile())return normalizePath2(c);return null}function findGoModule(fromDir){let cur=path157.resolve(fromDir),walked=[];for(let i=0;i<16;i++){let cached3=goModuleCache.get(cur);if(cached3!==void 0){for(let d of walked)goModuleCache.set(d,cached3);return cached3}walked.push(cur);try{let goMod=path157.join(cur,"go.mod"),moduleMatch=fs79.readFileSync(goMod,"utf-8").match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);if(moduleMatch){let result={moduleRoot:cur,modulePath:moduleMatch[1]};for(let d of walked)goModuleCache.set(d,result);return result}}catch{}try{fs79.accessSync(path157.join(cur,".git"));break}catch{}let parent=path157.dirname(cur);if(parent===cur)break;cur=parent}for(let d of walked)goModuleCache.set(d,null);return null}function resolveGoImport(fromDir,importPath){let dir=null;if(importPath.startsWith("."))dir=path157.resolve(fromDir,importPath);else{let mod=findGoModule(fromDir);if(mod&&(importPath===mod.modulePath||importPath.startsWith(`${mod.modulePath}/`))){let subpath=importPath.slice(mod.modulePath.length);dir=path157.join(mod.moduleRoot,subpath)}}if(dir===null)return[];if(!fs79.existsSync(dir)||!fs79.statSync(dir).isDirectory())return[];try{return fs79.readdirSync(dir).filter((f)=>f.endsWith(".go")&&!f.endsWith("_test.go")).map((f)=>normalizePath2(path157.join(dir,f)))}catch{return[]}}function _clearGoModuleCache(){goModuleCache.clear()}function findTestFilesSync(cwd){let testFiles=[],skipDirs=new Set(["node_modules","dist",".git",".swarm",".cache"]);function walk(dir,visitedRealPaths){let entries;try{entries=fs79.readdirSync(dir,{withFileTypes:!0})}catch{return}let realPath;try{realPath=normalizePath2(fs79.realpathSync.native(dir))}catch{return}let directoryKey=process.platform==="win32"?realPath.toLowerCase():realPath;if(visitedRealPaths.has(directoryKey))return;visitedRealPaths.add(directoryKey);for(let entry of entries)if(entry.isDirectory()){if(!skipDirs.has(entry.name))walk(path157.join(dir,entry.name),visitedRealPaths)}else if(entry.isFile()){let name=entry.name,isTsTest=/\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name)||dir.includes("__tests__")&&/\.(ts|tsx|js|jsx)$/.test(name),isPyTest=/^test_.+\.py$/.test(name)||/.+_test\.py$/.test(name)||dir.includes(`${path157.sep}tests${path157.sep}`)&&name.endsWith(".py"),isGoTest=/.+_test\.go$/.test(name);if(isTsTest||isPyTest||isGoTest)testFiles.push(normalizePath2(path157.join(dir,entry.name)))}}return walk(cwd,new Set),[...new Set(testFiles)]}function extractImports3(content){function execRegex(regex,content2){let results=[];regex.lastIndex=0;let match;while((match=regex.exec(content2))!==null)results.push(match[1]);return results}return[...execRegex(IMPORT_REGEX_ES,content),...execRegex(IMPORT_REGEX_REQUIRE,content),...execRegex(IMPORT_REGEX_REEXPORT,content)]}function addImpactEdgesForTestFile(testFile,content,impactMap){let ext=path157.extname(testFile).toLowerCase(),testDir=path157.dirname(testFile);function addEdge(source){if(!impactMap[source])impactMap[source]=[];if(!impactMap[source].includes(testFile))impactMap[source].push(testFile)}if(TS_EXTENSIONS.has(ext)){let imports=extractImports3(content);for(let importPath of imports){let resolved=resolveRelativeImport(testDir,importPath);if(resolved!==null)addEdge(resolved)}return}if(PYTHON_EXTENSIONS.has(ext)){let modules=_internals122.extractImports(testFile,content);for(let mod of modules){let resolved=resolvePythonImport(testDir,mod);if(resolved!==null)addEdge(resolved)}return}if(GO_EXTENSIONS.has(ext)){let imports=_internals121.extractImports(testFile,content);for(let importPath of imports){let sourceFiles=resolveGoImport(testDir,importPath);for(let source of sourceFiles)addEdge(source)}return}}async function buildImpactMapInternal(cwd){_clearGoModuleCache();let testFiles=findTestFilesSync(cwd),impactMap={};for(let testFile of testFiles){let content;try{content=fs79.readFileSync(testFile,"utf-8")}catch{continue}if(content.substring(0,8192).includes("\x00"))continue;addImpactEdgesForTestFile(testFile,content,impactMap)}return impactMap}async function buildImpactMap(cwd){let impactMap=await _internals123.buildImpactMapInternal(cwd);return await _internals123.saveImpactMap(cwd,impactMap),impactMap}async function loadImpactMap(cwd,options){let cachePath=path157.join(cwd,".swarm","cache","impact-map.json");if(fs79.existsSync(cachePath))try{let content=fs79.readFileSync(cachePath,"utf-8"),data=JSON.parse(content);if(data.map!==null&&typeof data.map==="object"&&!Array.isArray(data.map)){let map3=data.map;if(Object.values(map3).every((v)=>Array.isArray(v)&&v.every((item)=>typeof item==="string"))){let generatedAt=new Date(data.generatedAt).getTime();if(!_internals123.isCacheStale(map3,generatedAt))return map3;if(options?.skipRebuild)return map3}}if(options?.skipRebuild)return{}}catch{if(options?.skipRebuild)return{}}if(options?.skipRebuild)return{};return _internals123.buildImpactMap(cwd)}async function saveImpactMap(cwd,impactMap){if(!path157.isAbsolute(cwd))throw Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);_internals123.validateProjectRoot(cwd);let cacheDir2=path157.join(cwd,".swarm","cache"),cachePath=path157.join(cacheDir2,"impact-map.json");if(!fs79.existsSync(cacheDir2))fs79.mkdirSync(cacheDir2,{recursive:!0});let data={generatedAt:new Date().toISOString(),fileCount:Object.keys(impactMap).length,map:impactMap};fs79.writeFileSync(cachePath,JSON.stringify(data,null,2),"utf-8")}async function analyzeImpact(changedFiles,cwd,budget){if(!Array.isArray(changedFiles))return{impactedTests:[],unrelatedTests:[],untestedFiles:[],impactMap:{}};let validFiles=changedFiles.filter((f)=>typeof f==="string"&&f.length>0&&!f.includes("\x00")),impactMap=await _internals123.loadImpactMap(cwd),impactedTestsSet=new Set,untestedFiles=[],visitedCount=0,budgetExceeded=!1;for(let changedFile of validFiles){if(budget!==void 0&&visitedCount>=budget){budgetExceeded=!0;break}let normalizedChanged=normalizePath2(path157.resolve(changedFile)),tests=impactMap[normalizedChanged];if(tests&&tests.length>0){for(let test of tests){if(budget!==void 0&&visitedCount>=budget){budgetExceeded=!0;break}impactedTestsSet.add(test),visitedCount++}if(budgetExceeded)break}else{let changedDir=normalizePath2(path157.dirname(normalizedChanged)),changedInputDir=normalizePath2(path157.dirname(changedFile)),suffixMatches=Object.entries(impactMap).filter(([sourcePath])=>{return sourcePath.endsWith(changedFile)||changedFile.endsWith(sourcePath)||sourcePath.endsWith(normalizedChanged)||normalizedChanged.endsWith(sourcePath)}).sort(([sourceA],[sourceB])=>{let sourceDirA=normalizePath2(path157.dirname(sourceA)),sourceDirB=normalizePath2(path157.dirname(sourceB)),exactA=sourceDirA===changedDir||changedInputDir!=="."&&(sourceDirA===changedInputDir||sourceDirA.endsWith(`/${changedInputDir}`)),exactB=sourceDirB===changedDir||changedInputDir!=="."&&(sourceDirB===changedInputDir||sourceDirB.endsWith(`/${changedInputDir}`));if(exactA!==exactB)return exactA?-1:1;let sharedA=Math.max(sharedTrailingSegments(sourceDirA,changedDir),changedInputDir==="."?0:sharedTrailingSegments(sourceDirA,changedInputDir)),sharedB=Math.max(sharedTrailingSegments(sourceDirB,changedDir),changedInputDir==="."?0:sharedTrailingSegments(sourceDirB,changedInputDir)),nearestA=sharedA>0,nearestB=sharedB>0;if(nearestA!==nearestB)return nearestA?-1:1;if(sharedA!==sharedB)return sharedB-sharedA;return sourceA.localeCompare(sourceB)}),found=suffixMatches.length>0;for(let[,tests2]of suffixMatches){if(budget!==void 0&&visitedCount>=budget){budgetExceeded=!0;break}for(let test of tests2){if(budget!==void 0&&visitedCount>=budget){budgetExceeded=!0;break}impactedTestsSet.add(test),visitedCount++}if(budgetExceeded)break}if(budgetExceeded)break;if(!found)untestedFiles.push(changedFile)}}let impactedTests=[...impactedTestsSet],allTestFiles=new Set;for(let tests of Object.values(impactMap))for(let test of tests)allTestFiles.add(test);let unrelatedTests=[...allTestFiles].filter((t)=>!impactedTestsSet.has(t));return{impactedTests,unrelatedTests,untestedFiles,impactMap,budgetExceeded}}var IMPORT_REGEX_ES,IMPORT_REGEX_REQUIRE,IMPORT_REGEX_REEXPORT,TS_EXTENSIONS,PYTHON_EXTENSIONS,GO_EXTENSIONS,EXTENSIONS_TO_TRY,goModuleCache,_internals123;var init_analyzer=__esm(()=>{init_manager2();init_go2();init_python2();IMPORT_REGEX_ES=/import\s+[\s\S]*?\s+from\s+['"]([^'"]+)['"]/g,IMPORT_REGEX_REQUIRE=/require\s*\(\s*['"]([^'"]+)['"]\s*\)/g,IMPORT_REGEX_REEXPORT=/export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g,TS_EXTENSIONS=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs"]),PYTHON_EXTENSIONS=new Set([".py"]),GO_EXTENSIONS=new Set([".go"]),EXTENSIONS_TO_TRY=[".ts",".tsx",".js",".jsx",".mjs",".cjs"];goModuleCache=new Map;_internals123={validateProjectRoot,normalizePath:normalizePath2,isCacheStale,resolveRelativeImport,findTestFilesSync,extractImports:extractImports3,buildImpactMapInternal,buildImpactMap,loadImpactMap,saveImpactMap,analyzeImpact,_clearGoModuleCache}});function computeCombinedFlakyScore(recent){let totalRuns=recent.length;if(totalRuns<2)return{alternationCount:0,flakyScore:0};let alternationCount=0,passCount=0;for(let i=0;i<recent.length;i++){if(recent[i].result==="pass")passCount++;if(i>0&&recent[i].result!==recent[i-1].result)alternationCount++}let alternationScore=alternationCount/totalRuns,passRate=passCount/totalRuns,passRateVarianceScore=4*passRate*(1-passRate);return{alternationCount,flakyScore:(alternationScore+passRateVarianceScore)/2}}function detectFlakyTests(allHistory){let grouped=new Map;for(let record3 of allHistory){let key=`${record3.testFile.toLowerCase()}\x00${record3.testName.toLowerCase()}`;if(!grouped.has(key))grouped.set(key,{records:[],originalFile:record3.testFile,originalName:record3.testName});grouped.get(key).records.push(record3)}let results=[];for(let[_key,entry]of grouped){let records=entry.records;if(records.length===0)continue;let recent=records.slice().sort((a,b)=>new Date(a.timestamp).getTime()-new Date(b.timestamp).getTime()).slice(-20),totalRuns=recent.length;if(totalRuns<2)continue;let{alternationCount,flakyScore}=computeCombinedFlakyScore(recent),isQuarantined=flakyScore>0.3&&totalRuns>=5,recentResults=recent.map((r)=>r.result),testFile=entry.originalFile,testName=entry.originalName,recommendation;if(isQuarantined){if(alternationCount===totalRuns-1)recommendation="Highly unstable — investigate test isolation issues, mock cleanup, or shared state";else if(flakyScore>0.5)recommendation="Severely flaky — consider quarantining and rewriting test with proper isolation";else if(flakyScore>0.3)recommendation="Moderately flaky — review for timing dependencies, async issues, or environmental factors"}results.push({testFile,testName,flakyScore,totalRuns,alternationCount,isQuarantined,recentResults,recommendation})}return results}import fs80 from"node:fs";import path158 from"node:path";function getHistoryPath(workingDir){if(!workingDir)throw Error("getHistoryPath requires a working directory — project root must be provided by the caller");if(!path158.isAbsolute(workingDir))throw Error(`getHistoryPath requires an absolute project root path, got: "${workingDir}"`);return path158.join(workingDir,".swarm","cache","test-history.jsonl")}function sanitizeErrorMessage(errorMessage2){if(errorMessage2===void 0)return;if(errorMessage2.length>MAX_ERROR_LENGTH)return errorMessage2.substring(0,MAX_ERROR_LENGTH);return errorMessage2}function sanitizeStackPrefix(stackPrefix){if(stackPrefix===void 0)return;if(stackPrefix.length>MAX_STACK_LENGTH)return stackPrefix.substring(0,MAX_STACK_LENGTH);return stackPrefix}function sanitizeChangedFiles(changedFiles){return changedFiles.filter((f)=>typeof f==="string"&&f.length>0&&!DANGEROUS_PROPERTY_NAMES.has(f)).slice(0,MAX_CHANGED_FILES)}function isTestRunResult(value){return value==="pass"||value==="fail"||value==="skip"}function parseStoredRecord(value){if(typeof value!=="object"||value===null)return null;let record3=value;if(typeof record3.testFile!=="string"||record3.testFile.length===0)return null;if(typeof record3.testName!=="string"||record3.testName.length===0)return null;if(typeof record3.taskId!=="string"||record3.taskId.length===0)return null;if(!isTestRunResult(record3.result))return null;if(typeof record3.durationMs!=="number"||!Number.isFinite(record3.durationMs))return null;if(typeof record3.timestamp!=="string"||Number.isNaN(Date.parse(record3.timestamp)))return null;return{timestamp:record3.timestamp,taskId:record3.taskId,testFile:record3.testFile,testName:record3.testName,result:record3.result,durationMs:Math.max(0,record3.durationMs),errorMessage:typeof record3.errorMessage==="string"?sanitizeErrorMessage(record3.errorMessage):void 0,stackPrefix:typeof record3.stackPrefix==="string"?sanitizeStackPrefix(record3.stackPrefix):void 0,changedFiles:sanitizeChangedFiles(Array.isArray(record3.changedFiles)?record3.changedFiles:[])}}function batchAppendTestRuns(records,workingDir){if(records.length===0)return;for(let record3 of records){if(typeof record3.testFile!=="string"||record3.testFile.length===0)throw TypeError("testFile must be a non-empty string");if(typeof record3.testName!=="string"||record3.testName.length===0)throw TypeError("testName must be a non-empty string");if(typeof record3.taskId!=="string"||record3.taskId.length===0)throw TypeError("taskId must be a non-empty string");if(record3.result!=="pass"&&record3.result!=="fail"&&record3.result!=="skip")throw TypeError('result must be "pass", "fail", or "skip"');if(typeof record3.durationMs!=="number"||!Number.isFinite(record3.durationMs))throw TypeError("durationMs must be a finite number");if(record3.timestamp!==void 0&&Number.isNaN(Date.parse(record3.timestamp)))throw TypeError("timestamp must be a valid ISO 8601 string");if(record3.changedFiles!==void 0&&!Array.isArray(record3.changedFiles))throw TypeError("changedFiles must be an array")}let historyPath=getHistoryPath(workingDir),historyDir=path158.dirname(historyPath);if(_internals124.validateProjectRoot(workingDir),!fs80.existsSync(historyDir))fs80.mkdirSync(historyDir,{recursive:!0});withHistoryWriteLock(historyPath,()=>{let existingRecords=readAllRecords2(historyPath),sanitizedRecords=records.map((record3)=>({...record3,timestamp:record3.timestamp||new Date().toISOString(),durationMs:Math.max(0,record3.durationMs),errorMessage:sanitizeErrorMessage(record3.errorMessage),stackPrefix:sanitizeStackPrefix(record3.stackPrefix),changedFiles:sanitizeChangedFiles(record3.changedFiles||[])}));existingRecords.push(...sanitizedRecords);let recordsByTest=new Map;for(let rec of existingRecords){let normalizedKey=`${rec.testFile.toLowerCase()}|${rec.testName.toLowerCase()}`;if(!recordsByTest.has(normalizedKey))recordsByTest.set(normalizedKey,[]);recordsByTest.get(normalizedKey).push(rec)}let prunedRecords=[];for(let[,recs]of recordsByTest){recs.sort((a,b)=>new Date(a.timestamp).getTime()-new Date(b.timestamp).getTime());let toKeep=recs.slice(-MAX_HISTORY_PER_TEST);prunedRecords.push(...toKeep)}prunedRecords.sort((a,b)=>new Date(a.timestamp).getTime()-new Date(b.timestamp).getTime());try{let content=`${prunedRecords.map((rec)=>JSON.stringify(rec)).join(`
|
|
2043
2043
|
`)}
|
|
2044
2044
|
`,tempPath=`${historyPath}.tmp`;fs80.writeFileSync(tempPath,content,"utf-8"),fs80.renameSync(tempPath,historyPath)}catch(err){try{let tempPath=`${historyPath}.tmp`;if(fs80.existsSync(tempPath))fs80.unlinkSync(tempPath)}catch{}throw Error(`Failed to write test history: ${err instanceof Error?err.message:String(err)}`)}})}function withHistoryWriteLock(historyPath,fn2){let lockPath=`${historyPath}.write-lock`,deadline=Date.now()+HISTORY_WRITE_LOCK_TIMEOUT_MS;while(!0)try{fs80.mkdirSync(lockPath);break}catch(error93){if((error93 instanceof Error&&"code"in error93?error93.code:void 0)!=="EEXIST")throw Error(`Failed to acquire test history lock: ${error93 instanceof Error?error93.message:String(error93)}`);if(Date.now()>=deadline)throw Error(`Timed out waiting for test history lock: ${historyPath}`);try{let lockStat=fs80.statSync(lockPath);if(Date.now()-lockStat.mtimeMs>=HISTORY_WRITE_LOCK_STALE_MS){fs80.rmSync(lockPath,{recursive:!0,force:!0});continue}}catch{}let remainingMs=Math.max(0,deadline-Date.now()),sleepMs=Math.min(HISTORY_WRITE_LOCK_BACKOFF_MS,remainingMs);if(sleepMs>0)sleepSync(sleepMs)}try{return fn2()}finally{try{fs80.rmSync(lockPath,{recursive:!0,force:!0})}catch{}}function sleepSync(ms){let until=Date.now()+ms;while(Date.now()<until);}}function readAllRecords2(historyPath){if(!fs80.existsSync(historyPath))return[];try{let lines=fs80.readFileSync(historyPath,"utf-8").split(`
|
|
2045
|
-
`),records=[];for(let line of lines){let trimmed=line.trim();if(trimmed.length===0)continue;try{let parsed=JSON.parse(trimmed),record3=parseStoredRecord(parsed);if(record3)records.push(record3)}catch{}}return records}catch(err){throw Error(`Failed to read test history: ${err instanceof Error?err.message:String(err)}`)}}function getAllHistory(workingDir){let historyPath=getHistoryPath(workingDir),records=readAllRecords2(historyPath);return records.sort((a,b)=>new Date(a.timestamp).getTime()-new Date(b.timestamp).getTime()),records}var MAX_HISTORY_PER_TEST=20,MAX_ERROR_LENGTH=500,MAX_STACK_LENGTH=200,MAX_CHANGED_FILES=50,HISTORY_WRITE_LOCK_TIMEOUT_MS=5000,HISTORY_WRITE_LOCK_STALE_MS=60000,HISTORY_WRITE_LOCK_BACKOFF_MS=10,DANGEROUS_PROPERTY_NAMES,_internals124;var init_history_store=__esm(()=>{init_manager2();DANGEROUS_PROPERTY_NAMES=new Set(["__proto__","constructor","prototype"]);_internals124={validateProjectRoot}});class LanguageBackendRegistry{backends=new Map;register(backend){let existing=this.backends.get(backend.id);if(existing&&existing!==backend)throw Error(`LanguageBackendRegistry: backend id "${backend.id}" registered twice. Each LanguageBackend.id must be unique.`);this.backends.set(backend.id,backend)}get(id){return this.backends.get(id)}getOrDefault(id){let registered=this.backends.get(id);if(registered)return registered;let profile=LANGUAGE_REGISTRY.get(id);if(!profile)return;return defaultBackendFor(profile)}unregister(id){this.backends.delete(id)}}var LANGUAGE_BACKEND_REGISTRY;var init_registry_backend=__esm(()=>{init_default_backend();init_profiles();LANGUAGE_BACKEND_REGISTRY=new LanguageBackendRegistry});import*as fs81 from"node:fs";import*as path159 from"node:path";function detectLaravelProject(directory){let signals=getLaravelSignals(directory);return[signals.hasArtisanFile,signals.hasLaravelFrameworkDep,signals.hasConfigApp].filter(Boolean).length>=2}function getLaravelSignals(directory){let hasArtisanFile=checkArtisanFile(directory),hasLaravelFrameworkDep=checkLaravelFrameworkDep(directory),hasConfigApp=checkConfigApp(directory);return{hasArtisanFile,hasLaravelFrameworkDep,hasConfigApp}}function checkArtisanFile(directory){let artisanPath=path159.join(directory,"artisan");if(!fs81.existsSync(artisanPath))return!1;try{return fs81.statSync(artisanPath).isFile()}catch{return!1}}function checkLaravelFrameworkDep(directory){let composerPath=path159.join(directory,"composer.json");if(!fs81.existsSync(composerPath))return!1;try{let content=fs81.readFileSync(composerPath,"utf-8");return typeof(JSON.parse(content)?.require??{})["laravel/framework"]==="string"}catch{return!1}}function checkConfigApp(directory){return fs81.existsSync(path159.join(directory,"config","app.php"))}function isLarastanConfigured(directory){let neonPath=path159.join(directory,"phpstan.neon");if(!fs81.existsSync(neonPath))return!1;try{let fd=fs81.openSync(neonPath,"r");try{let buf=Buffer.alloc(4096),bytesRead=fs81.readSync(fd,buf,0,4096,0),content=buf.subarray(0,bytesRead).toString("utf-8");return content.includes("nunomaduro/larastan")||content.includes("larastan/larastan")}finally{fs81.closeSync(fd)}}catch{return!1}}function getLaravelCommandOverlay(directory){if(!detectLaravelProject(directory))return null;let lintCommand=null;if(fs81.existsSync(path159.join(directory,"pint.json")))lintCommand="vendor/bin/pint --test";else if(fs81.existsSync(path159.join(directory,".php-cs-fixer.php")))lintCommand="vendor/bin/php-cs-fixer fix --dry-run --diff";let staticAnalysisCommand=null,staticAnalysisTool=null,hasPhpstanNeon=fs81.existsSync(path159.join(directory,"phpstan.neon")),hasPhpstanNeonDist=fs81.existsSync(path159.join(directory,"phpstan.neon.dist"));if(hasPhpstanNeon||hasPhpstanNeonDist)staticAnalysisCommand="vendor/bin/phpstan analyse",staticAnalysisTool=isLarastanConfigured(directory)?"larastan":"phpstan";return{testCommand:"php artisan test",lintCommand,staticAnalysisCommand,staticAnalysisTool,auditCommand:"composer audit --locked --format=json",supportsParallel:!0}}var init_framework_detector=()=>{};import*as fs82 from"node:fs";import*as path160 from"node:path";async function selectFramework3(dir){if(detectLaravelProject(dir))return{name:"laravel",detectedVia:"Laravel signals (artisan / composer.json / config/app.php)"};return null}async function selectTestFramework(dir){if(detectLaravelProject(dir))return{name:"php-artisan",cmd:["php","artisan","test"],cwd:dir,detectedVia:"Laravel signals (artisan / composer.json / config/app.php)"};if(fs82.existsSync(path160.join(dir,"Pest.php")))return{name:"pest",cmd:[phpVendorBin2("pest")],cwd:dir,detectedVia:"Pest.php"};if(fs82.existsSync(path160.join(dir,"phpunit.xml")))return{name:"phpunit",cmd:[phpVendorBin2("phpunit")],cwd:dir,detectedVia:"phpunit.xml"};if(fs82.existsSync(path160.join(dir,"phpunit.xml.dist")))return{name:"phpunit",cmd:[phpVendorBin2("phpunit")],cwd:dir,detectedVia:"phpunit.xml.dist"};return null}function phpVendorBin2(name){return path160.join("vendor","bin",process.platform==="win32"?`${name}.bat`:name)}function buildPhpBackend(){let profile=LANGUAGE_REGISTRY.get(PROFILE_ID3);if(!profile)throw Error("buildPhpBackend: php profile not in LANGUAGE_REGISTRY. profiles.ts must be imported before this backend.");return{...defaultBackendFor(profile),selectFramework:selectFramework3,selectTestFramework}}var PROFILE_ID3="php";var init_php2=__esm(()=>{init_default_backend();init_framework_detector();init_profiles()});import*as fs83 from"node:fs";import*as path161 from"node:path";function readPackageJsonRaw(dir){try{let content=fs83.readFileSync(path161.join(dir,"package.json"),"utf-8");return JSON.parse(content)}catch{return null}}function readPackageJson(dir){return _internals125.readPackageJsonRaw(dir)}function readPackageJsonTestScript(dir){return readPackageJson(dir)?.scripts?.test??null}function frameworkFromScriptsTest(script){if(script.includes("vitest"))return"vitest";if(script.includes("jest"))return"jest";if(script.includes("mocha"))return"mocha";if(script.includes("bun test"))return"bun:test";return null}function frameworkFromDevDeps(devDeps){if(!devDeps)return null;if(devDeps.vitest||devDeps["@vitest/ui"])return"vitest";if(devDeps.jest||devDeps["@types/jest"])return"jest";if(devDeps.mocha||devDeps["@types/mocha"])return"mocha";return null}function selectionFromFramework(profile,fwName,dir,detectedVia){let fw=profile.test.frameworks.find((f)=>f.name===fwName);if(!fw)return null;let argv=tokenizeCommand(fw.cmd);if(argv.length===0)return null;return{name:fw.name,cmd:argv,cwd:dir,detectedVia,filesIgnored:!1}}async function selectTestFramework2(dir){let profile=LANGUAGE_REGISTRY.get(PROFILE_ID4);if(!profile)return null;let pkg=readPackageJson(dir),script=pkg?.scripts?.test;if(script){let fwName=frameworkFromScriptsTest(script);if(fwName){let sel=selectionFromFramework(profile,fwName,dir,"package.json#scripts.test");if(sel)return sel}}let devDepsFw=frameworkFromDevDeps(pkg?.devDependencies);if(devDepsFw){let sel=selectionFromFramework(profile,devDepsFw,dir,"package.json#devDependencies");if(sel)return sel}return defaultSelectTestFramework(profile,dir)}function buildTestCommand(framework,files,dir,opts){let profile=LANGUAGE_REGISTRY.get(PROFILE_ID4);if(!profile)return null;return defaultBuildTestCommand(profile,framework,files,dir,opts)}function parseTestOutput(framework,stdout,stderr,exitCode){return defaultParseTestOutput(framework,stdout,stderr,exitCode)}async function selectFramework4(dir){let pkg=readPackageJson(dir);if(!pkg)return null;let deps={...pkg.dependencies,...pkg.devDependencies},order=[["next","next"],["nuxt","nuxt"],["@angular/core","angular"],["svelte","svelte"],["react","react"],["vue","vue"],["express","express"],["fastify","fastify"],["@nestjs/core","nestjs"]];for(let[pkgName,displayName]of order)if(deps[pkgName])return{name:displayName,detectedVia:`package.json#dependencies.${pkgName}`};return null}async function selectEntryPoints3(dir){let pkg=readPackageJson(dir);if(!pkg)return[];let points=[],obj=pkg;if(obj.bin)if(typeof obj.bin==="string")points.push(obj.bin);else for(let v of Object.values(obj.bin))points.push(v);if(obj.main)points.push(obj.main);if(obj.module&&obj.module!==obj.main)points.push(obj.module);if(obj.exports&&typeof obj.exports==="object"){let root=obj.exports["."];if(typeof root==="string"&&!points.includes(root))points.push(root)}return[...new Set(points.filter((p)=>p.length>0))]}function extractImports4(_sourceFile,source){let out=new Set;for(let re of[IMPORT_REGEX_ES2,IMPORT_REGEX_BARE,IMPORT_REGEX_REQUIRE2,IMPORT_REGEX_DYNAMIC,IMPORT_REGEX_REEXPORT2]){re.lastIndex=0;let m=re.exec(source);while(m!==null)out.add(m[1]),m=re.exec(source)}return[...out]}async function selectBuildCommand(dir){let profile=LANGUAGE_REGISTRY.get(PROFILE_ID4);if(!profile)return null;return defaultSelectBuildCommand(profile,dir)}async function testFilesFor(sourceFile,dir){let profile=LANGUAGE_REGISTRY.get(PROFILE_ID4);if(!profile)return[];return defaultTestFilesFor(profile,sourceFile,dir)}function buildTypescriptBackend(){let profile=LANGUAGE_REGISTRY.get(PROFILE_ID4);if(!profile)throw Error("buildTypescriptBackend: typescript profile not in LANGUAGE_REGISTRY. profiles.ts must be imported before this backend.");return{...profile,selectTestFramework:selectTestFramework2,buildTestCommand,parseTestOutput,extractImports:extractImports4,selectBuildCommand,testFilesFor,selectFramework:selectFramework4,selectEntryPoints:selectEntryPoints3}}var PROFILE_ID4="typescript",IMPORT_REGEX_ES2,IMPORT_REGEX_BARE,IMPORT_REGEX_REQUIRE2,IMPORT_REGEX_DYNAMIC,IMPORT_REGEX_REEXPORT2,_internals125;var init_typescript=__esm(()=>{init_default_backend();init_profiles();IMPORT_REGEX_ES2=/import\s+[\s\S]*?\s+from\s+['"]([^'"]+)['"]/g,IMPORT_REGEX_BARE=/import\s+['"]([^'"]+)['"]/g,IMPORT_REGEX_REQUIRE2=/require\s*\(\s*['"]([^'"]+)['"]\s*\)/g,IMPORT_REGEX_DYNAMIC=/import\s*\(\s*['"]([^'"]+)['"]\s*\)/g,IMPORT_REGEX_REEXPORT2=/export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;_internals125={readPackageJsonRaw,readPackageJsonTestScript,frameworkFromScriptsTest}});function registerAllBackends(){if(registered)return;LANGUAGE_BACKEND_REGISTRY.register(buildTypescriptBackend()),LANGUAGE_BACKEND_REGISTRY.register(buildPythonBackend()),LANGUAGE_BACKEND_REGISTRY.register(buildGoBackend()),LANGUAGE_BACKEND_REGISTRY.register(buildPhpBackend()),registered=!0}var registered=!1;var init_backends=__esm(()=>{init_registry_backend();init_go2();init_php2();init_python2();init_typescript();registerAllBackends()});var exports_dispatch={};__export(exports_dispatch,{pickedProfiles:()=>pickedProfiles,pickBackend:()=>pickBackend,clearDispatchCache:()=>clearDispatchCache,_internals:()=>_internals126});import*as fs84 from"node:fs";import*as path162 from"node:path";function safeReaddirSet(dir){try{return new Set(fs84.readdirSync(dir))}catch{return new Set}}function manifestHash(dir){let entries=safeReaddirSet(dir);if(entries.size===0)return"";let parts=[];for(let name of MANIFEST_FILES){if(!entries.has(name))continue;try{let stat15=fs84.statSync(path162.join(dir,name));parts.push(`${name}:${stat15.size}:${stat15.mtimeMs}:${stat15.ino}`)}catch{}}return parts.join("|")}function findManifestRoot(start){let resolved=path162.resolve(start),cached3=manifestRootCache.get(resolved);if(cached3!==void 0)return cached3;let cur=resolved;for(let i=0;i<32;i++){let entries=safeReaddirSet(cur);if(entries.size>0){for(let name of MANIFEST_FILES)if(entries.has(name))return manifestRootCache.set(resolved,cur),cur;if(entries.has(".git"))return manifestRootCache.set(resolved,cur),cur}let parent=path162.dirname(cur);if(parent===cur)break;cur=parent}return manifestRootCache.set(resolved,start),start}function evictIfNeeded(){if(cache2.size<=_internals126.cacheCapacity)return;let oldestKey,oldestOrder=1/0;for(let[k,v]of cache2.entries())if(v.insertOrder<oldestOrder)oldestOrder=v.insertOrder,oldestKey=k;if(oldestKey!==void 0)cache2.delete(oldestKey)}async function pickBackend(dir){let root=findManifestRoot(dir),hash4=manifestHash(root),cacheKey=root,cached3=cache2.get(cacheKey);if(cached3&&cached3.hash===hash4)return cached3.backend;if(hash4==="")return cache2.set(cacheKey,{hash:hash4,backend:null,profiles:[],insertOrder:insertCounter++}),evictIfNeeded(),null;let profiles=await _internals126.detectProjectLanguages(root);if(profiles.length===0)return cache2.set(cacheKey,{hash:hash4,backend:null,profiles:[],insertOrder:insertCounter++}),evictIfNeeded(),null;let winner=profiles[0],backend=LANGUAGE_BACKEND_REGISTRY.getOrDefault(winner.id)??null;return cache2.set(cacheKey,{hash:hash4,backend,profiles:profiles.map((p)=>({id:p.id})),insertOrder:insertCounter++}),evictIfNeeded(),backend}function pickedProfiles(dir){let root=findManifestRoot(dir);return cache2.get(root)?.profiles??[]}function clearDispatchCache(){cache2.clear(),manifestRootCache.clear(),insertCounter=0}var _internals126,cache2,insertCounter=0,MANIFEST_FILES,_MANIFEST_SET,manifestRootCache;var init_dispatch=__esm(()=>{init_backends();init_detector();init_registry_backend();_internals126={detectProjectLanguages,cacheCapacity:64},cache2=new Map,MANIFEST_FILES=["package.json","tsconfig.json","pyproject.toml","setup.py","setup.cfg","requirements.txt","Pipfile","Cargo.toml","go.mod","pom.xml","build.gradle","build.gradle.kts","build.zig","CMakeLists.txt","Makefile","meson.build","Package.swift","pubspec.yaml","Gemfile","composer.json"],_MANIFEST_SET=new Set(MANIFEST_FILES);manifestRootCache=new Map});import*as fs85 from"node:fs";import*as path163 from"node:path";async function estimateFanOut(sourceFiles,cwd){try{let impactMap=await _internals127.loadImpactMap(cwd,{skipRebuild:!0}),uniqueTestFiles=new Set;for(let sourceFile of sourceFiles){let normalizedPath2=path163.resolve(cwd,sourceFile).replace(/\\/g,"/"),testFiles=impactMap[normalizedPath2];if(testFiles)for(let testFile of testFiles)uniqueTestFiles.add(testFile)}return{estimatedCount:uniqueTestFiles.size}}catch{return{estimatedCount:0}}}function isAbsolutePath(str){if(str.startsWith("/"))return!0;if(/^[a-zA-Z]:[/\\]/.test(str))return!0;if(/^\\\\/.test(str))return!0;if(/^\\\\\.\\/.test(str))return!0;return!1}function containsPowerShellMetacharacters(str){return POWERSHELL_METACHARACTERS.test(str)}function validateArgs2(args2){if(typeof args2!=="object"||args2===null)return!1;let obj=args2;if(obj.scope!==void 0){if(obj.scope!=="all"&&obj.scope!=="convention"&&obj.scope!=="graph"&&obj.scope!=="impact"&&obj.scope!=="target")return!1}if(obj.native_target!==void 0){if(typeof obj.native_target!=="object"||obj.native_target===null)return!1;let target=obj.native_target;if(target.framework!=="go-test"&&target.framework!=="ctest")return!1;if(typeof target.name!=="string"||typeof target.path!=="string")return!1;if(target.name.length===0||target.name.length>256)return!1;if(target.path.length===0||target.path.length>1024)return!1;if(containsControlChars(target.name)||containsControlChars(target.path))return!1;if(target.framework==="go-test"&&target.name.split("/").some((p)=>!p))return!1;if(isAbsolutePath(target.path)||containsPathTraversal(target.path))return!1}if(obj.scope==="target"){if(obj.native_target===void 0)return!1;if(Array.isArray(obj.files)&&obj.files.length>0)return!1;if(obj.coverage===!0||obj.bail===!0)return!1}else if(obj.native_target!==void 0)return!1;if(obj.files!==void 0){if(!Array.isArray(obj.files))return!1;for(let f of obj.files){if(typeof f!=="string")return!1;if(isAbsolutePath(f))return!1;if(containsPathTraversal(f))return!1;if(containsControlChars(f))return!1;if(containsPowerShellMetacharacters(f))return!1}}if(obj.coverage!==void 0){if(typeof obj.coverage!=="boolean")return!1}if(obj.bail!==void 0){if(typeof obj.bail!=="boolean")return!1}if(obj.timeout_ms!==void 0){if(typeof obj.timeout_ms!=="number")return!1;if(obj.timeout_ms<0||obj.timeout_ms>MAX_TIMEOUT_MS3)return!1}return!0}function validateNativeTargetInput(target){if(target.framework!=="go-test"&&target.framework!=="ctest")return'Native target framework must be "go-test" or "ctest"';if(typeof target.name!=="string"||target.name.length===0||target.name.length>256)return"Native target name must be a non-empty string up to 256 characters";if(typeof target.path!=="string"||target.path.length===0||target.path.length>1024)return"Native target path must be a non-empty string up to 1024 characters";if(containsControlChars(target.name)||containsControlChars(target.path))return"Native target values must not contain control characters";if(target.framework==="go-test"&&target.name.split("/").some((p)=>!p))return"Go native target name must not contain empty slash-separated segments";if(isAbsolutePath(target.path))return"Native target path must be workspace-relative, not absolute";if(containsPathTraversal(target.path))return"Native target path escapes project root";return}function resolveNativeTarget(target,workingDir){let rootReal,targetReal;try{if(rootReal=fs85.realpathSync(workingDir),targetReal=fs85.realpathSync(path163.resolve(rootReal,target.path)),!fs85.statSync(targetReal).isDirectory())return{success:!1,error:"Native target path must be a directory"}}catch{return{success:!1,error:"Native target path does not exist"}}let relative35=path163.relative(rootReal,targetReal);if(relative35.startsWith("..")||path163.isAbsolute(relative35))return{success:!1,error:"Native target path escapes project root"};if(!_internals127.isCommandAvailable(target.framework==="go-test"?"go":"ctest"))return{success:!1,error:`Native target framework "${target.framework}" is unavailable`};let executionDirectory=rootReal,commandRelative=relative35;if(target.framework==="go-test"){let hasRootWorkspace=fs85.existsSync(path163.join(rootReal,"go.work")),moduleRoot;for(let current=targetReal;;current=path163.dirname(current)){if(fs85.existsSync(path163.join(current,"go.mod"))){moduleRoot=current;break}if(current===rootReal)break;let parent=path163.dirname(current);if(parent===current||path163.relative(rootReal,parent).startsWith(".."))break}if(!hasRootWorkspace&&!moduleRoot)return{success:!1,error:"Go native target requires an enclosing go.mod or go.work at the project root"};if(!hasRootWorkspace&&moduleRoot)executionDirectory=moduleRoot,commandRelative=path163.relative(moduleRoot,targetReal)}else if(!fs85.existsSync(path163.join(targetReal,"CMakeCache.txt")))return{success:!1,error:"CTest native target requires CMakeCache.txt in the target directory"};return{success:!0,target:{...target,path:commandRelative.length===0?".":commandRelative.replace(/\\/g,"/")},executionDirectory,historyPath:relative35.length===0?".":relative35.replace(/\\/g,"/")}}function hasPackageJsonDependency(deps,...patterns){for(let pattern of patterns)if(deps[pattern])return!0;return!1}function hasDevDependency(devDeps,...patterns){if(!devDeps)return!1;return hasPackageJsonDependency(devDeps,...patterns)}function detectGoTest(cwd){return _internals127.existsSync(path163.join(cwd,"go.mod"))&&_internals127.isCommandAvailable("go")}function detectJavaMaven(cwd){return _internals127.existsSync(path163.join(cwd,"pom.xml"))&&_internals127.isCommandAvailable("mvn")}function detectGradle(cwd){let hasBuildFile=_internals127.existsSync(path163.join(cwd,"build.gradle"))||_internals127.existsSync(path163.join(cwd,"build.gradle.kts")),hasGradlew=_internals127.existsSync(path163.join(cwd,"gradlew"))||_internals127.existsSync(path163.join(cwd,"gradlew.bat"));return hasBuildFile&&(hasGradlew||_internals127.isCommandAvailable("gradle"))}function detectDotnetTest(cwd){try{return _internals127.readdirSync(cwd).some((f)=>f.endsWith(".csproj"))&&_internals127.isCommandAvailable("dotnet")}catch{return!1}}function detectCTest(cwd){let hasSource=_internals127.existsSync(path163.join(cwd,"CMakeLists.txt")),hasBuildCache=_internals127.existsSync(path163.join(cwd,"CMakeCache.txt"))||_internals127.existsSync(path163.join(cwd,"build","CMakeCache.txt"));return(hasSource||hasBuildCache)&&_internals127.isCommandAvailable("ctest")}function detectSwiftTest(cwd){return _internals127.existsSync(path163.join(cwd,"Package.swift"))&&_internals127.isCommandAvailable("swift")}function detectDartTest(cwd){return _internals127.existsSync(path163.join(cwd,"pubspec.yaml"))&&(_internals127.isCommandAvailable("dart")||_internals127.isCommandAvailable("flutter"))}function detectRSpec(cwd){let hasRSpecFile=_internals127.existsSync(path163.join(cwd,".rspec")),hasGemfile=_internals127.existsSync(path163.join(cwd,"Gemfile")),hasSpecDir=_internals127.existsSync(path163.join(cwd,"spec"));return(hasRSpecFile||hasGemfile&&hasSpecDir)&&(_internals127.isCommandAvailable("bundle")||_internals127.isCommandAvailable("rspec"))}function detectMinitest(cwd){return _internals127.existsSync(path163.join(cwd,"test"))&&(_internals127.existsSync(path163.join(cwd,"Gemfile"))||_internals127.existsSync(path163.join(cwd,"Rakefile")))&&_internals127.isCommandAvailable("ruby")}async function detectTestFrameworkViaDispatch(cwd){try{let{pickBackend:pickBackend2}=await Promise.resolve().then(() => (init_dispatch(),exports_dispatch)),backend=await pickBackend2(cwd);if(!backend?.selectTestFramework)return"none";let sel=await backend.selectTestFramework(cwd);if(!sel)return"none";return DISPATCH_FRAMEWORK_MAP[sel.name]??"none"}catch{return"none"}}async function buildTestCommandViaDispatch(framework,scope,files,coverage,baseDir,bail,nativeTarget){if(framework==="none")return null;try{let{pickBackend:pickBackend2}=await Promise.resolve().then(() => (init_dispatch(),exports_dispatch)),backend=await pickBackend2(baseDir);if(backend?.buildTestCommand){let cmd=backend.buildTestCommand(framework,files,baseDir,{scope,coverage,bail,nativeTarget});if(cmd)return cmd}return null}catch{return null}}async function parseTestOutputViaDispatch(framework,output,baseDir){if(framework==="none")return null;try{let{pickBackend:pickBackend2}=await Promise.resolve().then(() => (init_dispatch(),exports_dispatch)),backend=await pickBackend2(baseDir);if(!backend?.parseTestOutput)return null;let summary=backend.parseTestOutput(framework,output,"",0),passed=summary.passed??0,failed=summary.failed??0,skipped=summary.skipped??0,total=summary.total??passed+failed+skipped,result={totals:{passed,failed,skipped,total}};if(summary.coveragePercent!==void 0)result.coveragePercent=summary.coveragePercent;return result}catch{return null}}async function detectTestFramework(cwd){let baseDir=cwd;try{let packageJsonPath=path163.join(baseDir,"package.json");if(_internals127.existsSync(packageJsonPath)){let content=_internals127.readFileSync(packageJsonPath,"utf-8"),pkg=JSON.parse(content),_deps=pkg.dependencies||{},devDeps=pkg.devDependencies||{},scripts=pkg.scripts||{};if(scripts.test?.includes("vitest"))return"vitest";if(scripts.test?.includes("jest"))return"jest";if(scripts.test?.includes("mocha"))return"mocha";if(scripts.test?.includes("bun test"))return"bun";if(hasDevDependency(devDeps,"vitest","@vitest/ui"))return"vitest";if(hasDevDependency(devDeps,"jest","@types/jest"))return"jest";if(hasDevDependency(devDeps,"mocha","@types/mocha"))return"mocha";if(_internals127.existsSync(path163.join(baseDir,"bun.lockb"))||_internals127.existsSync(path163.join(baseDir,"bun.lock"))){if(scripts.test?.includes("bun"))return"bun"}}}catch{}try{let pyprojectTomlPath=path163.join(baseDir,"pyproject.toml"),setupCfgPath=path163.join(baseDir,"setup.cfg"),requirementsTxtPath=path163.join(baseDir,"requirements.txt");if(_internals127.existsSync(pyprojectTomlPath)){let content=_internals127.readFileSync(pyprojectTomlPath,"utf-8");if(content.includes("[tool.pytest"))return"pytest";if(content.includes("pytest"))return"pytest"}if(_internals127.existsSync(setupCfgPath)){if(_internals127.readFileSync(setupCfgPath,"utf-8").includes("[pytest]"))return"pytest"}if(_internals127.existsSync(requirementsTxtPath)){if(_internals127.readFileSync(requirementsTxtPath,"utf-8").includes("pytest"))return"pytest"}}catch{}try{let cargoTomlPath=path163.join(baseDir,"Cargo.toml");if(_internals127.existsSync(cargoTomlPath)){let content=_internals127.readFileSync(cargoTomlPath,"utf-8");if(content.includes("[dev-dependencies]")){if(content.includes("tokio")||content.includes("mockall")||content.includes("pretty_assertions"))return"cargo"}}}catch{}try{let pesterConfigPath=path163.join(baseDir,"pester.config.ps1"),pesterConfigJsonPath=path163.join(baseDir,"pester.config.ps1.json"),pesterPs1Path=path163.join(baseDir,"tests.ps1");if(_internals127.existsSync(pesterConfigPath)||_internals127.existsSync(pesterConfigJsonPath)||_internals127.existsSync(pesterPs1Path))return"pester"}catch{}let phpFramework=detectPhpTest(baseDir);if(phpFramework)return phpFramework;if(detectGoTest(baseDir))return"go-test";if(detectJavaMaven(baseDir))return"maven";if(detectGradle(baseDir))return"gradle";if(detectDotnetTest(baseDir))return"dotnet-test";if(detectCTest(baseDir))return"ctest";if(detectSwiftTest(baseDir))return"swift-test";if(detectDartTest(baseDir))return"dart-test";if(detectRSpec(baseDir))return"rspec";if(detectMinitest(baseDir))return"minitest";return"none"}function detectPhpTest(cwd){if(_internals127.existsSync(path163.join(cwd,"artisan"))&&_internals127.existsSync(path163.join(cwd,"composer.json")))return"php-artisan";if(_internals127.existsSync(path163.join(cwd,"Pest.php")))return"pest";if(_internals127.existsSync(path163.join(cwd,"phpunit.xml"))||_internals127.existsSync(path163.join(cwd,"phpunit.xml.dist")))return"phpunit";return null}function isTestDirectoryPath(normalizedPath2){return normalizedPath2.split("/").some((segment)=>TEST_DIRECTORY_NAMES.includes(segment))}function resolveWorkspacePath(file3,workingDir){return path163.isAbsolute(file3)?path163.resolve(file3):path163.resolve(workingDir,file3)}function toWorkspaceOutputPath(absolutePath2,workingDir,preferRelative){if(!preferRelative)return absolutePath2;return path163.relative(workingDir,absolutePath2)}function dedupePush(target,value){if(!target.includes(value))target.push(value)}function buildLanguageSpecificTestNames(nameWithoutExt,ext){switch(ext){case".go":return[`${nameWithoutExt}_test.go`];case".py":return[`test_${nameWithoutExt}.py`,`${nameWithoutExt}_test.py`];case".rb":return[`${nameWithoutExt}_spec.rb`];case".java":return[`${nameWithoutExt}Test.java`,`${nameWithoutExt}Tests.java`,`Test${nameWithoutExt}.java`,`${nameWithoutExt}IT.java`];case".cs":return[`${nameWithoutExt}Test.cs`,`${nameWithoutExt}Tests.cs`];case".kt":return[`${nameWithoutExt}Test.kt`,`${nameWithoutExt}Tests.kt`,`Test${nameWithoutExt}.kt`];case".php":return[`${nameWithoutExt}Test.php`,`${nameWithoutExt}Tests.php`,`Test${nameWithoutExt}.php`];case".ps1":return[`${nameWithoutExt}.Tests.ps1`,`${nameWithoutExt}.tests.ps1`];default:return[]}}function getRepoLevelCandidateDirectories(workingDir,relativePath2,ext){let relativeDir=path163.dirname(relativePath2),nestedRelativeDir=relativeDir==="."?"":relativeDir,directories=TEST_DIRECTORY_NAMES.flatMap((dirName)=>{let rootDir=path163.join(workingDir,dirName);return nestedRelativeDir?[rootDir,path163.join(rootDir,nestedRelativeDir)]:[rootDir]}),normalizedRelativePath=relativePath2.replace(/\\/g,"/");if(ext===".java"&&normalizedRelativePath.startsWith("src/main/java/"))directories.push(path163.join(workingDir,"src/test/java",path163.dirname(normalizedRelativePath.slice(14))));if((ext===".kt"||ext===".java")&&normalizedRelativePath.startsWith("src/main/kotlin/"))directories.push(path163.join(workingDir,"src/test/kotlin",path163.dirname(normalizedRelativePath.slice(16))));return[...new Set(directories)]}function hasCompoundTestExtension(filename){let lower=filename.toLowerCase();return COMPOUND_TEST_EXTENSIONS.some((ext)=>lower.endsWith(ext))}function isLanguageSpecificTestFile(basename27){let lower=basename27.toLowerCase();if(lower.endsWith("_test.go"))return!0;if(lower.endsWith(".py")&&(lower.startsWith("test_")||lower.endsWith("_test.py")))return!0;if(lower.endsWith("_spec.rb"))return!0;if(lower.endsWith(".java")&&(/^Test[A-Z]/.test(basename27)||basename27.endsWith("Test.java")||basename27.endsWith("Tests.java")||lower.endsWith("it.java")))return!0;if(lower.endsWith(".cs")&&(lower.endsWith("test.cs")||lower.endsWith("tests.cs")))return!0;if(lower.endsWith(".kt")&&(/^Test[A-Z]/.test(basename27)||lower.endsWith("test.kt")||lower.endsWith("tests.kt")))return!0;if(lower.endsWith(".php")&&(/^Test[A-Z]/.test(basename27)||basename27.endsWith("Test.php")||basename27.endsWith("Tests.php")))return!0;if(lower.endsWith(".tests.ps1"))return!0;return!1}function isConventionTestFilePath(filePath){let normalizedPath2=filePath.replace(/\\/g,"/"),basename27=path163.basename(filePath);return hasCompoundTestExtension(basename27)||basename27.includes(".spec.")||basename27.includes(".test.")||isLanguageSpecificTestFile(basename27)||isTestDirectoryPath(normalizedPath2)}function getTestFilesFromConvention(sourceFiles,workingDir=process.cwd()){let testFiles=[];for(let file3 of sourceFiles){let absoluteFile=resolveWorkspacePath(file3,workingDir),relativeFile=path163.relative(workingDir,absoluteFile),basename27=path163.basename(absoluteFile),dirname74=path163.dirname(absoluteFile),preferRelativeOutput=!path163.isAbsolute(file3);if(isConventionTestFilePath(relativeFile)||isConventionTestFilePath(file3)){dedupePush(testFiles,toWorkspaceOutputPath(absoluteFile,workingDir,preferRelativeOutput));continue}let nameWithoutExt=basename27.replace(/\.[^.]+$/,""),ext=path163.extname(basename27),genericTestNames=[`${nameWithoutExt}.spec${ext}`,`${nameWithoutExt}.test${ext}`],languageSpecificTestNames=buildLanguageSpecificTestNames(nameWithoutExt,ext),colocatedCandidates=[...genericTestNames,...languageSpecificTestNames].map((candidateName)=>path163.join(dirname74,candidateName)),testDirectoryNames=[basename27,...genericTestNames,...languageSpecificTestNames],repoLevelDirectories=getRepoLevelCandidateDirectories(workingDir,relativeFile,ext),possibleTestFiles=[...colocatedCandidates,...TEST_DIRECTORY_NAMES.flatMap((dirName)=>testDirectoryNames.map((candidateName)=>path163.join(dirname74,dirName,candidateName))),...repoLevelDirectories.flatMap((candidateDir)=>testDirectoryNames.map((candidateName)=>path163.join(candidateDir,candidateName)))];for(let testFile of possibleTestFiles)if(fs85.existsSync(testFile))dedupePush(testFiles,toWorkspaceOutputPath(testFile,workingDir,preferRelativeOutput))}return testFiles}async function getTestFilesFromGraph(sourceFiles,workingDir){let testFiles=[],absoluteSourceFiles=sourceFiles.map((sourceFile)=>resolveWorkspacePath(sourceFile,workingDir)),candidateTestFiles=getTestFilesFromConvention(sourceFiles,workingDir);if(sourceFiles.length===0)return testFiles;for(let testFile of candidateTestFiles)try{let absoluteTestFile=resolveWorkspacePath(testFile,workingDir),content=fs85.readFileSync(absoluteTestFile,"utf-8"),testDir=path163.dirname(absoluteTestFile),importRegex=/import\s+.*?\s+from\s+['"]([^'"]+)['"]/g,match;match=importRegex.exec(content);while(match!==null){let importPath=match[1],resolvedImport;if(importPath.startsWith(".")){if(resolvedImport=path163.resolve(testDir,importPath),!path163.extname(resolvedImport))for(let extToTry of[".ts",".tsx",".js",".jsx",".mjs",".cjs"]){let withExt=resolvedImport+extToTry;if(absoluteSourceFiles.includes(withExt)||fs85.existsSync(withExt)){resolvedImport=withExt;break}}}else continue;let importBasename=path163.basename(resolvedImport,path163.extname(resolvedImport)),importDir=path163.dirname(resolvedImport);for(let sourceFile of absoluteSourceFiles){let sourceDir=path163.dirname(sourceFile),sourceBasename=path163.basename(sourceFile,path163.extname(sourceFile)),isRelatedDir=importDir===sourceDir||importDir===path163.join(sourceDir,"__tests__")||importDir===path163.join(sourceDir,"tests")||importDir===path163.join(sourceDir,"test")||importDir===path163.join(sourceDir,"spec");if(resolvedImport===sourceFile||importBasename===sourceBasename&&isRelatedDir){dedupePush(testFiles,testFile);break}}match=importRegex.exec(content)}let requireRegex=/require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;match=requireRegex.exec(content);while(match!==null){let importPath=match[1];if(importPath.startsWith(".")){let resolvedImport=path163.resolve(testDir,importPath);if(!path163.extname(resolvedImport))for(let extToTry of[".ts",".tsx",".js",".jsx",".mjs",".cjs"]){let withExt=resolvedImport+extToTry;if(absoluteSourceFiles.includes(withExt)||fs85.existsSync(withExt)){resolvedImport=withExt;break}}let importDir=path163.dirname(resolvedImport),importBasename=path163.basename(resolvedImport,path163.extname(resolvedImport));for(let sourceFile of absoluteSourceFiles){let sourceDir=path163.dirname(sourceFile),sourceBasename=path163.basename(sourceFile,path163.extname(sourceFile)),isRelatedDir=importDir===sourceDir||importDir===path163.join(sourceDir,"__tests__")||importDir===path163.join(sourceDir,"tests")||importDir===path163.join(sourceDir,"test")||importDir===path163.join(sourceDir,"spec");if(resolvedImport===sourceFile||importBasename===sourceBasename&&isRelatedDir){dedupePush(testFiles,testFile);break}}}match=requireRegex.exec(content)}}catch{}return testFiles}function getTargetedExecutionUnsupportedReason(framework){switch(framework){case"go-test":return"go test targets packages, not individual test files";case"cargo":return"cargo test targets crates, targets, or test names rather than file paths";case"maven":return"maven test selection is class-based, not file-path based";case"gradle":return"gradle test selection is class-based, not file-path based";case"dotnet-test":return"dotnet test filters by fully qualified names, not file paths";case"ctest":return"ctest filters named tests from the build tree, not source test files";case"swift-test":return"swift test filters test names, not file paths";default:return null}}function buildTestCommand2(framework,scope,files,coverage,baseDir,bail,nativeTarget){if(nativeTarget)return nativeTarget.framework===framework?buildNativeTargetCommand(nativeTarget):null;switch(framework){case"bun":{let args2=["bun","test"];if(coverage)args2.push("--coverage");if(bail)args2.push("--bail");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"vitest":{let args2=["npx","vitest","run","--reporter=json","--outputFile",VITEST_JSON_OUTPUT_RELATIVE_PATH];if(coverage)args2.push("--coverage");if(bail)args2.push("--bail=1");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"jest":{let args2=["npx","jest","--json"];if(coverage)args2.push("--coverage");if(bail)args2.push("--bail");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"mocha":{let args2=["npx","mocha"];if(bail)args2.push("--bail");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"pytest":{let args2=process.platform==="win32"?["python","-m","pytest"]:["python3","-m","pytest"];if(coverage)args2.push("--cov=.","--cov-report=term-missing");if(bail)args2.push("-x");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"cargo":{let args2=["cargo","test"];if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"pester":{if(scope!=="all"&&files.length>0){let psCommand=`Invoke-Pester -Path @('${files.map((f)=>f.replace(/'/g,"''").replace(/`/g,"``").replace(/\$/g,"`$")).join("','")}')`;return["pwsh","-EncodedCommand",Buffer.from(psCommand,"utf16le").toString("base64")]}return["pwsh","-Command","Invoke-Pester"]}case"go-test":return["go","test","./..."];case"maven":return["mvn","test"];case"gradle":{let isWindows=process.platform==="win32",hasGradlewBat=fs85.existsSync(path163.join(baseDir,"gradlew.bat")),hasGradlew=fs85.existsSync(path163.join(baseDir,"gradlew"));if(hasGradlewBat&&isWindows)return["gradlew.bat","test"];if(hasGradlew)return["./gradlew","test"];return["gradle","test"]}case"dotnet-test":return["dotnet","test"];case"ctest":return["ctest","--test-dir",["build","_build","cmake-build-debug","cmake-build-release","out"].find((d)=>fs85.existsSync(path163.join(baseDir,d,"CMakeCache.txt")))??"build"];case"swift-test":return["swift","test"];case"dart-test":return _internals127.isCommandAvailable("flutter")?["flutter","test",...files]:["dart","test",...files];case"rspec":{let args2=_internals127.isCommandAvailable("bundle")?["bundle","exec","rspec"]:["rspec"];if(bail)args2.push("--fail-fast");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"minitest":if(scope!=="all"&&files.length>0)return["ruby","-Itest","-e",files.map((f)=>`require_relative '${f.replace(/\\/g,"/").replace(/'/g,"\\'")}'`).join("; ")];return["ruby","-Itest","-e",'Dir.glob("test/**/*_test.rb").sort.each { |f| require_relative f }'];case"pest":{let args2=[phpVendorBin3("pest")];if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"phpunit":{let args2=[phpVendorBin3("phpunit")];if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"php-artisan":{let args2=["php","artisan","test"];if(scope!=="all"&&files.length>0)args2.push(...files);return args2}default:return null}}function phpVendorBin3(name){return path163.join("vendor","bin",process.platform==="win32"?`${name}.bat`:name)}function mapFrameworkStatusToResult(status){if(typeof status!=="string")return null;let normalized=status.toLowerCase();if(normalized==="pass"||normalized==="passed")return"pass";if(normalized==="fail"||normalized==="failed")return"fail";if(normalized==="skip"||normalized==="skipped"||normalized==="pending"||normalized==="todo")return"skip";return null}function firstLine(value){if(typeof value!=="string")return;let line=value.split(`
|
|
2045
|
+
`),records=[];for(let line of lines){let trimmed=line.trim();if(trimmed.length===0)continue;try{let parsed=JSON.parse(trimmed),record3=parseStoredRecord(parsed);if(record3)records.push(record3)}catch{}}return records}catch(err){throw Error(`Failed to read test history: ${err instanceof Error?err.message:String(err)}`)}}function getAllHistory(workingDir){let historyPath=getHistoryPath(workingDir),records=readAllRecords2(historyPath);return records.sort((a,b)=>new Date(a.timestamp).getTime()-new Date(b.timestamp).getTime()),records}var MAX_HISTORY_PER_TEST=20,MAX_ERROR_LENGTH=500,MAX_STACK_LENGTH=200,MAX_CHANGED_FILES=50,HISTORY_WRITE_LOCK_TIMEOUT_MS=5000,HISTORY_WRITE_LOCK_STALE_MS=60000,HISTORY_WRITE_LOCK_BACKOFF_MS=10,DANGEROUS_PROPERTY_NAMES,_internals124;var init_history_store=__esm(()=>{init_manager2();DANGEROUS_PROPERTY_NAMES=new Set(["__proto__","constructor","prototype"]);_internals124={validateProjectRoot}});class LanguageBackendRegistry{backends=new Map;register(backend){let existing=this.backends.get(backend.id);if(existing&&existing!==backend)throw Error(`LanguageBackendRegistry: backend id "${backend.id}" registered twice. Each LanguageBackend.id must be unique.`);this.backends.set(backend.id,backend)}get(id){return this.backends.get(id)}getOrDefault(id){let registered=this.backends.get(id);if(registered)return registered;let profile=LANGUAGE_REGISTRY.get(id);if(!profile)return;return defaultBackendFor(profile)}unregister(id){this.backends.delete(id)}}var LANGUAGE_BACKEND_REGISTRY;var init_registry_backend=__esm(()=>{init_default_backend();init_profiles();LANGUAGE_BACKEND_REGISTRY=new LanguageBackendRegistry});import*as fs81 from"node:fs";import*as path159 from"node:path";function detectLaravelProject(directory){let signals=getLaravelSignals(directory);return[signals.hasArtisanFile,signals.hasLaravelFrameworkDep,signals.hasConfigApp].filter(Boolean).length>=2}function getLaravelSignals(directory){let hasArtisanFile=checkArtisanFile(directory),hasLaravelFrameworkDep=checkLaravelFrameworkDep(directory),hasConfigApp=checkConfigApp(directory);return{hasArtisanFile,hasLaravelFrameworkDep,hasConfigApp}}function checkArtisanFile(directory){let artisanPath=path159.join(directory,"artisan");if(!fs81.existsSync(artisanPath))return!1;try{return fs81.statSync(artisanPath).isFile()}catch{return!1}}function checkLaravelFrameworkDep(directory){let composerPath=path159.join(directory,"composer.json");if(!fs81.existsSync(composerPath))return!1;try{let content=fs81.readFileSync(composerPath,"utf-8");return typeof(JSON.parse(content)?.require??{})["laravel/framework"]==="string"}catch{return!1}}function checkConfigApp(directory){return fs81.existsSync(path159.join(directory,"config","app.php"))}function isLarastanConfigured(directory){let neonPath=path159.join(directory,"phpstan.neon");if(!fs81.existsSync(neonPath))return!1;try{let fd=fs81.openSync(neonPath,"r");try{let buf=Buffer.alloc(4096),bytesRead=fs81.readSync(fd,buf,0,4096,0),content=buf.subarray(0,bytesRead).toString("utf-8");return content.includes("nunomaduro/larastan")||content.includes("larastan/larastan")}finally{fs81.closeSync(fd)}}catch{return!1}}function getLaravelCommandOverlay(directory){if(!detectLaravelProject(directory))return null;let lintCommand=null;if(fs81.existsSync(path159.join(directory,"pint.json")))lintCommand="vendor/bin/pint --test";else if(fs81.existsSync(path159.join(directory,".php-cs-fixer.php")))lintCommand="vendor/bin/php-cs-fixer fix --dry-run --diff";let staticAnalysisCommand=null,staticAnalysisTool=null,hasPhpstanNeon=fs81.existsSync(path159.join(directory,"phpstan.neon")),hasPhpstanNeonDist=fs81.existsSync(path159.join(directory,"phpstan.neon.dist"));if(hasPhpstanNeon||hasPhpstanNeonDist)staticAnalysisCommand="vendor/bin/phpstan analyse",staticAnalysisTool=isLarastanConfigured(directory)?"larastan":"phpstan";return{testCommand:"php artisan test",lintCommand,staticAnalysisCommand,staticAnalysisTool,auditCommand:"composer audit --locked --format=json",supportsParallel:!0}}var init_framework_detector=()=>{};import*as fs82 from"node:fs";import*as path160 from"node:path";async function selectFramework3(dir){if(detectLaravelProject(dir))return{name:"laravel",detectedVia:"Laravel signals (artisan / composer.json / config/app.php)"};return null}async function selectTestFramework(dir){if(detectLaravelProject(dir))return{name:"php-artisan",cmd:["php","artisan","test"],cwd:dir,detectedVia:"Laravel signals (artisan / composer.json / config/app.php)"};if(fs82.existsSync(path160.join(dir,"Pest.php")))return{name:"pest",cmd:[phpVendorBin2("pest")],cwd:dir,detectedVia:"Pest.php"};if(fs82.existsSync(path160.join(dir,"phpunit.xml")))return{name:"phpunit",cmd:[phpVendorBin2("phpunit")],cwd:dir,detectedVia:"phpunit.xml"};if(fs82.existsSync(path160.join(dir,"phpunit.xml.dist")))return{name:"phpunit",cmd:[phpVendorBin2("phpunit")],cwd:dir,detectedVia:"phpunit.xml.dist"};return null}function phpVendorBin2(name){return path160.join("vendor","bin",process.platform==="win32"?`${name}.bat`:name)}function buildPhpBackend(){let profile=LANGUAGE_REGISTRY.get(PROFILE_ID3);if(!profile)throw Error("buildPhpBackend: php profile not in LANGUAGE_REGISTRY. profiles.ts must be imported before this backend.");return{...defaultBackendFor(profile),selectFramework:selectFramework3,selectTestFramework}}var PROFILE_ID3="php";var init_php2=__esm(()=>{init_default_backend();init_framework_detector();init_profiles()});import*as fs83 from"node:fs";import*as path161 from"node:path";function readPackageJsonRaw(dir){try{let content=fs83.readFileSync(path161.join(dir,"package.json"),"utf-8");return JSON.parse(content)}catch{return null}}function readPackageJson(dir){return _internals125.readPackageJsonRaw(dir)}function readPackageJsonTestScript(dir){return readPackageJson(dir)?.scripts?.test??null}function frameworkFromScriptsTest(script){if(script.includes("vitest"))return"vitest";if(script.includes("jest"))return"jest";if(script.includes("mocha"))return"mocha";if(script.includes("bun test"))return"bun:test";return null}function frameworkFromDevDeps(devDeps){if(!devDeps)return null;if(devDeps.vitest||devDeps["@vitest/ui"])return"vitest";if(devDeps.jest||devDeps["@types/jest"])return"jest";if(devDeps.mocha||devDeps["@types/mocha"])return"mocha";return null}function selectionFromFramework(profile,fwName,dir,detectedVia){let fw=profile.test.frameworks.find((f)=>f.name===fwName);if(!fw)return null;let argv=tokenizeCommand(fw.cmd);if(argv.length===0)return null;return{name:fw.name,cmd:argv,cwd:dir,detectedVia,filesIgnored:!1}}async function selectTestFramework2(dir){let profile=LANGUAGE_REGISTRY.get(PROFILE_ID4);if(!profile)return null;let pkg=readPackageJson(dir),script=pkg?.scripts?.test;if(script){let fwName=frameworkFromScriptsTest(script);if(fwName){let sel=selectionFromFramework(profile,fwName,dir,"package.json#scripts.test");if(sel)return sel}}let devDepsFw=frameworkFromDevDeps(pkg?.devDependencies);if(devDepsFw){let sel=selectionFromFramework(profile,devDepsFw,dir,"package.json#devDependencies");if(sel)return sel}return defaultSelectTestFramework(profile,dir)}function buildTestCommand(framework,files,dir,opts){let profile=LANGUAGE_REGISTRY.get(PROFILE_ID4);if(!profile)return null;return defaultBuildTestCommand(profile,framework,files,dir,opts)}function parseTestOutput(framework,stdout,stderr,exitCode){return defaultParseTestOutput(framework,stdout,stderr,exitCode)}async function selectFramework4(dir){let pkg=readPackageJson(dir);if(!pkg)return null;let deps={...pkg.dependencies,...pkg.devDependencies},order=[["next","next"],["nuxt","nuxt"],["@angular/core","angular"],["svelte","svelte"],["react","react"],["vue","vue"],["express","express"],["fastify","fastify"],["@nestjs/core","nestjs"]];for(let[pkgName,displayName]of order)if(deps[pkgName])return{name:displayName,detectedVia:`package.json#dependencies.${pkgName}`};return null}async function selectEntryPoints3(dir){let pkg=readPackageJson(dir);if(!pkg)return[];let points=[],obj=pkg;if(obj.bin)if(typeof obj.bin==="string")points.push(obj.bin);else for(let v of Object.values(obj.bin))points.push(v);if(obj.main)points.push(obj.main);if(obj.module&&obj.module!==obj.main)points.push(obj.module);if(obj.exports&&typeof obj.exports==="object"){let root=obj.exports["."];if(typeof root==="string"&&!points.includes(root))points.push(root)}return[...new Set(points.filter((p)=>p.length>0))]}function extractImports4(_sourceFile,source){let out=new Set;for(let re of[IMPORT_REGEX_ES2,IMPORT_REGEX_BARE,IMPORT_REGEX_REQUIRE2,IMPORT_REGEX_DYNAMIC,IMPORT_REGEX_REEXPORT2]){re.lastIndex=0;let m=re.exec(source);while(m!==null)out.add(m[1]),m=re.exec(source)}return[...out]}async function selectBuildCommand(dir){let profile=LANGUAGE_REGISTRY.get(PROFILE_ID4);if(!profile)return null;return defaultSelectBuildCommand(profile,dir)}async function testFilesFor(sourceFile,dir){let profile=LANGUAGE_REGISTRY.get(PROFILE_ID4);if(!profile)return[];return defaultTestFilesFor(profile,sourceFile,dir)}function buildTypescriptBackend(){let profile=LANGUAGE_REGISTRY.get(PROFILE_ID4);if(!profile)throw Error("buildTypescriptBackend: typescript profile not in LANGUAGE_REGISTRY. profiles.ts must be imported before this backend.");return{...profile,selectTestFramework:selectTestFramework2,buildTestCommand,parseTestOutput,extractImports:extractImports4,selectBuildCommand,testFilesFor,selectFramework:selectFramework4,selectEntryPoints:selectEntryPoints3}}var PROFILE_ID4="typescript",IMPORT_REGEX_ES2,IMPORT_REGEX_BARE,IMPORT_REGEX_REQUIRE2,IMPORT_REGEX_DYNAMIC,IMPORT_REGEX_REEXPORT2,_internals125;var init_typescript=__esm(()=>{init_default_backend();init_profiles();IMPORT_REGEX_ES2=/import\s+[\s\S]*?\s+from\s+['"]([^'"]+)['"]/g,IMPORT_REGEX_BARE=/import\s+['"]([^'"]+)['"]/g,IMPORT_REGEX_REQUIRE2=/require\s*\(\s*['"]([^'"]+)['"]\s*\)/g,IMPORT_REGEX_DYNAMIC=/import\s*\(\s*['"]([^'"]+)['"]\s*\)/g,IMPORT_REGEX_REEXPORT2=/export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;_internals125={readPackageJsonRaw,readPackageJsonTestScript,frameworkFromScriptsTest}});function registerAllBackends(){if(registered)return;LANGUAGE_BACKEND_REGISTRY.register(buildTypescriptBackend()),LANGUAGE_BACKEND_REGISTRY.register(buildPythonBackend()),LANGUAGE_BACKEND_REGISTRY.register(buildGoBackend()),LANGUAGE_BACKEND_REGISTRY.register(buildPhpBackend()),registered=!0}var registered=!1;var init_backends=__esm(()=>{init_registry_backend();init_go2();init_php2();init_python2();init_typescript();registerAllBackends()});var exports_dispatch={};__export(exports_dispatch,{pickedProfiles:()=>pickedProfiles,pickBackend:()=>pickBackend,clearDispatchCache:()=>clearDispatchCache,_internals:()=>_internals126});import*as fs84 from"node:fs";import*as path162 from"node:path";function safeReaddirSet(dir){try{return new Set(fs84.readdirSync(dir))}catch{return new Set}}function manifestHash(dir){let entries=safeReaddirSet(dir);if(entries.size===0)return"";let parts=[];for(let name of MANIFEST_FILES){if(!entries.has(name))continue;try{let stat15=fs84.statSync(path162.join(dir,name));parts.push(`${name}:${stat15.size}:${stat15.mtimeMs}:${stat15.ino}`)}catch{}}return parts.join("|")}function findManifestRoot(start){let resolved=path162.resolve(start),cached3=manifestRootCache.get(resolved);if(cached3!==void 0)return cached3;let cur=resolved;for(let i=0;i<32;i++){let entries=safeReaddirSet(cur);if(entries.size>0){for(let name of MANIFEST_FILES)if(entries.has(name))return manifestRootCache.set(resolved,cur),cur;if(entries.has(".git"))return manifestRootCache.set(resolved,cur),cur}let parent=path162.dirname(cur);if(parent===cur)break;cur=parent}return manifestRootCache.set(resolved,start),start}function evictIfNeeded(){if(cache2.size<=_internals126.cacheCapacity)return;let oldestKey,oldestOrder=1/0;for(let[k,v]of cache2.entries())if(v.insertOrder<oldestOrder)oldestOrder=v.insertOrder,oldestKey=k;if(oldestKey!==void 0)cache2.delete(oldestKey)}async function pickBackend(dir){let root=findManifestRoot(dir),hash4=manifestHash(root),cacheKey=root,cached3=cache2.get(cacheKey);if(cached3&&cached3.hash===hash4)return cached3.backend;if(hash4==="")return cache2.set(cacheKey,{hash:hash4,backend:null,profiles:[],insertOrder:insertCounter++}),evictIfNeeded(),null;let profiles=await _internals126.detectProjectLanguages(root);if(profiles.length===0)return cache2.set(cacheKey,{hash:hash4,backend:null,profiles:[],insertOrder:insertCounter++}),evictIfNeeded(),null;let winner=profiles[0],backend=LANGUAGE_BACKEND_REGISTRY.getOrDefault(winner.id)??null;return cache2.set(cacheKey,{hash:hash4,backend,profiles:profiles.map((p)=>({id:p.id})),insertOrder:insertCounter++}),evictIfNeeded(),backend}function pickedProfiles(dir){let root=findManifestRoot(dir);return cache2.get(root)?.profiles??[]}function clearDispatchCache(){cache2.clear(),manifestRootCache.clear(),insertCounter=0}var _internals126,cache2,insertCounter=0,MANIFEST_FILES,_MANIFEST_SET,manifestRootCache;var init_dispatch=__esm(()=>{init_backends();init_detector();init_registry_backend();_internals126={detectProjectLanguages,cacheCapacity:64},cache2=new Map,MANIFEST_FILES=["package.json","tsconfig.json","pyproject.toml","setup.py","setup.cfg","requirements.txt","Pipfile","Cargo.toml","go.mod","pom.xml","build.gradle","build.gradle.kts","build.zig","CMakeLists.txt","Makefile","meson.build","Package.swift","pubspec.yaml","Gemfile","composer.json"],_MANIFEST_SET=new Set(MANIFEST_FILES);manifestRootCache=new Map});import*as fs85 from"node:fs";import*as path163 from"node:path";async function estimateFanOut(sourceFiles,cwd){try{let impactMap=await _internals127.loadImpactMap(cwd,{skipRebuild:!0}),uniqueTestFiles=new Set;for(let sourceFile of sourceFiles){let normalizedPath2=path163.resolve(cwd,sourceFile).replace(/\\/g,"/"),testFiles=impactMap[normalizedPath2];if(testFiles)for(let testFile of testFiles)uniqueTestFiles.add(testFile)}return{estimatedCount:uniqueTestFiles.size}}catch{return{estimatedCount:0}}}function isAbsolutePath(str){if(str.startsWith("/"))return!0;if(/^[a-zA-Z]:[/\\]/.test(str))return!0;if(/^\\\\/.test(str))return!0;if(/^\\\\\.\\/.test(str))return!0;return!1}function containsPowerShellMetacharacters(str){return POWERSHELL_METACHARACTERS.test(str)}function containsShellMetacharacters(str){return SHELL_METACHARACTERS2.test(str)}function validateArgs2(args2){if(typeof args2!=="object"||args2===null)return!1;let obj=args2;if(obj.scope!==void 0){if(obj.scope!=="all"&&obj.scope!=="convention"&&obj.scope!=="graph"&&obj.scope!=="impact"&&obj.scope!=="target")return!1}if(obj.native_target!==void 0){if(typeof obj.native_target!=="object"||obj.native_target===null)return!1;let target=obj.native_target;if(target.framework!=="go-test"&&target.framework!=="ctest")return!1;if(typeof target.name!=="string"||typeof target.path!=="string")return!1;if(target.name.length===0||target.name.length>256)return!1;if(target.path.length===0||target.path.length>1024)return!1;if(containsControlChars(target.name)||containsControlChars(target.path))return!1;if(target.framework==="go-test"&&target.name.split("/").some((p)=>!p))return!1;if(isAbsolutePath(target.path)||containsPathTraversal(target.path))return!1}if(obj.scope==="target"){if(obj.native_target===void 0)return!1;if(Array.isArray(obj.files)&&obj.files.length>0)return!1;if(obj.coverage===!0||obj.bail===!0)return!1}else if(obj.native_target!==void 0)return!1;if(obj.files!==void 0){if(!Array.isArray(obj.files))return!1;for(let f of obj.files){if(typeof f!=="string")return!1;if(isAbsolutePath(f))return!1;if(containsPathTraversal(f))return!1;if(containsControlChars(f))return!1;if(containsPowerShellMetacharacters(f))return!1}}if(obj.targets!==void 0){if(!Array.isArray(obj.targets))return!1;for(let t of obj.targets){if(typeof t!=="string")return!1;if(t.length===0)return!1;if(isAbsolutePath(t))return!1;if(containsPathTraversal(t))return!1;if(containsControlChars(t))return!1;if(containsShellMetacharacters(t))return!1}}if(obj.coverage!==void 0){if(typeof obj.coverage!=="boolean")return!1}if(obj.bail!==void 0){if(typeof obj.bail!=="boolean")return!1}if(obj.timeout_ms!==void 0){if(typeof obj.timeout_ms!=="number")return!1;if(obj.timeout_ms<0||obj.timeout_ms>MAX_TIMEOUT_MS3)return!1}return!0}function validateNativeTargetInput(target){if(target.framework!=="go-test"&&target.framework!=="ctest")return'Native target framework must be "go-test" or "ctest"';if(typeof target.name!=="string"||target.name.length===0||target.name.length>256)return"Native target name must be a non-empty string up to 256 characters";if(typeof target.path!=="string"||target.path.length===0||target.path.length>1024)return"Native target path must be a non-empty string up to 1024 characters";if(containsControlChars(target.name)||containsControlChars(target.path))return"Native target values must not contain control characters";if(target.framework==="go-test"&&target.name.split("/").some((p)=>!p))return"Go native target name must not contain empty slash-separated segments";if(isAbsolutePath(target.path))return"Native target path must be workspace-relative, not absolute";if(containsPathTraversal(target.path))return"Native target path escapes project root";return}function resolveNativeTarget(target,workingDir){let rootReal,targetReal;try{if(rootReal=fs85.realpathSync(workingDir),targetReal=fs85.realpathSync(path163.resolve(rootReal,target.path)),!fs85.statSync(targetReal).isDirectory())return{success:!1,error:"Native target path must be a directory"}}catch{return{success:!1,error:"Native target path does not exist"}}let relative35=path163.relative(rootReal,targetReal);if(relative35.startsWith("..")||path163.isAbsolute(relative35))return{success:!1,error:"Native target path escapes project root"};if(!_internals127.isCommandAvailable(target.framework==="go-test"?"go":"ctest"))return{success:!1,error:`Native target framework "${target.framework}" is unavailable`};let executionDirectory=rootReal,commandRelative=relative35;if(target.framework==="go-test"){let hasRootWorkspace=fs85.existsSync(path163.join(rootReal,"go.work")),moduleRoot;for(let current=targetReal;;current=path163.dirname(current)){if(fs85.existsSync(path163.join(current,"go.mod"))){moduleRoot=current;break}if(current===rootReal)break;let parent=path163.dirname(current);if(parent===current||path163.relative(rootReal,parent).startsWith(".."))break}if(!hasRootWorkspace&&!moduleRoot)return{success:!1,error:"Go native target requires an enclosing go.mod or go.work at the project root"};if(!hasRootWorkspace&&moduleRoot)executionDirectory=moduleRoot,commandRelative=path163.relative(moduleRoot,targetReal)}else if(!fs85.existsSync(path163.join(targetReal,"CMakeCache.txt")))return{success:!1,error:"CTest native target requires CMakeCache.txt in the target directory"};return{success:!0,target:{...target,path:commandRelative.length===0?".":commandRelative.replace(/\\/g,"/")},executionDirectory,historyPath:relative35.length===0?".":relative35.replace(/\\/g,"/")}}function hasPackageJsonDependency(deps,...patterns){for(let pattern of patterns)if(deps[pattern])return!0;return!1}function hasDevDependency(devDeps,...patterns){if(!devDeps)return!1;return hasPackageJsonDependency(devDeps,...patterns)}function detectGoTest(cwd){return _internals127.existsSync(path163.join(cwd,"go.mod"))&&_internals127.isCommandAvailable("go")}function detectJavaMaven(cwd){return _internals127.existsSync(path163.join(cwd,"pom.xml"))&&_internals127.isCommandAvailable("mvn")}function detectGradle(cwd){let hasBuildFile=_internals127.existsSync(path163.join(cwd,"build.gradle"))||_internals127.existsSync(path163.join(cwd,"build.gradle.kts")),hasGradlew=_internals127.existsSync(path163.join(cwd,"gradlew"))||_internals127.existsSync(path163.join(cwd,"gradlew.bat"));return hasBuildFile&&(hasGradlew||_internals127.isCommandAvailable("gradle"))}function detectDotnetTest(cwd){try{return _internals127.readdirSync(cwd).some((f)=>f.endsWith(".csproj"))&&_internals127.isCommandAvailable("dotnet")}catch{return!1}}function detectCTest(cwd){let hasSource=_internals127.existsSync(path163.join(cwd,"CMakeLists.txt")),hasBuildCache=_internals127.existsSync(path163.join(cwd,"CMakeCache.txt"))||_internals127.existsSync(path163.join(cwd,"build","CMakeCache.txt"));return(hasSource||hasBuildCache)&&_internals127.isCommandAvailable("ctest")}function detectSwiftTest(cwd){return _internals127.existsSync(path163.join(cwd,"Package.swift"))&&_internals127.isCommandAvailable("swift")}function detectDartTest(cwd){return _internals127.existsSync(path163.join(cwd,"pubspec.yaml"))&&(_internals127.isCommandAvailable("dart")||_internals127.isCommandAvailable("flutter"))}function detectRSpec(cwd){let hasRSpecFile=_internals127.existsSync(path163.join(cwd,".rspec")),hasGemfile=_internals127.existsSync(path163.join(cwd,"Gemfile")),hasSpecDir=_internals127.existsSync(path163.join(cwd,"spec"));return(hasRSpecFile||hasGemfile&&hasSpecDir)&&(_internals127.isCommandAvailable("bundle")||_internals127.isCommandAvailable("rspec"))}function detectMinitest(cwd){return _internals127.existsSync(path163.join(cwd,"test"))&&(_internals127.existsSync(path163.join(cwd,"Gemfile"))||_internals127.existsSync(path163.join(cwd,"Rakefile")))&&_internals127.isCommandAvailable("ruby")}async function detectTestFrameworkViaDispatch(cwd){try{let{pickBackend:pickBackend2}=await Promise.resolve().then(() => (init_dispatch(),exports_dispatch)),backend=await pickBackend2(cwd);if(!backend?.selectTestFramework)return"none";let sel=await backend.selectTestFramework(cwd);if(!sel)return"none";return DISPATCH_FRAMEWORK_MAP[sel.name]??"none"}catch{return"none"}}async function buildTestCommandViaDispatch(framework,scope,files,coverage,baseDir,bail,targets,nativeTarget){if(framework==="none")return null;try{let{pickBackend:pickBackend2}=await Promise.resolve().then(() => (init_dispatch(),exports_dispatch)),backend=await pickBackend2(baseDir);if(backend?.buildTestCommand){let cmd=backend.buildTestCommand(framework,files,baseDir,{scope,coverage,bail,targets,nativeTarget});if(cmd)return cmd}return null}catch{return null}}async function parseTestOutputViaDispatch(framework,output,baseDir){if(framework==="none")return null;try{let{pickBackend:pickBackend2}=await Promise.resolve().then(() => (init_dispatch(),exports_dispatch)),backend=await pickBackend2(baseDir);if(!backend?.parseTestOutput)return null;let summary=backend.parseTestOutput(framework,output,"",0),passed=summary.passed??0,failed=summary.failed??0,skipped=summary.skipped??0,total=summary.total??passed+failed+skipped,result={totals:{passed,failed,skipped,total}};if(summary.coveragePercent!==void 0)result.coveragePercent=summary.coveragePercent;return result}catch{return null}}async function detectTestFramework(cwd){let baseDir=cwd;try{let packageJsonPath=path163.join(baseDir,"package.json");if(_internals127.existsSync(packageJsonPath)){let content=_internals127.readFileSync(packageJsonPath,"utf-8"),pkg=JSON.parse(content),_deps=pkg.dependencies||{},devDeps=pkg.devDependencies||{},scripts=pkg.scripts||{};if(scripts.test?.includes("vitest"))return"vitest";if(scripts.test?.includes("jest"))return"jest";if(scripts.test?.includes("mocha"))return"mocha";if(scripts.test?.includes("bun test"))return"bun";if(hasDevDependency(devDeps,"vitest","@vitest/ui"))return"vitest";if(hasDevDependency(devDeps,"jest","@types/jest"))return"jest";if(hasDevDependency(devDeps,"mocha","@types/mocha"))return"mocha";if(_internals127.existsSync(path163.join(baseDir,"bun.lockb"))||_internals127.existsSync(path163.join(baseDir,"bun.lock"))){if(scripts.test?.includes("bun"))return"bun"}}}catch{}try{let pyprojectTomlPath=path163.join(baseDir,"pyproject.toml"),setupCfgPath=path163.join(baseDir,"setup.cfg"),requirementsTxtPath=path163.join(baseDir,"requirements.txt");if(_internals127.existsSync(pyprojectTomlPath)){let content=_internals127.readFileSync(pyprojectTomlPath,"utf-8");if(content.includes("[tool.pytest"))return"pytest";if(content.includes("pytest"))return"pytest"}if(_internals127.existsSync(setupCfgPath)){if(_internals127.readFileSync(setupCfgPath,"utf-8").includes("[pytest]"))return"pytest"}if(_internals127.existsSync(requirementsTxtPath)){if(_internals127.readFileSync(requirementsTxtPath,"utf-8").includes("pytest"))return"pytest"}}catch{}try{let cargoTomlPath=path163.join(baseDir,"Cargo.toml");if(_internals127.existsSync(cargoTomlPath)){let content=_internals127.readFileSync(cargoTomlPath,"utf-8");if(content.includes("[dev-dependencies]")){if(content.includes("tokio")||content.includes("mockall")||content.includes("pretty_assertions"))return"cargo"}}}catch{}try{let pesterConfigPath=path163.join(baseDir,"pester.config.ps1"),pesterConfigJsonPath=path163.join(baseDir,"pester.config.ps1.json"),pesterPs1Path=path163.join(baseDir,"tests.ps1");if(_internals127.existsSync(pesterConfigPath)||_internals127.existsSync(pesterConfigJsonPath)||_internals127.existsSync(pesterPs1Path))return"pester"}catch{}let phpFramework=detectPhpTest(baseDir);if(phpFramework)return phpFramework;if(detectGoTest(baseDir))return"go-test";if(detectJavaMaven(baseDir))return"maven";if(detectGradle(baseDir))return"gradle";if(detectDotnetTest(baseDir))return"dotnet-test";if(detectCTest(baseDir))return"ctest";if(detectSwiftTest(baseDir))return"swift-test";if(detectDartTest(baseDir))return"dart-test";if(detectRSpec(baseDir))return"rspec";if(detectMinitest(baseDir))return"minitest";return"none"}function detectPhpTest(cwd){if(_internals127.existsSync(path163.join(cwd,"artisan"))&&_internals127.existsSync(path163.join(cwd,"composer.json")))return"php-artisan";if(_internals127.existsSync(path163.join(cwd,"Pest.php")))return"pest";if(_internals127.existsSync(path163.join(cwd,"phpunit.xml"))||_internals127.existsSync(path163.join(cwd,"phpunit.xml.dist")))return"phpunit";return null}function isTestDirectoryPath(normalizedPath2){return normalizedPath2.split("/").some((segment)=>TEST_DIRECTORY_NAMES.includes(segment))}function resolveWorkspacePath(file3,workingDir){return path163.isAbsolute(file3)?path163.resolve(file3):path163.resolve(workingDir,file3)}function toWorkspaceOutputPath(absolutePath2,workingDir,preferRelative){if(!preferRelative)return absolutePath2;return path163.relative(workingDir,absolutePath2)}function dedupePush(target,value){if(!target.includes(value))target.push(value)}function buildLanguageSpecificTestNames(nameWithoutExt,ext){switch(ext){case".go":return[`${nameWithoutExt}_test.go`];case".py":return[`test_${nameWithoutExt}.py`,`${nameWithoutExt}_test.py`];case".rb":return[`${nameWithoutExt}_spec.rb`];case".java":return[`${nameWithoutExt}Test.java`,`${nameWithoutExt}Tests.java`,`Test${nameWithoutExt}.java`,`${nameWithoutExt}IT.java`];case".cs":return[`${nameWithoutExt}Test.cs`,`${nameWithoutExt}Tests.cs`];case".kt":return[`${nameWithoutExt}Test.kt`,`${nameWithoutExt}Tests.kt`,`Test${nameWithoutExt}.kt`];case".php":return[`${nameWithoutExt}Test.php`,`${nameWithoutExt}Tests.php`,`Test${nameWithoutExt}.php`];case".ps1":return[`${nameWithoutExt}.Tests.ps1`,`${nameWithoutExt}.tests.ps1`];default:return[]}}function getRepoLevelCandidateDirectories(workingDir,relativePath2,ext){let relativeDir=path163.dirname(relativePath2),nestedRelativeDir=relativeDir==="."?"":relativeDir,directories=TEST_DIRECTORY_NAMES.flatMap((dirName)=>{let rootDir=path163.join(workingDir,dirName);return nestedRelativeDir?[rootDir,path163.join(rootDir,nestedRelativeDir)]:[rootDir]}),normalizedRelativePath=relativePath2.replace(/\\/g,"/");if(ext===".java"&&normalizedRelativePath.startsWith("src/main/java/"))directories.push(path163.join(workingDir,"src/test/java",path163.dirname(normalizedRelativePath.slice(14))));if((ext===".kt"||ext===".java")&&normalizedRelativePath.startsWith("src/main/kotlin/"))directories.push(path163.join(workingDir,"src/test/kotlin",path163.dirname(normalizedRelativePath.slice(16))));return[...new Set(directories)]}function hasCompoundTestExtension(filename){let lower=filename.toLowerCase();return COMPOUND_TEST_EXTENSIONS.some((ext)=>lower.endsWith(ext))}function isLanguageSpecificTestFile(basename27){let lower=basename27.toLowerCase();if(lower.endsWith("_test.go"))return!0;if(lower.endsWith(".py")&&(lower.startsWith("test_")||lower.endsWith("_test.py")))return!0;if(lower.endsWith("_spec.rb"))return!0;if(lower.endsWith(".java")&&(/^Test[A-Z]/.test(basename27)||basename27.endsWith("Test.java")||basename27.endsWith("Tests.java")||lower.endsWith("it.java")))return!0;if(lower.endsWith(".cs")&&(lower.endsWith("test.cs")||lower.endsWith("tests.cs")))return!0;if(lower.endsWith(".kt")&&(/^Test[A-Z]/.test(basename27)||lower.endsWith("test.kt")||lower.endsWith("tests.kt")))return!0;if(lower.endsWith(".php")&&(/^Test[A-Z]/.test(basename27)||basename27.endsWith("Test.php")||basename27.endsWith("Tests.php")))return!0;if(lower.endsWith(".tests.ps1"))return!0;return!1}function isConventionTestFilePath(filePath){let normalizedPath2=filePath.replace(/\\/g,"/"),basename27=path163.basename(filePath);return hasCompoundTestExtension(basename27)||basename27.includes(".spec.")||basename27.includes(".test.")||isLanguageSpecificTestFile(basename27)||isTestDirectoryPath(normalizedPath2)}function getTestFilesFromConvention(sourceFiles,workingDir=process.cwd()){let testFiles=[];for(let file3 of sourceFiles){let absoluteFile=resolveWorkspacePath(file3,workingDir),relativeFile=path163.relative(workingDir,absoluteFile),basename27=path163.basename(absoluteFile),dirname74=path163.dirname(absoluteFile),preferRelativeOutput=!path163.isAbsolute(file3);if(isConventionTestFilePath(relativeFile)||isConventionTestFilePath(file3)){dedupePush(testFiles,toWorkspaceOutputPath(absoluteFile,workingDir,preferRelativeOutput));continue}let nameWithoutExt=basename27.replace(/\.[^.]+$/,""),ext=path163.extname(basename27),genericTestNames=[`${nameWithoutExt}.spec${ext}`,`${nameWithoutExt}.test${ext}`],languageSpecificTestNames=buildLanguageSpecificTestNames(nameWithoutExt,ext),colocatedCandidates=[...genericTestNames,...languageSpecificTestNames].map((candidateName)=>path163.join(dirname74,candidateName)),testDirectoryNames=[basename27,...genericTestNames,...languageSpecificTestNames],repoLevelDirectories=getRepoLevelCandidateDirectories(workingDir,relativeFile,ext),possibleTestFiles=[...colocatedCandidates,...TEST_DIRECTORY_NAMES.flatMap((dirName)=>testDirectoryNames.map((candidateName)=>path163.join(dirname74,dirName,candidateName))),...repoLevelDirectories.flatMap((candidateDir)=>testDirectoryNames.map((candidateName)=>path163.join(candidateDir,candidateName)))];for(let testFile of possibleTestFiles)if(fs85.existsSync(testFile))dedupePush(testFiles,toWorkspaceOutputPath(testFile,workingDir,preferRelativeOutput))}return testFiles}async function getTestFilesFromGraph(sourceFiles,workingDir){let testFiles=[],absoluteSourceFiles=sourceFiles.map((sourceFile)=>resolveWorkspacePath(sourceFile,workingDir)),candidateTestFiles=getTestFilesFromConvention(sourceFiles,workingDir);if(sourceFiles.length===0)return testFiles;for(let testFile of candidateTestFiles)try{let absoluteTestFile=resolveWorkspacePath(testFile,workingDir),content=fs85.readFileSync(absoluteTestFile,"utf-8"),testDir=path163.dirname(absoluteTestFile),importRegex=/import\s+.*?\s+from\s+['"]([^'"]+)['"]/g,match;match=importRegex.exec(content);while(match!==null){let importPath=match[1],resolvedImport;if(importPath.startsWith(".")){if(resolvedImport=path163.resolve(testDir,importPath),!path163.extname(resolvedImport))for(let extToTry of[".ts",".tsx",".js",".jsx",".mjs",".cjs"]){let withExt=resolvedImport+extToTry;if(absoluteSourceFiles.includes(withExt)||fs85.existsSync(withExt)){resolvedImport=withExt;break}}}else continue;let importBasename=path163.basename(resolvedImport,path163.extname(resolvedImport)),importDir=path163.dirname(resolvedImport);for(let sourceFile of absoluteSourceFiles){let sourceDir=path163.dirname(sourceFile),sourceBasename=path163.basename(sourceFile,path163.extname(sourceFile)),isRelatedDir=importDir===sourceDir||importDir===path163.join(sourceDir,"__tests__")||importDir===path163.join(sourceDir,"tests")||importDir===path163.join(sourceDir,"test")||importDir===path163.join(sourceDir,"spec");if(resolvedImport===sourceFile||importBasename===sourceBasename&&isRelatedDir){dedupePush(testFiles,testFile);break}}match=importRegex.exec(content)}let requireRegex=/require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;match=requireRegex.exec(content);while(match!==null){let importPath=match[1];if(importPath.startsWith(".")){let resolvedImport=path163.resolve(testDir,importPath);if(!path163.extname(resolvedImport))for(let extToTry of[".ts",".tsx",".js",".jsx",".mjs",".cjs"]){let withExt=resolvedImport+extToTry;if(absoluteSourceFiles.includes(withExt)||fs85.existsSync(withExt)){resolvedImport=withExt;break}}let importDir=path163.dirname(resolvedImport),importBasename=path163.basename(resolvedImport,path163.extname(resolvedImport));for(let sourceFile of absoluteSourceFiles){let sourceDir=path163.dirname(sourceFile),sourceBasename=path163.basename(sourceFile,path163.extname(sourceFile)),isRelatedDir=importDir===sourceDir||importDir===path163.join(sourceDir,"__tests__")||importDir===path163.join(sourceDir,"tests")||importDir===path163.join(sourceDir,"test")||importDir===path163.join(sourceDir,"spec");if(resolvedImport===sourceFile||importBasename===sourceBasename&&isRelatedDir){dedupePush(testFiles,testFile);break}}}match=requireRegex.exec(content)}}catch{}return testFiles}function getTargetedExecutionUnsupportedReason(framework){switch(framework){case"go-test":return"go test targets packages, not individual test files";case"cargo":return"cargo test targets crates, targets, or test names rather than file paths";case"maven":return"maven test selection is class-based, not file-path based";case"gradle":return"gradle test selection is class-based, not file-path based";case"dotnet-test":return"dotnet test filters by fully qualified names, not file paths";case"ctest":return"ctest filters named tests from the build tree, not source test files";case"swift-test":return"swift test filters test names, not file paths";default:return null}}function buildTestCommand2(framework,scope,files,coverage,baseDir,bail,targets,nativeTarget){if(nativeTarget)return nativeTarget.framework===framework?buildNativeTargetCommand(nativeTarget):null;switch(framework){case"bun":{let args2=["bun","test"];if(coverage)args2.push("--coverage");if(bail)args2.push("--bail");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"vitest":{let args2=["npx","vitest","run","--reporter=json","--outputFile",VITEST_JSON_OUTPUT_RELATIVE_PATH];if(coverage)args2.push("--coverage");if(bail)args2.push("--bail=1");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"jest":{let args2=["npx","jest","--json"];if(coverage)args2.push("--coverage");if(bail)args2.push("--bail");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"mocha":{let args2=["npx","mocha"];if(bail)args2.push("--bail");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"pytest":{let args2=process.platform==="win32"?["python","-m","pytest"]:["python3","-m","pytest"];if(coverage)args2.push("--cov=.","--cov-report=term-missing");if(bail)args2.push("-x");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"cargo":{let args2=["cargo","test"];if(targets&&targets.length>0)args2.push("--",...targets);else if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"pester":{if(scope!=="all"&&files.length>0){let psCommand=`Invoke-Pester -Path @('${files.map((f)=>f.replace(/'/g,"''").replace(/`/g,"``").replace(/\$/g,"`$")).join("','")}')`;return["pwsh","-EncodedCommand",Buffer.from(psCommand,"utf16le").toString("base64")]}return["pwsh","-Command","Invoke-Pester"]}case"go-test":{let args2=["go","test"];if(targets&&targets.length>0)args2.push("-run",targets.join("|"));return args2.push("./..."),args2}case"maven":{let args2=["mvn","test"];if(targets&&targets.length>0)args2.push(`-Dtest=${targets.join(",")}`);return args2}case"gradle":{let isWindows=process.platform==="win32",hasGradlewBat=fs85.existsSync(path163.join(baseDir,"gradlew.bat")),hasGradlew=fs85.existsSync(path163.join(baseDir,"gradlew")),args2=[];if(hasGradlewBat&&isWindows)args2.push("gradlew.bat");else if(hasGradlew)args2.push("./gradlew");else args2.push("gradle");if(args2.push("test"),targets&&targets.length>0)for(let target of targets)args2.push("--tests",target);return args2}case"dotnet-test":{let args2=["dotnet","test"];if(targets&&targets.length>0)args2.push("--filter",targets.join("|"));return args2}case"ctest":{let args2=["ctest","--test-dir",["build","_build","cmake-build-debug","cmake-build-release","out"].find((d)=>fs85.existsSync(path163.join(baseDir,d,"CMakeCache.txt")))??"build"];if(targets&&targets.length>0)args2.push("-R",targets.join("|"));return args2}case"swift-test":{let args2=["swift","test"];if(targets&&targets.length>0)for(let target of targets)args2.push("--filter",target);return args2}case"dart-test":return _internals127.isCommandAvailable("flutter")?["flutter","test",...files]:["dart","test",...files];case"rspec":{let args2=_internals127.isCommandAvailable("bundle")?["bundle","exec","rspec"]:["rspec"];if(bail)args2.push("--fail-fast");if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"minitest":if(scope!=="all"&&files.length>0)return["ruby","-Itest","-e",files.map((f)=>`require_relative '${f.replace(/\\/g,"/").replace(/'/g,"\\'")}'`).join("; ")];return["ruby","-Itest","-e",'Dir.glob("test/**/*_test.rb").sort.each { |f| require_relative f }'];case"pest":{let args2=[phpVendorBin3("pest")];if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"phpunit":{let args2=[phpVendorBin3("phpunit")];if(scope!=="all"&&files.length>0)args2.push(...files);return args2}case"php-artisan":{let args2=["php","artisan","test"];if(scope!=="all"&&files.length>0)args2.push(...files);return args2}default:return null}}function phpVendorBin3(name){return path163.join("vendor","bin",process.platform==="win32"?`${name}.bat`:name)}function mapFrameworkStatusToResult(status){if(typeof status!=="string")return null;let normalized=status.toLowerCase();if(normalized==="pass"||normalized==="passed")return"pass";if(normalized==="fail"||normalized==="failed")return"fail";if(normalized==="skip"||normalized==="skipped"||normalized==="pending"||normalized==="todo")return"skip";return null}function firstLine(value){if(typeof value!=="string")return;let line=value.split(`
|
|
2046
2046
|
`).find((part)=>part.trim().length>0)?.trim();return line&&line.length>0?line:void 0}function parseJestLikeJsonTestResults(payload){if(typeof payload!=="object"||payload===null)return[];let rawSuites=payload.testResults;if(!Array.isArray(rawSuites))return[];let parsed=[];for(let suite of rawSuites){if(typeof suite!=="object"||suite===null)continue;let suiteObj=suite,rawFile=typeof suiteObj.name==="string"?suiteObj.name:typeof suiteObj.testFilePath==="string"?suiteObj.testFilePath:void 0;if(!rawFile)continue;let testFile=rawFile.replace(/\\/g,"/"),assertionResults=suiteObj.assertionResults;if(!Array.isArray(assertionResults))continue;for(let assertion of assertionResults){if(typeof assertion!=="object"||assertion===null)continue;let assertionObj=assertion,result=mapFrameworkStatusToResult(assertionObj.status),testName=typeof assertionObj.fullName==="string"?assertionObj.fullName:typeof assertionObj.title==="string"?assertionObj.title:void 0;if(!result||!testName||testName.length===0)continue;let firstFailure=(Array.isArray(assertionObj.failureMessages)?assertionObj.failureMessages:[]).find((entry)=>typeof entry==="string"&&entry.length>0),durationMs=typeof assertionObj.duration==="number"&&Number.isFinite(assertionObj.duration)?Math.max(assertionObj.duration,0):0;parsed.push({testFile,testName,result,durationMs,errorMessage:firstLine(firstFailure),stackPrefix:firstLine(firstFailure)})}}return parsed}function parseBunJsonLines(output){let parsed=[];for(let line of output.split(`
|
|
2047
2047
|
`)){let trimmed=line.trim();if(!trimmed.startsWith("{")||!trimmed.endsWith("}"))continue;try{let obj=JSON.parse(trimmed),rawFile=typeof obj.file==="string"?obj.file:typeof obj.testFile==="string"?obj.testFile:typeof obj.path==="string"?obj.path:void 0,rawName=typeof obj.testName==="string"?obj.testName:typeof obj.fullName==="string"?obj.fullName:typeof obj.name==="string"?obj.name:void 0,result=mapFrameworkStatusToResult(typeof obj.status==="string"?obj.status:obj.result);if(!rawFile||!rawName||!result)continue;let errorObj=typeof obj.error==="object"&&obj.error!==null?obj.error:void 0,durationMs=typeof obj.durationMs==="number"&&Number.isFinite(obj.durationMs)?Math.max(obj.durationMs,0):typeof obj.duration==="number"&&Number.isFinite(obj.duration)?Math.max(obj.duration,0):0;parsed.push({testFile:rawFile.replace(/\\/g,"/"),testName:rawName,result,durationMs,errorMessage:firstLine(errorObj?.message??obj.errorMessage),stackPrefix:firstLine(errorObj?.stack)})}catch{}}return parsed}function parseFrameworkJsonTestResults(framework,output){let jsonMatch=output.match(/\{[\s\S]*"testResults"[\s\S]*\}/);if(jsonMatch)try{let parsed=JSON.parse(jsonMatch[0]),testResults=parseJestLikeJsonTestResults(parsed);if(testResults.length>0)return testResults}catch{}for(let line of output.split(`
|
|
2048
|
-
`)){let trimmed=line.trim();if(!trimmed.startsWith("{")||!trimmed.endsWith("}"))continue;try{let parsed=JSON.parse(trimmed),testResults=parseJestLikeJsonTestResults(parsed);if(testResults.length>0)return testResults}catch{}}if(framework==="bun")return parseBunJsonLines(output);return[]}function parseTestOutput2(framework,output){let totals={passed:0,failed:0,skipped:0,total:0},coveragePercent;switch(framework){case"vitest":case"jest":case"bun":{let jsonMatch=output.match(/\{[\s\S]*"testResults"[\s\S]*\}/);if(jsonMatch)try{let parsed=JSON.parse(jsonMatch[0]);if(parsed.numTotalTests!==void 0)totals.passed=parsed.numPassedTests||0,totals.failed=parsed.numFailedTests||0,totals.skipped=parsed.numPendingTests||0,totals.total=parsed.numTotalTests||0;if(parsed.coverage!==void 0)coveragePercent=parsed.coverage}catch{}if(totals.total===0){let passMatch=output.match(/(\d+)\s+pass(ing|ed)?/),failMatch=output.match(/(\d+)\s+fail(ing|ed)?/),skipMatch=output.match(/(\d+)\s+skip(ping|ped)?/);if(passMatch)totals.passed=parseInt(passMatch[1],10);if(failMatch)totals.failed=parseInt(failMatch[1],10);if(skipMatch)totals.skipped=parseInt(skipMatch[1],10);totals.total=totals.passed+totals.failed+totals.skipped}let coverageMatch=output.match(/All files[^\d]*(\d+\.?\d*)\s*%/);if(!coveragePercent&&coverageMatch)coveragePercent=parseFloat(coverageMatch[1]);break}case"mocha":{let passMatch=output.match(/(\d+)\s+passing/),failMatch=output.match(/(\d+)\s+failing/),pendingMatch=output.match(/(\d+)\s+pending/);if(passMatch)totals.passed=parseInt(passMatch[1],10);if(failMatch)totals.failed=parseInt(failMatch[1],10);if(pendingMatch)totals.skipped=parseInt(pendingMatch[1],10);totals.total=totals.passed+totals.failed+totals.skipped;break}case"pytest":{let passMatch=output.match(/(\d+)\s+passed/),failMatch=output.match(/(\d+)\s+failed/),skipMatch=output.match(/(\d+)\s+skipped/);if(passMatch)totals.passed=parseInt(passMatch[1],10);if(failMatch)totals.failed=parseInt(failMatch[1],10);if(skipMatch)totals.skipped=parseInt(skipMatch[1],10);totals.total=totals.passed+totals.failed+totals.skipped;let coverageMatch=output.match(/TOTAL\s+(\d+\.?\d*)\s*%/);if(coverageMatch)coveragePercent=parseFloat(coverageMatch[1]);break}case"cargo":{let passMatch=output.match(/test result: ok\. (\d+) passed/),failMatch=output.match(/test result: FAILED\. (\d+) passed; (\d+) failed/);if(failMatch)totals.passed=parseInt(failMatch[1],10),totals.failed=parseInt(failMatch[2],10);else if(passMatch)totals.passed=parseInt(passMatch[1],10);totals.total=totals.passed+totals.failed;break}case"pester":{let passMatch=output.match(/Passed:\s*(\d+)/),failMatch=output.match(/Failed:\s*(\d+)/),skipMatch=output.match(/Skipped:\s*(\d+)/);if(passMatch)totals.passed=parseInt(passMatch[1],10);if(failMatch)totals.failed=parseInt(failMatch[1],10);if(skipMatch)totals.skipped=parseInt(skipMatch[1],10);totals.total=totals.passed+totals.failed+totals.skipped;break}case"go-test":{let passMatches=[...output.matchAll(/--- PASS:/g)],failMatches=[...output.matchAll(/--- FAIL:/g)],skipMatches=[...output.matchAll(/--- SKIP:/g)];totals.passed=passMatches.length,totals.failed=failMatches.length,totals.skipped=skipMatches.length,totals.total=totals.passed+totals.failed+totals.skipped;let covMatch=output.match(/coverage:\s*(\d+\.?\d*)\s*%/);if(covMatch)coveragePercent=parseFloat(covMatch[1]);break}case"maven":{let mavenMatch=output.match(/Tests run:\s*(\d+),\s*Failures:\s*(\d+),\s*Errors:\s*(\d+),\s*Skipped:\s*(\d+)/);if(mavenMatch){let total=parseInt(mavenMatch[1],10),failures=parseInt(mavenMatch[2],10),errors5=parseInt(mavenMatch[3],10),skipped=parseInt(mavenMatch[4],10);totals.failed=failures+errors5,totals.skipped=skipped,totals.passed=total-totals.failed-skipped,totals.total=total}break}case"gradle":{let gradleMatch=output.match(/(\d+) tests? completed(?:,\s*(\d+) failed)?(?:,\s*(\d+) skipped)?/);if(gradleMatch)totals.total=parseInt(gradleMatch[1],10),totals.failed=gradleMatch[2]?parseInt(gradleMatch[2],10):0,totals.skipped=gradleMatch[3]?parseInt(gradleMatch[3],10):0,totals.passed=totals.total-totals.failed-totals.skipped;break}case"dotnet-test":{let passMatch=output.match(/Passed[!:]?\s*(\d+)/i),failMatch=output.match(/Failed[!:]?\s*(\d+)/i),skipMatch=output.match(/Skipped[!:]?\s*(\d+)/i);if(passMatch)totals.passed=parseInt(passMatch[1],10);if(failMatch)totals.failed=parseInt(failMatch[1],10);if(skipMatch)totals.skipped=parseInt(skipMatch[1],10);totals.total=totals.passed+totals.failed+totals.skipped;break}case"ctest":{let disabledCount=[...output.matchAll(/\*{3}Not Run\s+\(Disabled\)/gi)].length;totals.skipped=disabledCount;let ctestMatch=output.match(/(\d+) tests? failed out of (\d+)/);if(ctestMatch){totals.failed=parseInt(ctestMatch[1],10);let executedTotal=parseInt(ctestMatch[2],10);totals.total=executedTotal+disabledCount,totals.passed=executedTotal-totals.failed}else{let allPassMatch=output.match(/100% tests passed.*?(\d+) tests?/);if(allPassMatch){let executedTotal=parseInt(allPassMatch[1],10);totals.total=executedTotal+disabledCount,totals.passed=executedTotal}else if(disabledCount>0)totals.total=disabledCount}break}case"swift-test":{let swiftMatch=output.match(/Executed (\d+) tests?,\s*with (\d+) failures?/);if(swiftMatch)totals.total=parseInt(swiftMatch[1],10),totals.failed=parseInt(swiftMatch[2],10),totals.passed=totals.total-totals.failed;break}case"dart-test":{let dartPassMatch=output.match(/\+(\d+):\s*All tests passed/),dartMixMatch=output.match(/\+(\d+)\s+-(\d+):/);if(dartPassMatch)totals.passed=parseInt(dartPassMatch[1],10),totals.total=totals.passed;else if(dartMixMatch)totals.passed=parseInt(dartMixMatch[1],10),totals.failed=parseInt(dartMixMatch[2],10),totals.total=totals.passed+totals.failed;break}case"rspec":{let rspecMatch=output.match(/(\d+) examples?,\s*(\d+) failures?(?:,\s*(\d+) pending)?/);if(rspecMatch)totals.total=parseInt(rspecMatch[1],10),totals.failed=parseInt(rspecMatch[2],10),totals.skipped=rspecMatch[3]?parseInt(rspecMatch[3],10):0,totals.passed=totals.total-totals.failed-totals.skipped;break}case"minitest":{let minitestMatch=output.match(/(\d+) runs?,\s*\d+ assertions?,\s*(\d+) failures?,\s*(\d+) errors?,\s*(\d+) skips?/);if(minitestMatch)totals.total=parseInt(minitestMatch[1],10),totals.failed=parseInt(minitestMatch[2],10)+parseInt(minitestMatch[3],10),totals.skipped=parseInt(minitestMatch[4],10),totals.passed=totals.total-totals.failed-totals.skipped;break}case"pest":case"phpunit":case"php-artisan":{let phpunitMatch=output.match(/Tests:\s*(\d+),\s*Assertions:\s*\d+(?:,\s*Failures:\s*(\d+))?(?:,\s*Errors:\s*(\d+))?(?:,\s*Skipped:\s*(\d+))?/),okMatch=output.match(/OK\s*\((\d+)\s+tests?/);if(phpunitMatch){totals.total=parseInt(phpunitMatch[1],10);let failures=phpunitMatch[2]?parseInt(phpunitMatch[2],10):0,errors5=phpunitMatch[3]?parseInt(phpunitMatch[3],10):0;totals.skipped=phpunitMatch[4]?parseInt(phpunitMatch[4],10):0,totals.failed=failures+errors5,totals.passed=totals.total-totals.failed-totals.skipped}else if(okMatch)totals.total=parseInt(okMatch[1],10),totals.passed=totals.total;break}default:break}return{totals,coveragePercent}}async function readBoundedStream2(stream,maxBytes){let reader=stream.getReader(),chunks=[],totalBytes=0,truncated=!1;try{while(!0){let{done,value}=await reader.read();if(done)break;if(totalBytes+value.length>maxBytes){let remaining=maxBytes-totalBytes;if(remaining>0)chunks.push(value.slice(0,remaining));totalBytes=maxBytes,truncated=!0,reader.cancel().catch(()=>{});break}chunks.push(value),totalBytes+=value.length}}catch{}finally{try{reader.releaseLock()}catch{}}let decoder=new TextDecoder("utf-8",{fatal:!1}),combined=new Uint8Array(totalBytes),offset=0;for(let chunk of chunks)combined.set(chunk,offset),offset+=chunk.length;return{text:decoder.decode(combined),truncated}}function formatPassingMessage(framework,totals,coveragePercent){let message=totals.total>0&&totals.passed===0&&totals.failed===0&&totals.skipped===totals.total?`${framework} tests completed with ${totals.skipped} skipped (${totals.total} total)`:`${framework} tests passed (${totals.passed}/${totals.total})`;if(coveragePercent!==void 0)message+=` with ${coveragePercent}% coverage`;return message}function formatNativeHistoryTestFile(target,historyPath){return`native:${target.framework}:path=${encodeURIComponent(historyPath)}#name=${encodeURIComponent(target.name)}`}async function runTests(framework,scope,files,coverage,timeout_ms,cwd,bail,nativeTarget){let executionCwd=cwd,resolvedNativeTarget=nativeTarget;if(scope==="target"&&!nativeTarget||scope!=="target"&&nativeTarget!==void 0||nativeTarget!==void 0&&nativeTarget.framework!==framework)return{success:!1,framework,scope,error:"Invalid native target pairing; refusing broad test fallback",message:'scope "target" requires one matching native target, and native targets are not valid with other scopes.',outcome:"error"};if(scope==="target"){if(files.length>0||coverage||bail)return{success:!1,framework,scope,error:'scope "target" cannot be combined with files, coverage, or bail',message:"Native target mode runs one exact framework-native name only. Omit files and leave coverage and bail disabled.",outcome:"error"};let nativeTargetError=validateNativeTargetInput(nativeTarget);if(nativeTargetError)return{success:!1,framework,scope,error:nativeTargetError,outcome:"error"};let resolvedTarget=resolveNativeTarget(nativeTarget,cwd);if(!resolvedTarget.success)return{success:!1,framework,scope,error:resolvedTarget.error,outcome:"error"};resolvedNativeTarget=resolvedTarget.target,executionCwd=resolvedTarget.executionDirectory}if(scope!=="all"&&scope!=="target"&&files.length>0){let unsupportedReason=getTargetedExecutionUnsupportedReason(framework);if(unsupportedReason)return{success:!1,framework,scope,error:`Framework "${framework}" does not support targeted test-file execution`,message:`The resolved test selection cannot be run safely because ${unsupportedReason}. Use a framework-native selector manually or let the architect handle the broader sweep.`,outcome:"error"}}let command=process.env.SWARM_LANG_BACKEND!=="legacy"?await buildTestCommandViaDispatch(framework,scope,files,coverage,executionCwd,bail,resolvedNativeTarget)??buildTestCommand2(framework,scope,files,coverage,executionCwd,bail,resolvedNativeTarget):buildTestCommand2(framework,scope,files,coverage,executionCwd,bail,resolvedNativeTarget);if(!command)return{success:!1,framework,scope,error:`No test command available for framework: ${framework}`,message:"Install a supported test framework to run tests",outcome:"error"};if(command.join(" ").length>MAX_COMMAND_LENGTH2)return{success:!1,framework,scope,command,error:"Command exceeds maximum allowed length",outcome:"error"};let startTime=Date.now(),vitestJsonOutputPath=framework==="vitest"?path163.join(executionCwd,".swarm","cache","test-runner-vitest.json"):void 0,proc,timeoutHandle,timedOutByDeadline=!1;try{if(vitestJsonOutputPath)try{if(fs85.mkdirSync(path163.dirname(vitestJsonOutputPath),{recursive:!0}),fs85.existsSync(vitestJsonOutputPath))fs85.unlinkSync(vitestJsonOutputPath)}catch{}let timeoutPromise=new Promise((resolve65)=>{timeoutHandle=setTimeout(()=>{resolve65({kind:"timeout"})},timeout_ms)});proc=_internals127.bunSpawn(command,{stdin:"ignore",stdout:"pipe",stderr:"pipe",cwd:executionCwd,timeout:timeout_ms,killProcessTree:!0});let stdoutPromise=readBoundedStream2(proc.stdout,MAX_OUTPUT_BYTES4),stderrPromise=readBoundedStream2(proc.stderr,MAX_OUTPUT_BYTES4),raceResult=await Promise.race([proc.exited.then((exitCode2)=>({kind:"exit",exitCode:exitCode2})),timeoutPromise]);if(timedOutByDeadline=raceResult.kind==="timeout",timeoutHandle!==void 0)clearTimeout(timeoutHandle),timeoutHandle=void 0;let[stdoutResult,stderrResult]=await Promise.all([stdoutPromise,stderrPromise]),exitCode=raceResult.kind==="timeout"?-1:raceResult.exitCode,duration_ms=Date.now()-startTime,output=stdoutResult.text;if(stderrResult.text)output+=(output?`
|
|
2048
|
+
`)){let trimmed=line.trim();if(!trimmed.startsWith("{")||!trimmed.endsWith("}"))continue;try{let parsed=JSON.parse(trimmed),testResults=parseJestLikeJsonTestResults(parsed);if(testResults.length>0)return testResults}catch{}}if(framework==="bun")return parseBunJsonLines(output);return[]}function parseTestOutput2(framework,output){let totals={passed:0,failed:0,skipped:0,total:0},coveragePercent;switch(framework){case"vitest":case"jest":case"bun":{let jsonMatch=output.match(/\{[\s\S]*"testResults"[\s\S]*\}/);if(jsonMatch)try{let parsed=JSON.parse(jsonMatch[0]);if(parsed.numTotalTests!==void 0)totals.passed=parsed.numPassedTests||0,totals.failed=parsed.numFailedTests||0,totals.skipped=parsed.numPendingTests||0,totals.total=parsed.numTotalTests||0;if(parsed.coverage!==void 0)coveragePercent=parsed.coverage}catch{}if(totals.total===0){let passMatch=output.match(/(\d+)\s+pass(ing|ed)?/),failMatch=output.match(/(\d+)\s+fail(ing|ed)?/),skipMatch=output.match(/(\d+)\s+skip(ping|ped)?/);if(passMatch)totals.passed=parseInt(passMatch[1],10);if(failMatch)totals.failed=parseInt(failMatch[1],10);if(skipMatch)totals.skipped=parseInt(skipMatch[1],10);totals.total=totals.passed+totals.failed+totals.skipped}let coverageMatch=output.match(/All files[^\d]*(\d+\.?\d*)\s*%/);if(!coveragePercent&&coverageMatch)coveragePercent=parseFloat(coverageMatch[1]);break}case"mocha":{let passMatch=output.match(/(\d+)\s+passing/),failMatch=output.match(/(\d+)\s+failing/),pendingMatch=output.match(/(\d+)\s+pending/);if(passMatch)totals.passed=parseInt(passMatch[1],10);if(failMatch)totals.failed=parseInt(failMatch[1],10);if(pendingMatch)totals.skipped=parseInt(pendingMatch[1],10);totals.total=totals.passed+totals.failed+totals.skipped;break}case"pytest":{let passMatch=output.match(/(\d+)\s+passed/),failMatch=output.match(/(\d+)\s+failed/),skipMatch=output.match(/(\d+)\s+skipped/);if(passMatch)totals.passed=parseInt(passMatch[1],10);if(failMatch)totals.failed=parseInt(failMatch[1],10);if(skipMatch)totals.skipped=parseInt(skipMatch[1],10);totals.total=totals.passed+totals.failed+totals.skipped;let coverageMatch=output.match(/TOTAL\s+(\d+\.?\d*)\s*%/);if(coverageMatch)coveragePercent=parseFloat(coverageMatch[1]);break}case"cargo":{let passMatch=output.match(/test result: ok\. (\d+) passed/),failMatch=output.match(/test result: FAILED\. (\d+) passed; (\d+) failed/);if(failMatch)totals.passed=parseInt(failMatch[1],10),totals.failed=parseInt(failMatch[2],10);else if(passMatch)totals.passed=parseInt(passMatch[1],10);totals.total=totals.passed+totals.failed;break}case"pester":{let passMatch=output.match(/Passed:\s*(\d+)/),failMatch=output.match(/Failed:\s*(\d+)/),skipMatch=output.match(/Skipped:\s*(\d+)/);if(passMatch)totals.passed=parseInt(passMatch[1],10);if(failMatch)totals.failed=parseInt(failMatch[1],10);if(skipMatch)totals.skipped=parseInt(skipMatch[1],10);totals.total=totals.passed+totals.failed+totals.skipped;break}case"go-test":{let passMatches=[...output.matchAll(/--- PASS:/g)],failMatches=[...output.matchAll(/--- FAIL:/g)],skipMatches=[...output.matchAll(/--- SKIP:/g)];totals.passed=passMatches.length,totals.failed=failMatches.length,totals.skipped=skipMatches.length,totals.total=totals.passed+totals.failed+totals.skipped;let covMatch=output.match(/coverage:\s*(\d+\.?\d*)\s*%/);if(covMatch)coveragePercent=parseFloat(covMatch[1]);break}case"maven":{let mavenMatch=output.match(/Tests run:\s*(\d+),\s*Failures:\s*(\d+),\s*Errors:\s*(\d+),\s*Skipped:\s*(\d+)/);if(mavenMatch){let total=parseInt(mavenMatch[1],10),failures=parseInt(mavenMatch[2],10),errors5=parseInt(mavenMatch[3],10),skipped=parseInt(mavenMatch[4],10);totals.failed=failures+errors5,totals.skipped=skipped,totals.passed=total-totals.failed-skipped,totals.total=total}break}case"gradle":{let gradleMatch=output.match(/(\d+) tests? completed(?:,\s*(\d+) failed)?(?:,\s*(\d+) skipped)?/);if(gradleMatch)totals.total=parseInt(gradleMatch[1],10),totals.failed=gradleMatch[2]?parseInt(gradleMatch[2],10):0,totals.skipped=gradleMatch[3]?parseInt(gradleMatch[3],10):0,totals.passed=totals.total-totals.failed-totals.skipped;break}case"dotnet-test":{let passMatch=output.match(/Passed[!:]?\s*(\d+)/i),failMatch=output.match(/Failed[!:]?\s*(\d+)/i),skipMatch=output.match(/Skipped[!:]?\s*(\d+)/i);if(passMatch)totals.passed=parseInt(passMatch[1],10);if(failMatch)totals.failed=parseInt(failMatch[1],10);if(skipMatch)totals.skipped=parseInt(skipMatch[1],10);totals.total=totals.passed+totals.failed+totals.skipped;break}case"ctest":{let disabledCount=[...output.matchAll(/\*{3}Not Run\s+\(Disabled\)/gi)].length;totals.skipped=disabledCount;let ctestMatch=output.match(/(\d+) tests? failed out of (\d+)/);if(ctestMatch){totals.failed=parseInt(ctestMatch[1],10);let executedTotal=parseInt(ctestMatch[2],10);totals.total=executedTotal+disabledCount,totals.passed=executedTotal-totals.failed}else{let allPassMatch=output.match(/100% tests passed.*?(\d+) tests?/);if(allPassMatch){let executedTotal=parseInt(allPassMatch[1],10);totals.total=executedTotal+disabledCount,totals.passed=executedTotal}else if(disabledCount>0)totals.total=disabledCount}break}case"swift-test":{let swiftMatch=output.match(/Executed (\d+) tests?,\s*with (\d+) failures?/);if(swiftMatch)totals.total=parseInt(swiftMatch[1],10),totals.failed=parseInt(swiftMatch[2],10),totals.passed=totals.total-totals.failed;break}case"dart-test":{let dartPassMatch=output.match(/\+(\d+):\s*All tests passed/),dartMixMatch=output.match(/\+(\d+)\s+-(\d+):/);if(dartPassMatch)totals.passed=parseInt(dartPassMatch[1],10),totals.total=totals.passed;else if(dartMixMatch)totals.passed=parseInt(dartMixMatch[1],10),totals.failed=parseInt(dartMixMatch[2],10),totals.total=totals.passed+totals.failed;break}case"rspec":{let rspecMatch=output.match(/(\d+) examples?,\s*(\d+) failures?(?:,\s*(\d+) pending)?/);if(rspecMatch)totals.total=parseInt(rspecMatch[1],10),totals.failed=parseInt(rspecMatch[2],10),totals.skipped=rspecMatch[3]?parseInt(rspecMatch[3],10):0,totals.passed=totals.total-totals.failed-totals.skipped;break}case"minitest":{let minitestMatch=output.match(/(\d+) runs?,\s*\d+ assertions?,\s*(\d+) failures?,\s*(\d+) errors?,\s*(\d+) skips?/);if(minitestMatch)totals.total=parseInt(minitestMatch[1],10),totals.failed=parseInt(minitestMatch[2],10)+parseInt(minitestMatch[3],10),totals.skipped=parseInt(minitestMatch[4],10),totals.passed=totals.total-totals.failed-totals.skipped;break}case"pest":case"phpunit":case"php-artisan":{let phpunitMatch=output.match(/Tests:\s*(\d+),\s*Assertions:\s*\d+(?:,\s*Failures:\s*(\d+))?(?:,\s*Errors:\s*(\d+))?(?:,\s*Skipped:\s*(\d+))?/),okMatch=output.match(/OK\s*\((\d+)\s+tests?/);if(phpunitMatch){totals.total=parseInt(phpunitMatch[1],10);let failures=phpunitMatch[2]?parseInt(phpunitMatch[2],10):0,errors5=phpunitMatch[3]?parseInt(phpunitMatch[3],10):0;totals.skipped=phpunitMatch[4]?parseInt(phpunitMatch[4],10):0,totals.failed=failures+errors5,totals.passed=totals.total-totals.failed-totals.skipped}else if(okMatch)totals.total=parseInt(okMatch[1],10),totals.passed=totals.total;break}default:break}return{totals,coveragePercent}}async function readBoundedStream2(stream,maxBytes){let reader=stream.getReader(),chunks=[],totalBytes=0,truncated=!1;try{while(!0){let{done,value}=await reader.read();if(done)break;if(totalBytes+value.length>maxBytes){let remaining=maxBytes-totalBytes;if(remaining>0)chunks.push(value.slice(0,remaining));totalBytes=maxBytes,truncated=!0,reader.cancel().catch(()=>{});break}chunks.push(value),totalBytes+=value.length}}catch{}finally{try{reader.releaseLock()}catch{}}let decoder=new TextDecoder("utf-8",{fatal:!1}),combined=new Uint8Array(totalBytes),offset=0;for(let chunk of chunks)combined.set(chunk,offset),offset+=chunk.length;return{text:decoder.decode(combined),truncated}}function formatPassingMessage(framework,totals,coveragePercent){let message=totals.total>0&&totals.passed===0&&totals.failed===0&&totals.skipped===totals.total?`${framework} tests completed with ${totals.skipped} skipped (${totals.total} total)`:`${framework} tests passed (${totals.passed}/${totals.total})`;if(coveragePercent!==void 0)message+=` with ${coveragePercent}% coverage`;return message}function formatNativeHistoryTestFile(target,historyPath){return`native:${target.framework}:path=${encodeURIComponent(historyPath)}#name=${encodeURIComponent(target.name)}`}async function runTests(framework,scope,files,coverage,timeout_ms,cwd,bail,targets,nativeTarget){let executionCwd=cwd,resolvedNativeTarget=nativeTarget;if(scope==="target"&&!nativeTarget||scope!=="target"&&nativeTarget!==void 0||nativeTarget!==void 0&&nativeTarget.framework!==framework)return{success:!1,framework,scope,error:"Invalid native target pairing; refusing broad test fallback",message:'scope "target" requires one matching native target, and native targets are not valid with other scopes.',outcome:"error"};if(scope==="target"){if(files.length>0||coverage||bail)return{success:!1,framework,scope,error:'scope "target" cannot be combined with files, coverage, or bail',message:"Native target mode runs one exact framework-native name only. Omit files and leave coverage and bail disabled.",outcome:"error"};let nativeTargetError=validateNativeTargetInput(nativeTarget);if(nativeTargetError)return{success:!1,framework,scope,error:nativeTargetError,outcome:"error"};let resolvedTarget=resolveNativeTarget(nativeTarget,cwd);if(!resolvedTarget.success)return{success:!1,framework,scope,error:resolvedTarget.error,outcome:"error"};resolvedNativeTarget=resolvedTarget.target,executionCwd=resolvedTarget.executionDirectory}if(scope!=="all"&&scope!=="target"&&files.length>0&&!(targets&&targets.length>0)){let unsupportedReason=getTargetedExecutionUnsupportedReason(framework);if(unsupportedReason)return{success:!1,framework,scope,error:`Framework "${framework}" does not support targeted test-file execution`,message:`The resolved test selection cannot be run safely because ${unsupportedReason}. Use a framework-native selector manually or let the architect handle the broader sweep.`,outcome:"error"}}let command=process.env.SWARM_LANG_BACKEND!=="legacy"?await buildTestCommandViaDispatch(framework,scope,files,coverage,executionCwd,bail,targets,resolvedNativeTarget)??buildTestCommand2(framework,scope,files,coverage,executionCwd,bail,targets,resolvedNativeTarget):buildTestCommand2(framework,scope,files,coverage,executionCwd,bail,targets,resolvedNativeTarget);if(!command)return{success:!1,framework,scope,error:`No test command available for framework: ${framework}`,message:"Install a supported test framework to run tests",outcome:"error"};if(command.join(" ").length>MAX_COMMAND_LENGTH2)return{success:!1,framework,scope,command,error:"Command exceeds maximum allowed length",outcome:"error"};let startTime=Date.now(),vitestJsonOutputPath=framework==="vitest"?path163.join(executionCwd,".swarm","cache","test-runner-vitest.json"):void 0,proc,timeoutHandle,timedOutByDeadline=!1;try{if(vitestJsonOutputPath)try{if(fs85.mkdirSync(path163.dirname(vitestJsonOutputPath),{recursive:!0}),fs85.existsSync(vitestJsonOutputPath))fs85.unlinkSync(vitestJsonOutputPath)}catch{}let timeoutPromise=new Promise((resolve65)=>{timeoutHandle=setTimeout(()=>{resolve65({kind:"timeout"})},timeout_ms)});proc=_internals127.bunSpawn(command,{stdin:"ignore",stdout:"pipe",stderr:"pipe",cwd:executionCwd,timeout:timeout_ms,killProcessTree:!0});let stdoutPromise=readBoundedStream2(proc.stdout,MAX_OUTPUT_BYTES4),stderrPromise=readBoundedStream2(proc.stderr,MAX_OUTPUT_BYTES4),raceResult=await Promise.race([proc.exited.then((exitCode2)=>({kind:"exit",exitCode:exitCode2})),timeoutPromise]);if(timedOutByDeadline=raceResult.kind==="timeout",timeoutHandle!==void 0)clearTimeout(timeoutHandle),timeoutHandle=void 0;let[stdoutResult,stderrResult]=await Promise.all([stdoutPromise,stderrPromise]),exitCode=raceResult.kind==="timeout"?-1:raceResult.exitCode,duration_ms=Date.now()-startTime,output=stdoutResult.text;if(stderrResult.text)output+=(output?`
|
|
2049
2049
|
`:"")+stderrResult.text;if(vitestJsonOutputPath)try{if(fs85.existsSync(vitestJsonOutputPath)){let vitestJsonOutput=fs85.readFileSync(vitestJsonOutputPath,"utf-8");if(vitestJsonOutput.trim().length>0)output+=(output?`
|
|
2050
2050
|
`:"")+vitestJsonOutput}}catch{}if(stdoutResult.truncated||stderrResult.truncated)output+=`
|
|
2051
|
-
... (output truncated at stream read limit)`;let parsed=process.env.SWARM_LANG_BACKEND!=="legacy"?await parseTestOutputViaDispatch(framework,output,executionCwd)??parseTestOutput2(framework,output):parseTestOutput2(framework,output),parsedTestCases=parseFrameworkJsonTestResults(framework,output),totals={...parsed.totals},{coveragePercent}=parsed;if(totals.total===0&&parsedTestCases.length>0){for(let entry of parsedTestCases)if(entry.result==="pass")totals.passed++;else if(entry.result==="fail")totals.failed++;else totals.skipped++;totals.total=parsedTestCases.length}let isTimeout=timedOutByDeadline,nativeTargetObserved=resolvedNativeTarget?didExecuteNativeTarget(resolvedNativeTarget,output):!0;if(exitCode===0&&!isTimeout&&totals.failed===0&&nativeTargetObserved){let result={success:!0,framework,scope,command,timeout_ms,duration_ms,totals,rawOutput:output,outcome:"pass",testCases:parsedTestCases};if(coveragePercent!==void 0)result.coveragePercent=coveragePercent;return result.message=formatPassingMessage(framework,totals,coveragePercent),result}else{let result={success:!1,framework,scope,command,timeout_ms,duration_ms,totals,rawOutput:output,error:isTimeout?`Tests timed out after ${timeout_ms}ms`:!nativeTargetObserved?`Native target "${resolvedNativeTarget?.name}" did not execute`:`Tests failed with ${totals.failed} failures`,message:isTimeout?`${framework} tests timed out after ${timeout_ms}ms`:!nativeTargetObserved?`${framework} did not report the exact requested native target; refusing a false-green 0/0 result`:`${framework} tests failed (${totals.failed}/${totals.total} failed)`,outcome:isTimeout?"error":"regression",testCases:parsedTestCases};if(coveragePercent!==void 0)result.coveragePercent=coveragePercent;return result}}catch(error93){let duration_ms=Date.now()-startTime;return{success:!1,framework,scope,command,timeout_ms,duration_ms,error:error93 instanceof Error?`Execution failed: ${error93.message}`:"Execution failed: unknown error",outcome:"error"}}finally{if(timeoutHandle!==void 0)clearTimeout(timeoutHandle);if(proc?.exitCode===null&&!timedOutByDeadline)try{if(proc.killTree)await proc.killTree("SIGKILL");else proc.kill("SIGKILL")}catch{}}}function escapeRegexForMatch(value){return value.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function didExecuteNativeTarget(target,output){if(target.framework==="go-test")return[...output.matchAll(/^\s*--- (?:PASS|FAIL|SKIP):\s+(.+?)(?:\s+\(|$)/gm)].some((match)=>match[1]===target.name);let exactName=escapeRegexForMatch(target.name);return new RegExp(`(?:Start\\s+\\d+:\\s*|Test\\s+#\\d+:\\s*)${exactName}(?=\\s|$)`,"m").test(output)}function normalizeHistoryTestFile(testFile,workingDir){let normalized=testFile.replace(/\\/g,"/");if(!path163.isAbsolute(testFile))return normalized;let relative35=path163.relative(workingDir,testFile);if(relative35.startsWith("..")||path163.isAbsolute(relative35))return normalized;return relative35.replace(/\\/g,"/")}function combineAggregateResult(current,next){if(current==="fail"||next==="fail")return"fail";if(current==="pass"||next==="pass")return"pass";return"skip"}function recordAndAnalyzeResults(result,testFiles,workingDir,sourceFiles,parsedTestCases){if(!result.totals||result.totals.total===0)return;let now2=new Date().toISOString(),changedFiles=(sourceFiles!==void 0?sourceFiles:testFiles).map((f)=>f.replace(/\\/g,"/")),aggregateResultsByFile=new Map,validParsedCases=parsedTestCases?.filter((parsedCase)=>parsedCase.testFile.length>0&&parsedCase.testName.length>0)??[],allRecords=[];for(let parsedCase of validParsedCases){let normalizedTestFile=normalizeHistoryTestFile(parsedCase.testFile,workingDir);allRecords.push({timestamp:now2,taskId:"auto",testFile:normalizedTestFile,testName:parsedCase.testName,result:parsedCase.result,durationMs:parsedCase.durationMs,errorMessage:parsedCase.errorMessage,stackPrefix:parsedCase.stackPrefix,changedFiles}),aggregateResultsByFile.set(normalizedTestFile,combineAggregateResult(aggregateResultsByFile.get(normalizedTestFile),parsedCase.result))}if(aggregateResultsByFile.size===0){let aggregateResult=result.success?"pass":"fail";for(let testFile of testFiles)aggregateResultsByFile.set(testFile.replace(/\\/g,"/"),aggregateResult)}for(let[testFile,aggregateResult]of aggregateResultsByFile)allRecords.push({timestamp:now2,taskId:"auto",testFile,testName:AGGREGATE_TEST_NAME,result:aggregateResult,durationMs:result.duration_ms||0,changedFiles});try{batchAppendTestRuns(allRecords,workingDir)}catch{}}function selectHistoryForAnalysis(history){let filesWithIndividualRecords=new Set;for(let record3 of history)if(record3.testName!==AGGREGATE_TEST_NAME)filesWithIndividualRecords.add(record3.testFile.toLowerCase());if(filesWithIndividualRecords.size===0)return history;return history.filter((record3)=>record3.testName!==AGGREGATE_TEST_NAME||!filesWithIndividualRecords.has(record3.testFile.toLowerCase()))}function analyzeFailures(workingDir){let report={flakyTests:[],failureClusters:[],quarantinedFailures:[]};try{let history=selectHistoryForAnalysis(getAllHistory(workingDir));if(history.length===0)return report;report.flakyTests=detectFlakyTests(history);let failingResults=history.filter((r)=>r.result==="fail");if(failingResults.length>0){let{clusters}=classifyAndCluster(failingResults,history);report.failureClusters=clusters.map((c)=>({rootCause:c.rootCause,affectedFiles:c.affectedTestFiles,classification:c.classification}))}for(let entry of report.flakyTests)if(entry.isQuarantined)report.quarantinedFailures.push(`${entry.testFile}: ${entry.testName}`)}catch{}return report}var MAX_OUTPUT_BYTES4=512000,MAX_COMMAND_LENGTH2=500,DEFAULT_TIMEOUT_MS3=60000,MAX_TIMEOUT_MS3=300000,MAX_SAFE_TEST_FILES=50,MAX_SAFE_SOURCE_FILES=1,AGGREGATE_TEST_NAME="(aggregate)",VITEST_JSON_OUTPUT_RELATIVE_PATH=".swarm/cache/test-runner-vitest.json",POWERSHELL_METACHARACTERS,DISPATCH_FRAMEWORK_MAP,COMPOUND_TEST_EXTENSIONS,TEST_DIRECTORY_NAMES,SOURCE_EXTENSIONS,test_runner,_internals127;var init_test_runner=__esm(()=>{init_zod();init_discovery();init_default_backend();init_analyzer();init_failure_classifier();init_history_store();init_bun_compat();init_path_security();init_create_tool();init_resolve_working_directory();POWERSHELL_METACHARACTERS=/[|;&`$(){}[\]<>"'#*?\x00-\x1f]/;DISPATCH_FRAMEWORK_MAP={bun:"bun",vitest:"vitest",jest:"jest",mocha:"mocha",pytest:"pytest",cargo:"cargo",pester:"pester","go-test":"go-test",maven:"maven",gradle:"gradle","dotnet-test":"dotnet-test",ctest:"ctest","swift-test":"swift-test","dart-test":"dart-test",rspec:"rspec",minitest:"minitest",pest:"pest",phpunit:"phpunit","php-artisan":"php-artisan","bun:test":"bun","xcodebuild-test":"swift-test","flutter test":"dart-test","dart test":"dart-test",Pest:"pest",PHPUnit:"phpunit"};COMPOUND_TEST_EXTENSIONS=[".test.ts",".test.tsx",".test.js",".test.jsx",".tests.ps1",".spec.ts",".spec.tsx",".spec.js",".spec.jsx",".test.ps1",".spec.ps1"],TEST_DIRECTORY_NAMES=["__tests__","tests","test","spec"];SOURCE_EXTENSIONS=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".py",".rs",".ps1",".psm1",".go",".java",".kt",".kts",".cs",".c",".h",".cpp",".hpp",".cc",".cxx",".php",".swift",".dart",".rb",".pyi"]);test_runner=createSwarmTool({description:'Run project tests with automatic framework detection for bun, vitest, jest, mocha, pytest, cargo, pester, go test, maven, gradle, dotnet test, ctest, swift test, dart test, rspec, minitest, pest, phpunit, or php-artisan. Returns JSON with success, framework, scope, command, timeout_ms, duration_ms, totals, outcome, and optional coveragePercent, rawOutput, testCases, and message fields. Scope "target" runs one exact Go test/subtest or CTest name via native_target using a workspace-relative package/build directory, with no broad fallback, coverage, or bail.',args:{scope:exports_external.enum(["all","convention","graph","impact","target"]).optional().describe('Test scope: "all" runs the full suite, "convention"/"graph"/"impact" resolve files, and "target" runs one exact Go or CTest native name without file fallback.'),native_target:exports_external.object({framework:exports_external.enum(["go-test","ctest"]),name:exports_external.string(),path:exports_external.string()}).optional().describe('For scope "target": exact framework-native test name plus a workspace-relative package/build directory. Absolute paths, traversal, coverage, bail, and broad fallback are rejected.'),files:exports_external.array(exports_external.string()).optional().describe('Specific files to test. For "convention", pass source files or direct test files. For "graph" and "impact", pass source files only.'),coverage:exports_external.boolean().optional().describe("Enable coverage reporting if supported"),bail:exports_external.boolean().optional().describe("Stop running tests after the first failure. Default false. Note: coverage may be incomplete when bail=true with coverage=true."),timeout_ms:exports_external.number().optional().describe("Timeout in milliseconds (default 60000, max 300000)"),working_directory:exports_external.string().optional().describe("Explicit project root directory. When provided, tests run relative to this path instead of the plugin context directory. Use this when CWD differs from the actual project root.")},async execute(args2,directory){let workingDirInput;if(args2&&typeof args2==="object"){let obj=args2;workingDirInput=typeof obj.working_directory==="string"?obj.working_directory:void 0}let dirResult=resolveWorkingDirectory(workingDirInput,directory);if(!dirResult.success){let errorResult={success:!1,framework:"none",scope:"all",error:dirResult.message,outcome:"error"};return JSON.stringify(errorResult,null,2)}let workingDir=dirResult.directory;if(workingDir.length>4096)return JSON.stringify({success:!1,framework:"none",scope:"all",error:"Invalid working directory",outcome:"error"},null,2);if(/^[/\\]{2}/.test(workingDir))return JSON.stringify({success:!1,framework:"none",scope:"all",error:"Invalid working directory",outcome:"error"},null,2);if(containsControlChars(workingDir))return JSON.stringify({success:!1,framework:"none",scope:"all",error:"Invalid working directory",outcome:"error"},null,2);if(containsPathTraversal(workingDir))return JSON.stringify({success:!1,framework:"none",scope:"all",error:"Invalid working directory",outcome:"error"},null,2);if(!validateArgs2(args2))return JSON.stringify({success:!1,framework:"none",scope:"all",error:"Invalid arguments",message:'scope must be "all", "convention", "graph", "impact", or "target"; target scope requires one valid native_target and cannot be combined with files, coverage, or bail',outcome:"error"},null,2);let scope=args2.scope||"all",nativeTarget,nativeExecutionDirectory=workingDir,nativeHistoryPath;if(scope==="target"){let resolvedTarget=resolveNativeTarget(args2.native_target,workingDir);if(!resolvedTarget.success)return JSON.stringify({success:!1,framework:args2.native_target.framework,scope,error:resolvedTarget.error,outcome:"error"},null,2);nativeTarget=resolvedTarget.target,nativeExecutionDirectory=resolvedTarget.executionDirectory,nativeHistoryPath=resolvedTarget.historyPath}if(scope==="all"){if(!process.env.SWARM_ALLOW_FULL_SUITE)return JSON.stringify({success:!1,framework:"none",scope:"all",error:'scope "all" is blocked for agent use. Use scope "convention" with specific test files, or scope "graph" with exactly one source file.',message:'The full test suite is blocked in agent context. Use scope "convention" with specific test files, or scope "graph" with exactly one source file. Example: { scope: "convention", files: ["src/tools/test-runner.ts"] }',outcome:"error"},null,2)}if((scope==="convention"||scope==="graph"||scope==="impact")&&(!args2.files||args2.files.length===0))return JSON.stringify({success:!1,framework:"none",scope,error:'scope "convention" and "graph" require explicit files array - omitting files causes unsafe full-project discovery',message:'When using scope "convention" or "graph", you must provide a non-empty "files" array. Use scope "all" for full project test suite without specifying files.',outcome:"error"},null,2);let _files=args2.files||[],coverage=args2.coverage||!1,bail=args2.bail||!1,timeout_ms=Math.min(args2.timeout_ms||DEFAULT_TIMEOUT_MS3,MAX_TIMEOUT_MS3),useDispatch=process.env.SWARM_LANG_BACKEND!=="legacy",framework;if(nativeTarget)framework=nativeTarget.framework;else if(useDispatch){if(framework=await detectTestFrameworkViaDispatch(workingDir),framework==="none")framework=await detectTestFramework(workingDir)}else framework=await detectTestFramework(workingDir);if(framework==="none")return JSON.stringify({success:!1,framework:"none",scope,error:"No test framework detected",message:"No supported test framework found. Install bun, vitest, jest, mocha, pytest, cargo, pester, or a supported language test runner (go test, maven, gradle, dotnet test, ctest, swift test, dart test, rspec, minitest).",totals:{passed:0,failed:0,skipped:0,total:0},outcome:"error"},null,2);let testFiles=[],graphFallbackReason,effectiveScope=scope;if(scope==="target");else if(scope==="all");else if(scope==="convention"){let directTestFiles=args2.files.filter((file3)=>isConventionTestFilePath(file3)),sourceFiles=args2.files.filter((file3)=>{if(directTestFiles.includes(file3))return!1;let ext=path163.extname(file3).toLowerCase();return SOURCE_EXTENSIONS.has(ext)}),invalidFiles=args2.files.filter((file3)=>!directTestFiles.includes(file3)&&!sourceFiles.includes(file3));if(directTestFiles.length===0&&sourceFiles.length===0)return JSON.stringify({success:!1,framework,scope,error:"Provided files contain no recognized source files or direct test files",message:"The files array must contain at least one source file with a recognized extension (.ts, .tsx, .js, .jsx, .py, .rs, .ps1, etc.) or a direct test file in a supported test location/naming convention.",outcome:"error"},null,2);if(invalidFiles.length>0){let errorResult={success:!1,framework,scope,error:"Provided files include entries that are neither recognized source files nor direct test files",message:`These files are not valid for targeted test discovery: ${invalidFiles.join(", ")}`,outcome:"error"};return JSON.stringify(errorResult,null,2)}if(sourceFiles.length>MAX_SAFE_SOURCE_FILES){let errorResult={success:!1,framework,scope,error:`scope "convention" accepts at most ${MAX_SAFE_SOURCE_FILES} source file for discovery (got ${sourceFiles.length}). Treat this as SKIP without retry.`,message:`Too many source files for scope "convention" discovery (${sourceFiles.length} provided, limit is ${MAX_SAFE_SOURCE_FILES}). Call test_runner once per source file, or pass direct test file paths instead of source files.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}testFiles=[...directTestFiles,...getTestFilesFromConvention(sourceFiles,workingDir)].filter((file3,index,items)=>items.indexOf(file3)===index)}else if(scope==="graph"){let sourceFiles=args2.files.filter((f)=>{if(isConventionTestFilePath(f))return!1;let ext=path163.extname(f).toLowerCase();return SOURCE_EXTENSIONS.has(ext)});if(sourceFiles.length===0)return JSON.stringify({success:!1,framework,scope,error:"Provided files contain no source files with recognized extensions",message:'The files array for scope "graph" must contain at least one source file with a recognized extension (.ts, .tsx, .js, .jsx, .py, .rs, .ps1, etc.). Direct test files belong in scope "convention".',outcome:"error"},null,2);if(sourceFiles.length>MAX_SAFE_SOURCE_FILES){let errorResult={success:!1,framework,scope,error:`scope "graph" accepts at most ${MAX_SAFE_SOURCE_FILES} source file (got ${sourceFiles.length}). Treat this as SKIP without retry.`,message:`Too many source files for scope "graph" (${sourceFiles.length} provided, limit is ${MAX_SAFE_SOURCE_FILES}). Call test_runner once per source file, or use scope "convention" with direct test file paths.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}let estimate=await estimateFanOut(sourceFiles,workingDir);if(estimate.estimatedCount>MAX_SAFE_TEST_FILES){let errorResult={success:!1,framework,scope,error:"Estimated test file count exceeds safe maximum",message:`Scope "graph" resolution would produce approximately ${estimate.estimatedCount} test files, which exceeds the safe limit of ${MAX_SAFE_TEST_FILES}. Break the source files into smaller batches and retry.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}let graphTestFiles=await getTestFilesFromGraph(sourceFiles,workingDir);if(graphTestFiles.length>0)testFiles=graphTestFiles;else graphFallbackReason="imports resolution returned no results, falling back to convention",effectiveScope="convention",testFiles=getTestFilesFromConvention(sourceFiles,workingDir)}else if(scope==="impact"){let sourceFiles=args2.files.filter((f)=>{if(isConventionTestFilePath(f))return!1;let ext=path163.extname(f).toLowerCase();return SOURCE_EXTENSIONS.has(ext)});if(sourceFiles.length===0)return JSON.stringify({success:!1,framework,scope,error:"Provided files contain no source files with recognized extensions",message:'The files array for scope "impact" must contain at least one source file with a recognized extension (.ts, .tsx, .js, .jsx, .py, .rs, .ps1, etc.). Direct test files belong in scope "convention".',outcome:"error"},null,2);if(sourceFiles.length>MAX_SAFE_SOURCE_FILES){let errorResult={success:!1,framework,scope,error:`scope "impact" accepts at most ${MAX_SAFE_SOURCE_FILES} source file (got ${sourceFiles.length}). Treat this as SKIP without retry.`,message:`Too many source files for scope "impact" (${sourceFiles.length} provided, limit is ${MAX_SAFE_SOURCE_FILES}). Call test_runner once per source file, or use scope "convention" with direct test file paths.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}let estimate=await estimateFanOut(sourceFiles,workingDir);if(estimate.estimatedCount>MAX_SAFE_TEST_FILES){let errorResult={success:!1,framework,scope,error:"Estimated test file count exceeds safe maximum",message:`Scope "impact" resolution would produce approximately ${estimate.estimatedCount} test files, which exceeds the safe limit of ${MAX_SAFE_TEST_FILES}. Break the source files into smaller batches and retry.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}try{let impactResult=await _internals127.analyzeImpact(sourceFiles,workingDir,MAX_SAFE_TEST_FILES);if(impactResult.budgetExceeded){let errorResult={success:!1,framework,scope,error:"Budget exceeded during impact analysis",message:`Impact analysis exceeded safe budget of ${MAX_SAFE_TEST_FILES} test files.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}if(impactResult.impactedTests.length>0)testFiles=impactResult.impactedTests.map((absPath)=>{let relativePath2=path163.relative(workingDir,absPath);return path163.isAbsolute(relativePath2)?absPath:relativePath2});else{graphFallbackReason="no impacted tests found via impact analysis, falling back to graph",effectiveScope="graph";let graphTestFiles=await getTestFilesFromGraph(sourceFiles,workingDir);if(graphTestFiles.length>0)testFiles=graphTestFiles;else graphFallbackReason="imports resolution returned no results, falling back to convention",effectiveScope="convention",testFiles=getTestFilesFromConvention(sourceFiles,workingDir)}}catch{graphFallbackReason="impact analysis failed, falling back to graph",effectiveScope="graph";let graphTestFiles=await getTestFilesFromGraph(sourceFiles,workingDir);if(graphTestFiles.length>0)testFiles=graphTestFiles;else graphFallbackReason="imports resolution returned no results, falling back to convention",effectiveScope="convention",testFiles=getTestFilesFromConvention(sourceFiles,workingDir)}}if(scope!=="all"&&scope!=="target"&&testFiles.length===0){let errorResult={success:!1,framework,scope:effectiveScope,error:"Provided source files resolved to zero test files",message:graphFallbackReason?`No matching test files found for the provided source files. Check that test files exist with matching naming conventions (.spec.*, .test.*, .Tests.ps1, __tests__/, tests/, test/, spec/). (${graphFallbackReason})`:"No matching test files found for the provided source files. Check that test files exist with matching naming conventions (.spec.*, .test.*, .Tests.ps1, __tests__/, tests/, test/, spec/).",outcome:"skip",...scope==="graph"&&{attempted_scope:"graph"},...scope==="impact"&&{attempted_scope:"graph"}};return JSON.stringify(errorResult,null,2)}if(scope!=="all"&&scope!=="target"&&testFiles.length>MAX_SAFE_TEST_FILES){let sampleFiles=testFiles.slice(0,5),errorResult={success:!1,framework,scope:effectiveScope,error:`Resolved test file count (${testFiles.length}) exceeds safe maximum (${MAX_SAFE_TEST_FILES})`,message:`Too many test files resolved (${testFiles.length}). Maximum allowed is ${MAX_SAFE_TEST_FILES}. Treat this as SKIP without retry. Provide more specific source files to narrow down test scope. First few resolved: ${sampleFiles.join(", ")}`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}let result=await runTests(framework,effectiveScope,testFiles,coverage,timeout_ms,nativeExecutionDirectory,bail,nativeTarget),historyTestFiles=nativeTarget?[formatNativeHistoryTestFile(nativeTarget,nativeHistoryPath)]:testFiles;recordAndAnalyzeResults(result,historyTestFiles,workingDir,nativeTarget?[]:_files.length>0?_files:void 0,result.testCases);let historyReport;if(!result.success&&result.totals&&result.totals.failed>0){if(historyReport=analyzeFailures(workingDir),historyReport.quarantinedFailures.length>0)result.message=(result.message||"")+` | QUARANTINED (flaky): ${historyReport.quarantinedFailures.join(", ")}`;if(historyReport.failureClusters.length>0){let clusterSummary=historyReport.failureClusters.slice(0,3).map((c)=>`${c.classification}: ${c.rootCause.substring(0,80)}`).join("; ");result.message=`${result.message||""} | FAILURE ANALYSIS: ${clusterSummary}`}}if(graphFallbackReason&&result.message)result.message=`${result.message} (${graphFallbackReason})`;if(bail&&coverage&&result.message)result.message=`${result.message} (coverage may be incomplete: bail=true stopped early)`;return JSON.stringify(result,null,2)}}),_internals127={analyzeImpact,loadImpactMap,isCommandAvailable,existsSync:fs85.existsSync,readdirSync:fs85.readdirSync,readFileSync:fs85.readFileSync,bunSpawn,buildNativeTargetCommand,formatNativeHistoryTestFile,selectHistoryForAnalysis,AGGREGATE_TEST_NAME}});import*as fs86 from"node:fs";import*as path164 from"node:path";function formatSecretscanIncompletePaths(incompletePaths,maxEntries=3){let visible=incompletePaths.slice(0,maxEntries).map((entry)=>{return`${entry.path} (${entry.reason})`}),suffix=incompletePaths.length>maxEntries?` (+${incompletePaths.length-maxEntries} more)`:"";return`${visible.join("; ")}${suffix}`}function validateDirectoryPath(dir){if(!dir||typeof dir!=="string")throw Error("Directory path is required");if(dir.includes(".."))throw Error("Directory path must not contain path traversal sequences");let normalized=path164.normalize(dir);return path164.isAbsolute(normalized)?normalized:path164.resolve(normalized)}function validateTimeout(timeoutMs,defaultValue){if(timeoutMs===void 0)return defaultValue;if(typeof timeoutMs!=="number"||!Number.isFinite(timeoutMs))throw Error("Timeout must be a finite number");if(timeoutMs<=0)throw Error("Timeout must be greater than 0");if(timeoutMs<MIN_CHECK_TIMEOUT_MS)throw Error(`Timeout must be at least ${MIN_CHECK_TIMEOUT_MS}ms (5 seconds)`);if(timeoutMs>MAX_CHECK_TIMEOUT_MS)throw Error(`Timeout must not exceed ${MAX_CHECK_TIMEOUT_MS}ms (5 minutes)`);return timeoutMs}function getPackageVersion(dir){try{let packagePath=path164.join(dir,"package.json");if(fs86.existsSync(packagePath)){let content=fs86.readFileSync(packagePath,"utf-8");return JSON.parse(content).version??null}}catch{}return null}function getChangelogVersion(dir){try{let changelogPath=path164.join(dir,"CHANGELOG.md");if(fs86.existsSync(changelogPath)){let match=fs86.readFileSync(changelogPath,"utf-8").match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);if(match)return match[1]}}catch{}return null}function getVersionFileVersion(dir){let possibleFiles=["VERSION.txt","version.txt","VERSION","version"];for(let file3 of possibleFiles){let filePath=path164.join(dir,file3);if(fs86.existsSync(filePath))try{let match=fs86.readFileSync(filePath,"utf-8").trim().match(/(\d+\.\d+\.\d+)/);if(match)return match[1]}catch{}}return null}async function runVersionCheck2(dir,_timeoutMs){let startTime=Date.now();try{let packageVersion=_internals128.getPackageVersion(dir),changelogVersion=_internals128.getChangelogVersion(dir),versionFileVersion=_internals128.getVersionFileVersion(dir),versions3=[];if(packageVersion)versions3.push(`package.json: ${packageVersion}`);if(changelogVersion)versions3.push(`CHANGELOG.md: ${changelogVersion}`);if(versionFileVersion)versions3.push(`version file: ${versionFileVersion}`);if(new Set([packageVersion,changelogVersion,versionFileVersion].filter(Boolean)).size<=1){if(versions3.length===0)return{type:"version",status:"skip",message:"No version information found to check",details:{},durationMs:Date.now()-startTime};return{type:"version",status:"pass",message:`Version consistent: ${versions3.join(", ")}`,details:{packageVersion,changelogVersion,versionFileVersion},durationMs:Date.now()-startTime}}return{type:"version",status:"fail",message:`Version mismatch: ${versions3.join("; ")}`,details:{packageVersion,changelogVersion,versionFileVersion},durationMs:Date.now()-startTime}}catch(error93){return{type:"version",status:"error",message:`Version check failed: ${error93 instanceof Error?error93.message:String(error93)}`,durationMs:Date.now()-startTime}}}async function runLintCheck(dir,linter,timeoutMs){let startTime=Date.now();try{let lintPromise=runLint(linter,"check",dir),timeoutId,timeoutPromise=new Promise((_,reject)=>{timeoutId=setTimeout(()=>{reject(Error(`Lint check timed out after ${timeoutMs}ms`))},timeoutMs)}),result=await Promise.race([lintPromise,timeoutPromise]).finally(()=>clearTimeout(timeoutId));if(!result.success)return{type:"lint",status:"error",message:result.error??"Lint check failed",details:{linter,success:result.success},durationMs:Date.now()-startTime};if(result.exitCode!==0){let issueMatch=result.output.match(/(\d+)\s+(issues?|errors?)/i),issueCount=issueMatch?parseInt(issueMatch[1],10):void 0;return{type:"lint",status:"fail",message:issueCount?`Lint found ${issueCount} issue(s)`:"Lint found issues",details:{linter,exitCode:result.exitCode,issueCount,hasOutput:result.output.length>0},durationMs:Date.now()-startTime}}return{type:"lint",status:"pass",message:"Lint check passed",details:{linter,exitCode:result.exitCode},durationMs:Date.now()-startTime}}catch(error93){if(error93 instanceof Error&&error93.message.includes("timed out"))return{type:"lint",status:"error",message:error93.message,details:{linter},durationMs:Date.now()-startTime};return{type:"lint",status:"error",message:`Lint check failed: ${error93 instanceof Error?error93.message:String(error93)}`,details:{linter},durationMs:Date.now()-startTime}}}async function runTestsCheck(_dir,scope,timeoutMs){let startTime=Date.now();try{let result=await runTests("none",scope,[],!1,timeoutMs,_dir,!1);if(!result.success)return{type:"tests",status:"error",message:result.error??"Tests check failed",details:{framework:result.framework,scope,success:result.success},durationMs:Date.now()-startTime};if(result.totals.failed>0)return{type:"tests",status:"fail",message:`Tests failed: ${result.totals.failed}/${result.totals.total} failed`,details:{framework:result.framework,scope,totals:result.totals},durationMs:Date.now()-startTime};if(result.totals.total===0)return{type:"tests",status:"skip",message:"No tests found to run",details:{framework:result.framework,scope},durationMs:Date.now()-startTime};return{type:"tests",status:"pass",message:`Tests passed: ${result.totals.passed} passed`,details:{framework:result.framework,scope,totals:result.totals},durationMs:Date.now()-startTime}}catch(error93){if(error93 instanceof Error&&(error93.message.includes("timeout")||error93.message.includes("ETIMEDOUT")))return{type:"tests",status:"error",message:`Tests check timed out after ${timeoutMs}ms`,durationMs:Date.now()-startTime};return{type:"tests",status:"error",message:`Tests check failed: ${error93 instanceof Error?error93.message:String(error93)}`,durationMs:Date.now()-startTime}}}async function runSecretsCheck(dir,timeoutMs){let startTime=Date.now();try{let secretsPromise=_internals128.runSecretscan(dir),timeoutPromise=new Promise((_,reject)=>{setTimeout(()=>{reject(Error(`Secrets check timed out after ${timeoutMs}ms`))},timeoutMs)}),result=await Promise.race([secretsPromise,timeoutPromise]);if("error"in result)return{type:"secrets",status:"fail",message:`Secrets check failed: ${result.error}`,details:{error:result.error,filesScanned:result.files_scanned,incompleteFiles:0,incompletePaths:[]},durationMs:Date.now()-startTime};let findingsCount=Math.max(result.count,result.findings.length);if(typeof result.incomplete_files!=="number"||!Array.isArray(result.incomplete_paths))return{type:"secrets",status:"fail",message:"Secrets check failed: scanner returned incomplete coverage metadata",details:{filesScanned:result.files_scanned},durationMs:Date.now()-startTime};let{incomplete_files:incompleteFiles,incomplete_paths:incompletePaths}=result,hasCountMismatch=result.count!==result.findings.length,hasIncompleteCoverage=incompleteFiles>0||incompletePaths.length>0,hasZeroCoverage=result.files_scanned===0,failures=[];if(findingsCount>0){let critical=result.findings.filter((f)=>f.severity==="critical").length,high=result.findings.filter((f)=>f.severity==="high").length;failures.push(`Found ${findingsCount} secret(s): ${critical} critical, ${high} high`)}if(hasIncompleteCoverage){let incompleteSummary=incompletePaths.length>0?`; incomplete paths: ${formatSecretscanIncompletePaths(incompletePaths)}`:"";failures.push(`${incompleteFiles} incomplete file(s)${incompleteSummary}`)}if(hasCountMismatch)failures.push(`findings/count mismatch (reported ${result.count}, actual ${result.findings.length})`);if(hasZeroCoverage)failures.push("zero requested files scanned");if(failures.length>0)return{type:"secrets",status:"fail",message:`Secrets check failed: ${failures.join("; ")}`,details:{count:findingsCount,reportedCount:result.count,critical:result.findings.filter((f)=>f.severity==="critical").length,high:result.findings.filter((f)=>f.severity==="high").length,filesScanned:result.files_scanned,skippedFiles:result.skipped_files,incompleteFiles,incompletePaths},durationMs:Date.now()-startTime};return{type:"secrets",status:"pass",message:"No secrets detected",details:{filesScanned:result.files_scanned,skippedFiles:result.skipped_files,incompleteFiles,incompletePaths},durationMs:Date.now()-startTime}}catch(error93){if(error93 instanceof Error&&error93.name==="AbortError")return{type:"secrets",status:"error",message:`Secrets check timed out after ${timeoutMs}ms`,durationMs:Date.now()-startTime};return{type:"secrets",status:"error",message:`Secrets check failed: ${error93 instanceof Error?error93.message:String(error93)}`,durationMs:Date.now()-startTime}}}async function runEvidenceCheck(dir){let startTime=Date.now();try{let plan=await loadPlan(dir);if(!plan)return{type:"evidence",status:"skip",message:"No plan found to check evidence against",details:{},durationMs:Date.now()-startTime};let completedTaskIds=[];for(let phase of plan.phases)for(let task of phase.tasks)if(task.status==="completed")completedTaskIds.push(task.id);if(completedTaskIds.length===0)return{type:"evidence",status:"skip",message:"No completed tasks yet",details:{completedTasks:0},durationMs:Date.now()-startTime};let evidenceTaskIds=new Set(await listEvidenceTaskIds(dir)),missingEvidence=[];for(let id of completedTaskIds){let gateStatus=await getDurableGateEvidenceStatusForTask(dir,id);if(gateStatus.isComplete)continue;if(gateStatus.evidenceExists&&gateStatus.missingGates.length>0){missingEvidence.push(id);continue}if(evidenceTaskIds.has(id))continue;missingEvidence.push(id)}let completedWithEvidence=completedTaskIds.length-missingEvidence.length;if(missingEvidence.length>0)return{type:"evidence",status:"fail",message:`${missingEvidence.length} completed task(s) missing evidence`,details:{totalCompleted:completedTaskIds.length,totalWithEvidence:completedWithEvidence,missingTasks:missingEvidence.slice(0,10),missingCount:missingEvidence.length},durationMs:Date.now()-startTime};return{type:"evidence",status:"pass",message:`All ${completedTaskIds.length} completed tasks have evidence`,details:{totalCompleted:completedTaskIds.length,totalWithEvidence:completedWithEvidence},durationMs:Date.now()-startTime}}catch(error93){return{type:"evidence",status:"error",message:`Evidence check failed: ${error93 instanceof Error?error93.message:String(error93)}`,durationMs:Date.now()-startTime}}}async function runRequirementCoverageCheck(dir,currentPhase){let startTime=Date.now();try{if(readEffectiveSpecSync(dir)===null)return{type:"req_coverage",status:"skip",message:"No effective spec found, requirement coverage not required",details:{},durationMs:Date.now()-startTime};let coverage=await checkRequirementCoverage(currentPhase,dir);if(coverage.exists)return{type:"req_coverage",status:"pass",message:"Requirement coverage report found",details:{path:coverage.path},durationMs:Date.now()-startTime};return{type:"req_coverage",status:"fail",message:"Requirement coverage report missing but effective spec exists",details:{expectedPath:coverage.path},durationMs:Date.now()-startTime}}catch(error93){return{type:"req_coverage",status:"error",message:`Requirement coverage check failed: ${error93 instanceof Error?error93.message:String(error93)}`,durationMs:Date.now()-startTime}}}async function runPreflight(dir,phase,config3){let startTime=Date.now(),reportId=`preflight-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,validatedDir;try{validatedDir=_internals128.validateDirectoryPath(dir)}catch(error93){return{id:reportId,timestamp:startTime,phase,overall:"fail",checks:[{type:"lint",status:"error",message:`Invalid directory: ${error93 instanceof Error?error93.message:String(error93)}`}],totalDurationMs:Date.now()-startTime,message:"Preflight aborted: invalid directory"}}let validatedTimeout;try{validatedTimeout=_internals128.validateTimeout(config3?.checkTimeoutMs,DEFAULT_CONFIG.checkTimeoutMs)}catch(error93){return{id:reportId,timestamp:startTime,phase,overall:"fail",checks:[{type:"lint",status:"error",message:`Invalid config: ${error93 instanceof Error?error93.message:String(error93)}`}],totalDurationMs:Date.now()-startTime,message:"Preflight aborted: invalid configuration"}}let cfg={checkTimeoutMs:validatedTimeout,skipTests:config3?.skipTests??DEFAULT_CONFIG.skipTests,skipSecrets:config3?.skipSecrets??DEFAULT_CONFIG.skipSecrets,skipEvidence:config3?.skipEvidence??DEFAULT_CONFIG.skipEvidence,skipVersion:config3?.skipVersion??DEFAULT_CONFIG.skipVersion,testScope:config3?.testScope??DEFAULT_CONFIG.testScope,linter:config3?.linter??DEFAULT_CONFIG.linter};log("[Preflight] Starting preflight checks",{reportId,phase,config:{skipTests:cfg.skipTests,skipSecrets:cfg.skipSecrets,skipEvidence:cfg.skipEvidence,skipVersion:cfg.skipVersion,testScope:cfg.testScope,linter:cfg.linter}});let checks5=[];log("[Preflight] Running lint check...");let lintResult=await _internals128.runLintCheck(validatedDir,cfg.linter,cfg.checkTimeoutMs);if(checks5.push(lintResult),log(`[Preflight] Lint check: ${lintResult.status} ${lintResult.message}`),!cfg.skipTests){log("[Preflight] Running tests check...");let testsResult=await _internals128.runTestsCheck(validatedDir,cfg.testScope,cfg.checkTimeoutMs);checks5.push(testsResult),log(`[Preflight] Tests check: ${testsResult.status} ${testsResult.message}`)}else checks5.push({type:"tests",status:"skip",message:"Tests check skipped by configuration"});if(!cfg.skipSecrets){log("[Preflight] Running secrets check...");let secretsResult=await _internals128.runSecretsCheck(validatedDir,cfg.checkTimeoutMs);checks5.push(secretsResult),log(`[Preflight] Secrets check: ${secretsResult.status} ${secretsResult.message}`)}else checks5.push({type:"secrets",status:"skip",message:"Secrets check skipped by configuration"});if(!cfg.skipEvidence){log("[Preflight] Running evidence check...");let evidenceResult=await _internals128.runEvidenceCheck(validatedDir);checks5.push(evidenceResult),log(`[Preflight] Evidence check: ${evidenceResult.status} ${evidenceResult.message}`)}else checks5.push({type:"evidence",status:"skip",message:"Evidence check skipped by configuration"});log("[Preflight] Running requirement coverage check...");let reqCoverageResult=await _internals128.runRequirementCoverageCheck(validatedDir,phase);if(checks5.push(reqCoverageResult),log(`[Preflight] Requirement coverage check: ${reqCoverageResult.status} ${reqCoverageResult.message}`),!cfg.skipVersion){log("[Preflight] Running version check...");let versionResult=await _internals128.runVersionCheck(validatedDir,cfg.checkTimeoutMs);checks5.push(versionResult),log(`[Preflight] Version check: ${versionResult.status} ${versionResult.message}`)}else checks5.push({type:"version",status:"skip",message:"Version check skipped by configuration"});let totalDurationMs=Date.now()-startTime,failedChecks=checks5.filter((c)=>c.status==="fail").length,errorChecks=checks5.filter((c)=>c.status==="error").length,skippedChecks=checks5.filter((c)=>c.status==="skip").length,overall,message;if(errorChecks>0)overall="fail",message=`Preflight failed with ${errorChecks} error(s)`;else if(failedChecks>0)overall="fail",message=`Preflight failed: ${failedChecks} check(s) failed`;else if(skippedChecks===checks5.length)overall="skipped",message="All checks were skipped";else overall="pass",message="Preflight passed all checks";return log(`[Preflight] Complete: ${overall} ${message}`),{id:reportId,timestamp:startTime,phase,overall,checks:checks5,totalDurationMs,message}}function formatPreflightMarkdown(report){let lines=["## Preflight Report","",`**Phase**: ${report.phase}`,`**Overall**: ${report.overall==="pass"?"✅ PASS":report.overall==="fail"?"❌ FAIL":"⏭️ SKIPPED"}`,`**Duration**: ${(report.totalDurationMs/1000).toFixed(2)}s`,"","### Checks",""];for(let check3 of report.checks){let icon=check3.status==="pass"?"✅":check3.status==="fail"?"❌":check3.status==="error"?"⚠️":"⏭️";lines.push(`- ${icon} **${check3.type}**: ${check3.message}`)}return lines.push(""),lines.push(report.message),lines.join(`
|
|
2051
|
+
... (output truncated at stream read limit)`;let parsed=process.env.SWARM_LANG_BACKEND!=="legacy"?await parseTestOutputViaDispatch(framework,output,executionCwd)??parseTestOutput2(framework,output):parseTestOutput2(framework,output),parsedTestCases=parseFrameworkJsonTestResults(framework,output),totals={...parsed.totals},{coveragePercent}=parsed;if(totals.total===0&&parsedTestCases.length>0){for(let entry of parsedTestCases)if(entry.result==="pass")totals.passed++;else if(entry.result==="fail")totals.failed++;else totals.skipped++;totals.total=parsedTestCases.length}let isTimeout=timedOutByDeadline,nativeTargetObserved=resolvedNativeTarget?didExecuteNativeTarget(resolvedNativeTarget,output):!0;if(exitCode===0&&!isTimeout&&totals.failed===0&&nativeTargetObserved){let result={success:!0,framework,scope,command,timeout_ms,duration_ms,totals,rawOutput:output,outcome:"pass",testCases:parsedTestCases};if(coveragePercent!==void 0)result.coveragePercent=coveragePercent;return result.message=formatPassingMessage(framework,totals,coveragePercent),result}else{let result={success:!1,framework,scope,command,timeout_ms,duration_ms,totals,rawOutput:output,error:isTimeout?`Tests timed out after ${timeout_ms}ms`:!nativeTargetObserved?`Native target "${resolvedNativeTarget?.name}" did not execute`:`Tests failed with ${totals.failed} failures`,message:isTimeout?`${framework} tests timed out after ${timeout_ms}ms`:!nativeTargetObserved?`${framework} did not report the exact requested native target; refusing a false-green 0/0 result`:`${framework} tests failed (${totals.failed}/${totals.total} failed)`,outcome:isTimeout?"error":"regression",testCases:parsedTestCases};if(coveragePercent!==void 0)result.coveragePercent=coveragePercent;return result}}catch(error93){let duration_ms=Date.now()-startTime;return{success:!1,framework,scope,command,timeout_ms,duration_ms,error:error93 instanceof Error?`Execution failed: ${error93.message}`:"Execution failed: unknown error",outcome:"error"}}finally{if(timeoutHandle!==void 0)clearTimeout(timeoutHandle);if(proc?.exitCode===null&&!timedOutByDeadline)try{if(proc.killTree)await proc.killTree("SIGKILL");else proc.kill("SIGKILL")}catch{}}}function escapeRegexForMatch(value){return value.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function didExecuteNativeTarget(target,output){if(target.framework==="go-test")return[...output.matchAll(/^\s*--- (?:PASS|FAIL|SKIP):\s+(.+?)(?:\s+\(|$)/gm)].some((match)=>match[1]===target.name);let exactName=escapeRegexForMatch(target.name);return new RegExp(`(?:Start\\s+\\d+:\\s*|Test\\s+#\\d+:\\s*)${exactName}(?=\\s|$)`,"m").test(output)}function normalizeHistoryTestFile(testFile,workingDir){let normalized=testFile.replace(/\\/g,"/");if(!path163.isAbsolute(testFile))return normalized;let relative35=path163.relative(workingDir,testFile);if(relative35.startsWith("..")||path163.isAbsolute(relative35))return normalized;return relative35.replace(/\\/g,"/")}function combineAggregateResult(current,next){if(current==="fail"||next==="fail")return"fail";if(current==="pass"||next==="pass")return"pass";return"skip"}function recordAndAnalyzeResults(result,testFiles,workingDir,sourceFiles,parsedTestCases){if(!result.totals||result.totals.total===0)return;let now2=new Date().toISOString(),changedFiles=(sourceFiles!==void 0?sourceFiles:testFiles).map((f)=>f.replace(/\\/g,"/")),aggregateResultsByFile=new Map,validParsedCases=parsedTestCases?.filter((parsedCase)=>parsedCase.testFile.length>0&&parsedCase.testName.length>0)??[],allRecords=[];for(let parsedCase of validParsedCases){let normalizedTestFile=normalizeHistoryTestFile(parsedCase.testFile,workingDir);allRecords.push({timestamp:now2,taskId:"auto",testFile:normalizedTestFile,testName:parsedCase.testName,result:parsedCase.result,durationMs:parsedCase.durationMs,errorMessage:parsedCase.errorMessage,stackPrefix:parsedCase.stackPrefix,changedFiles}),aggregateResultsByFile.set(normalizedTestFile,combineAggregateResult(aggregateResultsByFile.get(normalizedTestFile),parsedCase.result))}if(aggregateResultsByFile.size===0){let aggregateResult=result.success?"pass":"fail";for(let testFile of testFiles)aggregateResultsByFile.set(testFile.replace(/\\/g,"/"),aggregateResult)}for(let[testFile,aggregateResult]of aggregateResultsByFile)allRecords.push({timestamp:now2,taskId:"auto",testFile,testName:AGGREGATE_TEST_NAME,result:aggregateResult,durationMs:result.duration_ms||0,changedFiles});try{batchAppendTestRuns(allRecords,workingDir)}catch{}}function selectHistoryForAnalysis(history){let filesWithIndividualRecords=new Set;for(let record3 of history)if(record3.testName!==AGGREGATE_TEST_NAME)filesWithIndividualRecords.add(record3.testFile.toLowerCase());if(filesWithIndividualRecords.size===0)return history;return history.filter((record3)=>record3.testName!==AGGREGATE_TEST_NAME||!filesWithIndividualRecords.has(record3.testFile.toLowerCase()))}function analyzeFailures(workingDir){let report={flakyTests:[],failureClusters:[],quarantinedFailures:[]};try{let history=selectHistoryForAnalysis(getAllHistory(workingDir));if(history.length===0)return report;report.flakyTests=detectFlakyTests(history);let failingResults=history.filter((r)=>r.result==="fail");if(failingResults.length>0){let{clusters}=classifyAndCluster(failingResults,history);report.failureClusters=clusters.map((c)=>({rootCause:c.rootCause,affectedFiles:c.affectedTestFiles,classification:c.classification}))}for(let entry of report.flakyTests)if(entry.isQuarantined)report.quarantinedFailures.push(`${entry.testFile}: ${entry.testName}`)}catch{}return report}var MAX_OUTPUT_BYTES4=512000,MAX_COMMAND_LENGTH2=500,DEFAULT_TIMEOUT_MS3=60000,MAX_TIMEOUT_MS3=300000,MAX_SAFE_TEST_FILES=50,MAX_SAFE_SOURCE_FILES=1,AGGREGATE_TEST_NAME="(aggregate)",VITEST_JSON_OUTPUT_RELATIVE_PATH=".swarm/cache/test-runner-vitest.json",POWERSHELL_METACHARACTERS,SHELL_METACHARACTERS2,DISPATCH_FRAMEWORK_MAP,COMPOUND_TEST_EXTENSIONS,TEST_DIRECTORY_NAMES,SOURCE_EXTENSIONS,test_runner,_internals127;var init_test_runner=__esm(()=>{init_zod();init_discovery();init_default_backend();init_analyzer();init_failure_classifier();init_history_store();init_bun_compat();init_path_security();init_create_tool();init_resolve_working_directory();POWERSHELL_METACHARACTERS=/[|;&`$(){}[\]<>"'#*?\x00-\x1f]/;SHELL_METACHARACTERS2=/[;&`$(){}<>"'\x00-\x1f]/;DISPATCH_FRAMEWORK_MAP={bun:"bun",vitest:"vitest",jest:"jest",mocha:"mocha",pytest:"pytest",cargo:"cargo",pester:"pester","go-test":"go-test",maven:"maven",gradle:"gradle","dotnet-test":"dotnet-test",ctest:"ctest","swift-test":"swift-test","dart-test":"dart-test",rspec:"rspec",minitest:"minitest",pest:"pest",phpunit:"phpunit","php-artisan":"php-artisan","bun:test":"bun","xcodebuild-test":"swift-test","flutter test":"dart-test","dart test":"dart-test",Pest:"pest",PHPUnit:"phpunit"};COMPOUND_TEST_EXTENSIONS=[".test.ts",".test.tsx",".test.js",".test.jsx",".tests.ps1",".spec.ts",".spec.tsx",".spec.js",".spec.jsx",".test.ps1",".spec.ps1"],TEST_DIRECTORY_NAMES=["__tests__","tests","test","spec"];SOURCE_EXTENSIONS=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".py",".rs",".ps1",".psm1",".go",".java",".kt",".kts",".cs",".c",".h",".cpp",".hpp",".cc",".cxx",".php",".swift",".dart",".rb",".pyi"]);test_runner=createSwarmTool({description:'Run project tests with automatic framework detection for bun, vitest, jest, mocha, pytest, cargo, pester, go test, maven, gradle, dotnet test, ctest, swift test, dart test, rspec, minitest, pest, phpunit, or php-artisan. Returns JSON with success, framework, scope, command, timeout_ms, duration_ms, totals, outcome, and optional coveragePercent, rawOutput, testCases, and message fields. Scope "target" runs one exact Go test/subtest or CTest name via native_target using a workspace-relative package/build directory, with no broad fallback, coverage, or bail. The "targets" array passes framework-native test name patterns to cargo, go-test, maven, gradle, dotnet-test, ctest, and swift-test.',args:{scope:exports_external.enum(["all","convention","graph","impact","target"]).optional().describe('Test scope: "all" runs the full suite, "convention"/"graph"/"impact" resolve files, and "target" runs one exact Go or CTest native name without file fallback.'),native_target:exports_external.object({framework:exports_external.enum(["go-test","ctest"]),name:exports_external.string(),path:exports_external.string()}).optional().describe('For scope "target": exact framework-native test name plus a workspace-relative package/build directory. Absolute paths, traversal, coverage, bail, and broad fallback are rejected.'),files:exports_external.array(exports_external.string()).optional().describe('Specific files to test. For "convention", pass source files or direct test files. For "graph" and "impact", pass source files only.'),targets:exports_external.array(exports_external.string()).optional().describe("Framework-native test names or patterns to filter which tests run. Supported by cargo, go-test, maven, gradle, dotnet-test, ctest, and swift-test. Each entry is passed as-is to the framework's native filter flag."),coverage:exports_external.boolean().optional().describe("Enable coverage reporting if supported"),bail:exports_external.boolean().optional().describe("Stop running tests after the first failure. Default false. Note: coverage may be incomplete when bail=true with coverage=true."),timeout_ms:exports_external.number().optional().describe("Timeout in milliseconds (default 60000, max 300000)"),working_directory:exports_external.string().optional().describe("Explicit project root directory. When provided, tests run relative to this path instead of the plugin context directory. Use this when CWD differs from the actual project root.")},async execute(args2,directory){let workingDirInput;if(args2&&typeof args2==="object"){let obj=args2;workingDirInput=typeof obj.working_directory==="string"?obj.working_directory:void 0}let dirResult=resolveWorkingDirectory(workingDirInput,directory);if(!dirResult.success){let errorResult={success:!1,framework:"none",scope:"all",error:dirResult.message,outcome:"error"};return JSON.stringify(errorResult,null,2)}let workingDir=dirResult.directory;if(workingDir.length>4096)return JSON.stringify({success:!1,framework:"none",scope:"all",error:"Invalid working directory",outcome:"error"},null,2);if(/^[/\\]{2}/.test(workingDir))return JSON.stringify({success:!1,framework:"none",scope:"all",error:"Invalid working directory",outcome:"error"},null,2);if(containsControlChars(workingDir))return JSON.stringify({success:!1,framework:"none",scope:"all",error:"Invalid working directory",outcome:"error"},null,2);if(containsPathTraversal(workingDir))return JSON.stringify({success:!1,framework:"none",scope:"all",error:"Invalid working directory",outcome:"error"},null,2);if(!validateArgs2(args2))return JSON.stringify({success:!1,framework:"none",scope:"all",error:"Invalid arguments",message:'scope must be "all", "convention", "graph", "impact", or "target"; files and targets must be string arrays with safe values; target scope requires one valid native_target and cannot be combined with files, coverage, or bail',outcome:"error"},null,2);let scope=args2.scope||"all",nativeTarget,nativeExecutionDirectory=workingDir,nativeHistoryPath;if(scope==="target"){let resolvedTarget=resolveNativeTarget(args2.native_target,workingDir);if(!resolvedTarget.success)return JSON.stringify({success:!1,framework:args2.native_target.framework,scope,error:resolvedTarget.error,outcome:"error"},null,2);nativeTarget=resolvedTarget.target,nativeExecutionDirectory=resolvedTarget.executionDirectory,nativeHistoryPath=resolvedTarget.historyPath}if(scope==="all"){if(!process.env.SWARM_ALLOW_FULL_SUITE)return JSON.stringify({success:!1,framework:"none",scope:"all",error:'scope "all" is blocked for agent use. Use scope "convention" with specific test files, or scope "graph" with exactly one source file.',message:'The full test suite is blocked in agent context. Use scope "convention" with specific test files, or scope "graph" with exactly one source file. Example: { scope: "convention", files: ["src/tools/test-runner.ts"] }',outcome:"error"},null,2)}if((scope==="convention"||scope==="graph"||scope==="impact")&&(!args2.files||args2.files.length===0)&&(!args2.targets||args2.targets.length===0))return JSON.stringify({success:!1,framework:"none",scope,error:'scope "convention" and "graph" require explicit files or targets array - omitting both causes unsafe full-project discovery',message:'When using scope "convention" or "graph", you must provide a non-empty "files" or "targets" array. Use scope "all" for full project test suite without specifying files.',outcome:"error"},null,2);let _files=args2.files||[],coverage=args2.coverage||!1,bail=args2.bail||!1,timeout_ms=Math.min(args2.timeout_ms||DEFAULT_TIMEOUT_MS3,MAX_TIMEOUT_MS3),useDispatch=process.env.SWARM_LANG_BACKEND!=="legacy",framework;if(nativeTarget)framework=nativeTarget.framework;else if(useDispatch){if(framework=await detectTestFrameworkViaDispatch(workingDir),framework==="none")framework=await detectTestFramework(workingDir)}else framework=await detectTestFramework(workingDir);if(framework==="none")return JSON.stringify({success:!1,framework:"none",scope,error:"No test framework detected",message:"No supported test framework found. Install bun, vitest, jest, mocha, pytest, cargo, pester, or a supported language test runner (go test, maven, gradle, dotnet test, ctest, swift test, dart test, rspec, minitest).",totals:{passed:0,failed:0,skipped:0,total:0},outcome:"error"},null,2);let testFiles=[],graphFallbackReason,effectiveScope=scope;if(scope==="target");else if(scope==="all");else if(scope==="convention"){let directTestFiles=args2.files.filter((file3)=>isConventionTestFilePath(file3)),sourceFiles=args2.files.filter((file3)=>{if(directTestFiles.includes(file3))return!1;let ext=path163.extname(file3).toLowerCase();return SOURCE_EXTENSIONS.has(ext)}),invalidFiles=args2.files.filter((file3)=>!directTestFiles.includes(file3)&&!sourceFiles.includes(file3));if(directTestFiles.length===0&&sourceFiles.length===0)return JSON.stringify({success:!1,framework,scope,error:"Provided files contain no recognized source files or direct test files",message:"The files array must contain at least one source file with a recognized extension (.ts, .tsx, .js, .jsx, .py, .rs, .ps1, etc.) or a direct test file in a supported test location/naming convention.",outcome:"error"},null,2);if(invalidFiles.length>0){let errorResult={success:!1,framework,scope,error:"Provided files include entries that are neither recognized source files nor direct test files",message:`These files are not valid for targeted test discovery: ${invalidFiles.join(", ")}`,outcome:"error"};return JSON.stringify(errorResult,null,2)}if(sourceFiles.length>MAX_SAFE_SOURCE_FILES){let errorResult={success:!1,framework,scope,error:`scope "convention" accepts at most ${MAX_SAFE_SOURCE_FILES} source file for discovery (got ${sourceFiles.length}). Treat this as SKIP without retry.`,message:`Too many source files for scope "convention" discovery (${sourceFiles.length} provided, limit is ${MAX_SAFE_SOURCE_FILES}). Call test_runner once per source file, or pass direct test file paths instead of source files.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}testFiles=[...directTestFiles,...getTestFilesFromConvention(sourceFiles,workingDir)].filter((file3,index,items)=>items.indexOf(file3)===index)}else if(scope==="graph"){let sourceFiles=args2.files.filter((f)=>{if(isConventionTestFilePath(f))return!1;let ext=path163.extname(f).toLowerCase();return SOURCE_EXTENSIONS.has(ext)});if(sourceFiles.length===0)return JSON.stringify({success:!1,framework,scope,error:"Provided files contain no source files with recognized extensions",message:'The files array for scope "graph" must contain at least one source file with a recognized extension (.ts, .tsx, .js, .jsx, .py, .rs, .ps1, etc.). Direct test files belong in scope "convention".',outcome:"error"},null,2);if(sourceFiles.length>MAX_SAFE_SOURCE_FILES){let errorResult={success:!1,framework,scope,error:`scope "graph" accepts at most ${MAX_SAFE_SOURCE_FILES} source file (got ${sourceFiles.length}). Treat this as SKIP without retry.`,message:`Too many source files for scope "graph" (${sourceFiles.length} provided, limit is ${MAX_SAFE_SOURCE_FILES}). Call test_runner once per source file, or use scope "convention" with direct test file paths.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}let estimate=await estimateFanOut(sourceFiles,workingDir);if(estimate.estimatedCount>MAX_SAFE_TEST_FILES){let errorResult={success:!1,framework,scope,error:"Estimated test file count exceeds safe maximum",message:`Scope "graph" resolution would produce approximately ${estimate.estimatedCount} test files, which exceeds the safe limit of ${MAX_SAFE_TEST_FILES}. Break the source files into smaller batches and retry.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}let graphTestFiles=await getTestFilesFromGraph(sourceFiles,workingDir);if(graphTestFiles.length>0)testFiles=graphTestFiles;else graphFallbackReason="imports resolution returned no results, falling back to convention",effectiveScope="convention",testFiles=getTestFilesFromConvention(sourceFiles,workingDir)}else if(scope==="impact"){let sourceFiles=args2.files.filter((f)=>{if(isConventionTestFilePath(f))return!1;let ext=path163.extname(f).toLowerCase();return SOURCE_EXTENSIONS.has(ext)});if(sourceFiles.length===0)return JSON.stringify({success:!1,framework,scope,error:"Provided files contain no source files with recognized extensions",message:'The files array for scope "impact" must contain at least one source file with a recognized extension (.ts, .tsx, .js, .jsx, .py, .rs, .ps1, etc.). Direct test files belong in scope "convention".',outcome:"error"},null,2);if(sourceFiles.length>MAX_SAFE_SOURCE_FILES){let errorResult={success:!1,framework,scope,error:`scope "impact" accepts at most ${MAX_SAFE_SOURCE_FILES} source file (got ${sourceFiles.length}). Treat this as SKIP without retry.`,message:`Too many source files for scope "impact" (${sourceFiles.length} provided, limit is ${MAX_SAFE_SOURCE_FILES}). Call test_runner once per source file, or use scope "convention" with direct test file paths.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}let estimate=await estimateFanOut(sourceFiles,workingDir);if(estimate.estimatedCount>MAX_SAFE_TEST_FILES){let errorResult={success:!1,framework,scope,error:"Estimated test file count exceeds safe maximum",message:`Scope "impact" resolution would produce approximately ${estimate.estimatedCount} test files, which exceeds the safe limit of ${MAX_SAFE_TEST_FILES}. Break the source files into smaller batches and retry.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}try{let impactResult=await _internals127.analyzeImpact(sourceFiles,workingDir,MAX_SAFE_TEST_FILES);if(impactResult.budgetExceeded){let errorResult={success:!1,framework,scope,error:"Budget exceeded during impact analysis",message:`Impact analysis exceeded safe budget of ${MAX_SAFE_TEST_FILES} test files.`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}if(impactResult.impactedTests.length>0)testFiles=impactResult.impactedTests.map((absPath)=>{let relativePath2=path163.relative(workingDir,absPath);return path163.isAbsolute(relativePath2)?absPath:relativePath2});else{graphFallbackReason="no impacted tests found via impact analysis, falling back to graph",effectiveScope="graph";let graphTestFiles=await getTestFilesFromGraph(sourceFiles,workingDir);if(graphTestFiles.length>0)testFiles=graphTestFiles;else graphFallbackReason="imports resolution returned no results, falling back to convention",effectiveScope="convention",testFiles=getTestFilesFromConvention(sourceFiles,workingDir)}}catch{graphFallbackReason="impact analysis failed, falling back to graph",effectiveScope="graph";let graphTestFiles=await getTestFilesFromGraph(sourceFiles,workingDir);if(graphTestFiles.length>0)testFiles=graphTestFiles;else graphFallbackReason="imports resolution returned no results, falling back to convention",effectiveScope="convention",testFiles=getTestFilesFromConvention(sourceFiles,workingDir)}}if(scope!=="all"&&scope!=="target"&&testFiles.length===0&&!(args2.targets&&args2.targets.length>0)){let errorResult={success:!1,framework,scope:effectiveScope,error:"Provided source files resolved to zero test files",message:graphFallbackReason?`No matching test files found for the provided source files. Check that test files exist with matching naming conventions (.spec.*, .test.*, .Tests.ps1, __tests__/, tests/, test/, spec/). (${graphFallbackReason})`:"No matching test files found for the provided source files. Check that test files exist with matching naming conventions (.spec.*, .test.*, .Tests.ps1, __tests__/, tests/, test/, spec/).",outcome:"skip",...scope==="graph"&&{attempted_scope:"graph"},...scope==="impact"&&{attempted_scope:"graph"}};return JSON.stringify(errorResult,null,2)}if(scope!=="all"&&scope!=="target"&&testFiles.length>MAX_SAFE_TEST_FILES){let sampleFiles=testFiles.slice(0,5),errorResult={success:!1,framework,scope:effectiveScope,error:`Resolved test file count (${testFiles.length}) exceeds safe maximum (${MAX_SAFE_TEST_FILES})`,message:`Too many test files resolved (${testFiles.length}). Maximum allowed is ${MAX_SAFE_TEST_FILES}. Treat this as SKIP without retry. Provide more specific source files to narrow down test scope. First few resolved: ${sampleFiles.join(", ")}`,outcome:"scope_exceeded"};return JSON.stringify(errorResult,null,2)}let result=await runTests(framework,effectiveScope,testFiles,coverage,timeout_ms,nativeExecutionDirectory,bail,args2.targets,nativeTarget),historyTestFiles=nativeTarget?[formatNativeHistoryTestFile(nativeTarget,nativeHistoryPath)]:testFiles;recordAndAnalyzeResults(result,historyTestFiles,workingDir,nativeTarget?[]:_files.length>0?_files:void 0,result.testCases);let historyReport;if(!result.success&&result.totals&&result.totals.failed>0){if(historyReport=analyzeFailures(workingDir),historyReport.quarantinedFailures.length>0)result.message=(result.message||"")+` | QUARANTINED (flaky): ${historyReport.quarantinedFailures.join(", ")}`;if(historyReport.failureClusters.length>0){let clusterSummary=historyReport.failureClusters.slice(0,3).map((c)=>`${c.classification}: ${c.rootCause.substring(0,80)}`).join("; ");result.message=`${result.message||""} | FAILURE ANALYSIS: ${clusterSummary}`}}if(graphFallbackReason&&result.message)result.message=`${result.message} (${graphFallbackReason})`;if(bail&&coverage&&result.message)result.message=`${result.message} (coverage may be incomplete: bail=true stopped early)`;return JSON.stringify(result,null,2)}}),_internals127={analyzeImpact,loadImpactMap,isCommandAvailable,existsSync:fs85.existsSync,readdirSync:fs85.readdirSync,readFileSync:fs85.readFileSync,bunSpawn,buildNativeTargetCommand,formatNativeHistoryTestFile,selectHistoryForAnalysis,AGGREGATE_TEST_NAME}});import*as fs86 from"node:fs";import*as path164 from"node:path";function formatSecretscanIncompletePaths(incompletePaths,maxEntries=3){let visible=incompletePaths.slice(0,maxEntries).map((entry)=>{return`${entry.path} (${entry.reason})`}),suffix=incompletePaths.length>maxEntries?` (+${incompletePaths.length-maxEntries} more)`:"";return`${visible.join("; ")}${suffix}`}function validateDirectoryPath(dir){if(!dir||typeof dir!=="string")throw Error("Directory path is required");if(dir.includes(".."))throw Error("Directory path must not contain path traversal sequences");let normalized=path164.normalize(dir);return path164.isAbsolute(normalized)?normalized:path164.resolve(normalized)}function validateTimeout(timeoutMs,defaultValue){if(timeoutMs===void 0)return defaultValue;if(typeof timeoutMs!=="number"||!Number.isFinite(timeoutMs))throw Error("Timeout must be a finite number");if(timeoutMs<=0)throw Error("Timeout must be greater than 0");if(timeoutMs<MIN_CHECK_TIMEOUT_MS)throw Error(`Timeout must be at least ${MIN_CHECK_TIMEOUT_MS}ms (5 seconds)`);if(timeoutMs>MAX_CHECK_TIMEOUT_MS)throw Error(`Timeout must not exceed ${MAX_CHECK_TIMEOUT_MS}ms (5 minutes)`);return timeoutMs}function getPackageVersion(dir){try{let packagePath=path164.join(dir,"package.json");if(fs86.existsSync(packagePath)){let content=fs86.readFileSync(packagePath,"utf-8");return JSON.parse(content).version??null}}catch{}return null}function getChangelogVersion(dir){try{let changelogPath=path164.join(dir,"CHANGELOG.md");if(fs86.existsSync(changelogPath)){let match=fs86.readFileSync(changelogPath,"utf-8").match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);if(match)return match[1]}}catch{}return null}function getVersionFileVersion(dir){let possibleFiles=["VERSION.txt","version.txt","VERSION","version"];for(let file3 of possibleFiles){let filePath=path164.join(dir,file3);if(fs86.existsSync(filePath))try{let match=fs86.readFileSync(filePath,"utf-8").trim().match(/(\d+\.\d+\.\d+)/);if(match)return match[1]}catch{}}return null}async function runVersionCheck2(dir,_timeoutMs){let startTime=Date.now();try{let packageVersion=_internals128.getPackageVersion(dir),changelogVersion=_internals128.getChangelogVersion(dir),versionFileVersion=_internals128.getVersionFileVersion(dir),versions3=[];if(packageVersion)versions3.push(`package.json: ${packageVersion}`);if(changelogVersion)versions3.push(`CHANGELOG.md: ${changelogVersion}`);if(versionFileVersion)versions3.push(`version file: ${versionFileVersion}`);if(new Set([packageVersion,changelogVersion,versionFileVersion].filter(Boolean)).size<=1){if(versions3.length===0)return{type:"version",status:"skip",message:"No version information found to check",details:{},durationMs:Date.now()-startTime};return{type:"version",status:"pass",message:`Version consistent: ${versions3.join(", ")}`,details:{packageVersion,changelogVersion,versionFileVersion},durationMs:Date.now()-startTime}}return{type:"version",status:"fail",message:`Version mismatch: ${versions3.join("; ")}`,details:{packageVersion,changelogVersion,versionFileVersion},durationMs:Date.now()-startTime}}catch(error93){return{type:"version",status:"error",message:`Version check failed: ${error93 instanceof Error?error93.message:String(error93)}`,durationMs:Date.now()-startTime}}}async function runLintCheck(dir,linter,timeoutMs){let startTime=Date.now();try{let lintPromise=runLint(linter,"check",dir),timeoutId,timeoutPromise=new Promise((_,reject)=>{timeoutId=setTimeout(()=>{reject(Error(`Lint check timed out after ${timeoutMs}ms`))},timeoutMs)}),result=await Promise.race([lintPromise,timeoutPromise]).finally(()=>clearTimeout(timeoutId));if(!result.success)return{type:"lint",status:"error",message:result.error??"Lint check failed",details:{linter,success:result.success},durationMs:Date.now()-startTime};if(result.exitCode!==0){let issueMatch=result.output.match(/(\d+)\s+(issues?|errors?)/i),issueCount=issueMatch?parseInt(issueMatch[1],10):void 0;return{type:"lint",status:"fail",message:issueCount?`Lint found ${issueCount} issue(s)`:"Lint found issues",details:{linter,exitCode:result.exitCode,issueCount,hasOutput:result.output.length>0},durationMs:Date.now()-startTime}}return{type:"lint",status:"pass",message:"Lint check passed",details:{linter,exitCode:result.exitCode},durationMs:Date.now()-startTime}}catch(error93){if(error93 instanceof Error&&error93.message.includes("timed out"))return{type:"lint",status:"error",message:error93.message,details:{linter},durationMs:Date.now()-startTime};return{type:"lint",status:"error",message:`Lint check failed: ${error93 instanceof Error?error93.message:String(error93)}`,details:{linter},durationMs:Date.now()-startTime}}}async function runTestsCheck(_dir,scope,timeoutMs){let startTime=Date.now();try{let result=await runTests("none",scope,[],!1,timeoutMs,_dir,!1);if(!result.success)return{type:"tests",status:"error",message:result.error??"Tests check failed",details:{framework:result.framework,scope,success:result.success},durationMs:Date.now()-startTime};if(result.totals.failed>0)return{type:"tests",status:"fail",message:`Tests failed: ${result.totals.failed}/${result.totals.total} failed`,details:{framework:result.framework,scope,totals:result.totals},durationMs:Date.now()-startTime};if(result.totals.total===0)return{type:"tests",status:"skip",message:"No tests found to run",details:{framework:result.framework,scope},durationMs:Date.now()-startTime};return{type:"tests",status:"pass",message:`Tests passed: ${result.totals.passed} passed`,details:{framework:result.framework,scope,totals:result.totals},durationMs:Date.now()-startTime}}catch(error93){if(error93 instanceof Error&&(error93.message.includes("timeout")||error93.message.includes("ETIMEDOUT")))return{type:"tests",status:"error",message:`Tests check timed out after ${timeoutMs}ms`,durationMs:Date.now()-startTime};return{type:"tests",status:"error",message:`Tests check failed: ${error93 instanceof Error?error93.message:String(error93)}`,durationMs:Date.now()-startTime}}}async function runSecretsCheck(dir,timeoutMs){let startTime=Date.now();try{let secretsPromise=_internals128.runSecretscan(dir),timeoutPromise=new Promise((_,reject)=>{setTimeout(()=>{reject(Error(`Secrets check timed out after ${timeoutMs}ms`))},timeoutMs)}),result=await Promise.race([secretsPromise,timeoutPromise]);if("error"in result)return{type:"secrets",status:"fail",message:`Secrets check failed: ${result.error}`,details:{error:result.error,filesScanned:result.files_scanned,incompleteFiles:0,incompletePaths:[]},durationMs:Date.now()-startTime};let findingsCount=Math.max(result.count,result.findings.length);if(typeof result.incomplete_files!=="number"||!Array.isArray(result.incomplete_paths))return{type:"secrets",status:"fail",message:"Secrets check failed: scanner returned incomplete coverage metadata",details:{filesScanned:result.files_scanned},durationMs:Date.now()-startTime};let{incomplete_files:incompleteFiles,incomplete_paths:incompletePaths}=result,hasCountMismatch=result.count!==result.findings.length,hasIncompleteCoverage=incompleteFiles>0||incompletePaths.length>0,hasZeroCoverage=result.files_scanned===0,failures=[];if(findingsCount>0){let critical=result.findings.filter((f)=>f.severity==="critical").length,high=result.findings.filter((f)=>f.severity==="high").length;failures.push(`Found ${findingsCount} secret(s): ${critical} critical, ${high} high`)}if(hasIncompleteCoverage){let incompleteSummary=incompletePaths.length>0?`; incomplete paths: ${formatSecretscanIncompletePaths(incompletePaths)}`:"";failures.push(`${incompleteFiles} incomplete file(s)${incompleteSummary}`)}if(hasCountMismatch)failures.push(`findings/count mismatch (reported ${result.count}, actual ${result.findings.length})`);if(hasZeroCoverage)failures.push("zero requested files scanned");if(failures.length>0)return{type:"secrets",status:"fail",message:`Secrets check failed: ${failures.join("; ")}`,details:{count:findingsCount,reportedCount:result.count,critical:result.findings.filter((f)=>f.severity==="critical").length,high:result.findings.filter((f)=>f.severity==="high").length,filesScanned:result.files_scanned,skippedFiles:result.skipped_files,incompleteFiles,incompletePaths},durationMs:Date.now()-startTime};return{type:"secrets",status:"pass",message:"No secrets detected",details:{filesScanned:result.files_scanned,skippedFiles:result.skipped_files,incompleteFiles,incompletePaths},durationMs:Date.now()-startTime}}catch(error93){if(error93 instanceof Error&&error93.name==="AbortError")return{type:"secrets",status:"error",message:`Secrets check timed out after ${timeoutMs}ms`,durationMs:Date.now()-startTime};return{type:"secrets",status:"error",message:`Secrets check failed: ${error93 instanceof Error?error93.message:String(error93)}`,durationMs:Date.now()-startTime}}}async function runEvidenceCheck(dir){let startTime=Date.now();try{let plan=await loadPlan(dir);if(!plan)return{type:"evidence",status:"skip",message:"No plan found to check evidence against",details:{},durationMs:Date.now()-startTime};let completedTaskIds=[];for(let phase of plan.phases)for(let task of phase.tasks)if(task.status==="completed")completedTaskIds.push(task.id);if(completedTaskIds.length===0)return{type:"evidence",status:"skip",message:"No completed tasks yet",details:{completedTasks:0},durationMs:Date.now()-startTime};let evidenceTaskIds=new Set(await listEvidenceTaskIds(dir)),missingEvidence=[];for(let id of completedTaskIds){let gateStatus=await getDurableGateEvidenceStatusForTask(dir,id);if(gateStatus.isComplete)continue;if(gateStatus.evidenceExists&&gateStatus.missingGates.length>0){missingEvidence.push(id);continue}if(evidenceTaskIds.has(id))continue;missingEvidence.push(id)}let completedWithEvidence=completedTaskIds.length-missingEvidence.length;if(missingEvidence.length>0)return{type:"evidence",status:"fail",message:`${missingEvidence.length} completed task(s) missing evidence`,details:{totalCompleted:completedTaskIds.length,totalWithEvidence:completedWithEvidence,missingTasks:missingEvidence.slice(0,10),missingCount:missingEvidence.length},durationMs:Date.now()-startTime};return{type:"evidence",status:"pass",message:`All ${completedTaskIds.length} completed tasks have evidence`,details:{totalCompleted:completedTaskIds.length,totalWithEvidence:completedWithEvidence},durationMs:Date.now()-startTime}}catch(error93){return{type:"evidence",status:"error",message:`Evidence check failed: ${error93 instanceof Error?error93.message:String(error93)}`,durationMs:Date.now()-startTime}}}async function runRequirementCoverageCheck(dir,currentPhase){let startTime=Date.now();try{if(readEffectiveSpecSync(dir)===null)return{type:"req_coverage",status:"skip",message:"No effective spec found, requirement coverage not required",details:{},durationMs:Date.now()-startTime};let coverage=await checkRequirementCoverage(currentPhase,dir);if(coverage.exists)return{type:"req_coverage",status:"pass",message:"Requirement coverage report found",details:{path:coverage.path},durationMs:Date.now()-startTime};return{type:"req_coverage",status:"fail",message:"Requirement coverage report missing but effective spec exists",details:{expectedPath:coverage.path},durationMs:Date.now()-startTime}}catch(error93){return{type:"req_coverage",status:"error",message:`Requirement coverage check failed: ${error93 instanceof Error?error93.message:String(error93)}`,durationMs:Date.now()-startTime}}}async function runPreflight(dir,phase,config3){let startTime=Date.now(),reportId=`preflight-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,validatedDir;try{validatedDir=_internals128.validateDirectoryPath(dir)}catch(error93){return{id:reportId,timestamp:startTime,phase,overall:"fail",checks:[{type:"lint",status:"error",message:`Invalid directory: ${error93 instanceof Error?error93.message:String(error93)}`}],totalDurationMs:Date.now()-startTime,message:"Preflight aborted: invalid directory"}}let validatedTimeout;try{validatedTimeout=_internals128.validateTimeout(config3?.checkTimeoutMs,DEFAULT_CONFIG.checkTimeoutMs)}catch(error93){return{id:reportId,timestamp:startTime,phase,overall:"fail",checks:[{type:"lint",status:"error",message:`Invalid config: ${error93 instanceof Error?error93.message:String(error93)}`}],totalDurationMs:Date.now()-startTime,message:"Preflight aborted: invalid configuration"}}let cfg={checkTimeoutMs:validatedTimeout,skipTests:config3?.skipTests??DEFAULT_CONFIG.skipTests,skipSecrets:config3?.skipSecrets??DEFAULT_CONFIG.skipSecrets,skipEvidence:config3?.skipEvidence??DEFAULT_CONFIG.skipEvidence,skipVersion:config3?.skipVersion??DEFAULT_CONFIG.skipVersion,testScope:config3?.testScope??DEFAULT_CONFIG.testScope,linter:config3?.linter??DEFAULT_CONFIG.linter};log("[Preflight] Starting preflight checks",{reportId,phase,config:{skipTests:cfg.skipTests,skipSecrets:cfg.skipSecrets,skipEvidence:cfg.skipEvidence,skipVersion:cfg.skipVersion,testScope:cfg.testScope,linter:cfg.linter}});let checks5=[];log("[Preflight] Running lint check...");let lintResult=await _internals128.runLintCheck(validatedDir,cfg.linter,cfg.checkTimeoutMs);if(checks5.push(lintResult),log(`[Preflight] Lint check: ${lintResult.status} ${lintResult.message}`),!cfg.skipTests){log("[Preflight] Running tests check...");let testsResult=await _internals128.runTestsCheck(validatedDir,cfg.testScope,cfg.checkTimeoutMs);checks5.push(testsResult),log(`[Preflight] Tests check: ${testsResult.status} ${testsResult.message}`)}else checks5.push({type:"tests",status:"skip",message:"Tests check skipped by configuration"});if(!cfg.skipSecrets){log("[Preflight] Running secrets check...");let secretsResult=await _internals128.runSecretsCheck(validatedDir,cfg.checkTimeoutMs);checks5.push(secretsResult),log(`[Preflight] Secrets check: ${secretsResult.status} ${secretsResult.message}`)}else checks5.push({type:"secrets",status:"skip",message:"Secrets check skipped by configuration"});if(!cfg.skipEvidence){log("[Preflight] Running evidence check...");let evidenceResult=await _internals128.runEvidenceCheck(validatedDir);checks5.push(evidenceResult),log(`[Preflight] Evidence check: ${evidenceResult.status} ${evidenceResult.message}`)}else checks5.push({type:"evidence",status:"skip",message:"Evidence check skipped by configuration"});log("[Preflight] Running requirement coverage check...");let reqCoverageResult=await _internals128.runRequirementCoverageCheck(validatedDir,phase);if(checks5.push(reqCoverageResult),log(`[Preflight] Requirement coverage check: ${reqCoverageResult.status} ${reqCoverageResult.message}`),!cfg.skipVersion){log("[Preflight] Running version check...");let versionResult=await _internals128.runVersionCheck(validatedDir,cfg.checkTimeoutMs);checks5.push(versionResult),log(`[Preflight] Version check: ${versionResult.status} ${versionResult.message}`)}else checks5.push({type:"version",status:"skip",message:"Version check skipped by configuration"});let totalDurationMs=Date.now()-startTime,failedChecks=checks5.filter((c)=>c.status==="fail").length,errorChecks=checks5.filter((c)=>c.status==="error").length,skippedChecks=checks5.filter((c)=>c.status==="skip").length,overall,message;if(errorChecks>0)overall="fail",message=`Preflight failed with ${errorChecks} error(s)`;else if(failedChecks>0)overall="fail",message=`Preflight failed: ${failedChecks} check(s) failed`;else if(skippedChecks===checks5.length)overall="skipped",message="All checks were skipped";else overall="pass",message="Preflight passed all checks";return log(`[Preflight] Complete: ${overall} ${message}`),{id:reportId,timestamp:startTime,phase,overall,checks:checks5,totalDurationMs,message}}function formatPreflightMarkdown(report){let lines=["## Preflight Report","",`**Phase**: ${report.phase}`,`**Overall**: ${report.overall==="pass"?"✅ PASS":report.overall==="fail"?"❌ FAIL":"⏭️ SKIPPED"}`,`**Duration**: ${(report.totalDurationMs/1000).toFixed(2)}s`,"","### Checks",""];for(let check3 of report.checks){let icon=check3.status==="pass"?"✅":check3.status==="fail"?"❌":check3.status==="error"?"⚠️":"⏭️";lines.push(`- ${icon} **${check3.type}**: ${check3.message}`)}return lines.push(""),lines.push(report.message),lines.join(`
|
|
2052
2052
|
`)}async function handlePreflightCommand(directory,_args){let phase=(await loadPlan(directory))?.current_phase??1,report=await _internals128.runPreflight(directory,phase);return _internals128.formatPreflightMarkdown(report)}var MIN_CHECK_TIMEOUT_MS=5000,MAX_CHECK_TIMEOUT_MS=300000,DEFAULT_CONFIG,_internals128;var init_preflight_service=__esm(()=>{init_gate_bridge();init_manager2();init_manager();init_effective_spec();init_lint();init_secretscan();init_test_runner();init_utils();DEFAULT_CONFIG={checkTimeoutMs:60000,skipTests:!1,skipSecrets:!1,skipEvidence:!1,skipVersion:!1,testScope:"convention",linter:"biome"};_internals128={runPreflight,formatPreflightMarkdown,handlePreflightCommand,validateDirectoryPath,validateTimeout,getPackageVersion,getChangelogVersion,getVersionFileVersion,runVersionCheck:runVersionCheck2,runLintCheck,runTestsCheck,runSecretscan,runSecretsCheck,runEvidenceCheck,runRequirementCoverageCheck}});var init_preflight=__esm(()=>{init_preflight_service()});function parsePromoteArgs(args2){let category,lessonId,lessonText,force=!1,reason,actionable={};for(let i=0;i<args2.length;i++){let arg=args2[i],actionabilityField=ACTIONABILITY_LIST_FLAGS.get(arg);if(arg==="--category"&&i+1<args2.length)category=args2[i+1],i++;else if(arg==="--from-swarm"&&i+1<args2.length)lessonId=args2[i+1],i++;else if(arg==="--force")force=!0;else if(arg==="--reason"&&i+1<args2.length)reason=args2[i+1],i++;else if(actionabilityField!==void 0&&i+1<args2.length){let supplied=args2[i+1].split(",").map((v)=>v.trim()).filter((v)=>v.length>0);actionable[actionabilityField]=dedupeCapped([...actionable[actionabilityField]??[],...supplied],{cap:ACTIONABILITY_FIELD_CAP}),i++}else if(!arg.startsWith("--")){lessonText=args2.slice(i).join(" ");break}}return{category,lessonId,lessonText,force,reason,actionable}}async function handlePromoteCommand(directory,args2){let{category,lessonId,lessonText,force,reason,actionable}=parsePromoteArgs(args2);if(!lessonText&&!lessonId)return`Usage: /swarm promote "<lesson text>" or /swarm promote --from-swarm <id>
|
|
2053
2053
|
Options: --category <cat>, --force --reason "<why>" (audited policy override)
|
|
2054
2054
|
Actionability (direct text only; required unless knowledge.promotion_require_actionable=false):
|
|
@@ -5510,8 +5510,8 @@ RULES:
|
|
|
5510
5510
|
- Match language and test framework:
|
|
5511
5511
|
TypeScript/JavaScript → bun:test (import { describe, test, expect, mock, beforeEach, afterEach } from 'bun:test')
|
|
5512
5512
|
Python → pytest (name files test_<name>.py or <name>_test.py)
|
|
5513
|
-
Go → go test (name files <name>_test.go, same package) — run one exact test with { scope: "target", native_target: { framework: "go-test", name: "TestName[/Subtest]", path: "relative/package" } }
|
|
5514
|
-
CMake/CTest → run one exact configured test with { scope: "target", native_target: { framework: "ctest", name: "ExactTestName", path: "relative/build-dir" } }
|
|
5513
|
+
Go → go test (name files <name>_test.go, same package) — run one exact test with { scope: "target", native_target: { framework: "go-test", name: "TestName[/Subtest]", path: "relative/package" } }; or pass target names in the \`targets\` array for broader pattern matching
|
|
5514
|
+
CMake/CTest → run one exact configured test with { scope: "target", native_target: { framework: "ctest", name: "ExactTestName", path: "relative/build-dir" } }; or pass target patterns in the \`targets\` array
|
|
5515
5515
|
PowerShell → Pester (name files <name>.Tests.ps1)
|
|
5516
5516
|
Ruby → RSpec (name files <name>_spec.rb)
|
|
5517
5517
|
Java/Kotlin → JUnit 5 (name files <Name>Test.java / <Name>Test.kt)
|
|
@@ -5534,16 +5534,16 @@ EXECUTION BOUNDARY:
|
|
|
5534
5534
|
- scope: "all" is PROHIBITED for test_engineer — full-suite output can destabilize opencode's SSE streaming, and the architect handles regression sweeps separately via scope: "graph"
|
|
5535
5535
|
- If you need to verify tests beyond your assigned file, report the concern in your VERDICT and the architect will handle it
|
|
5536
5536
|
- If you wrote tests/foo.test.ts for src/foo.ts, you MUST run only tests/foo.test.ts
|
|
5537
|
-
- The test_runner convention scope recognises direct test files in supported locations/naming conventions: Python (test_*.py, *_test.py), Ruby (*_spec.rb), Java/Kotlin (*Test.*), C# (*Tests.cs), and PowerShell (*.Tests.ps1). For Go and CTest, use scope "target" with an exact framework-native name; never broaden to a package/build sweep.
|
|
5537
|
+
- The test_runner convention scope recognises direct test files in supported locations/naming conventions: Python (test_*.py, *_test.py), Ruby (*_spec.rb), Java/Kotlin (*Test.*), C# (*Tests.cs), and PowerShell (*.Tests.ps1). For Go and CTest, use scope "target" with an exact framework-native name; never broaden to a package/build sweep. For target-based frameworks (cargo, maven, gradle, dotnet-test, swift-test), you may also pass framework-native test names or patterns in the \`targets\` array parameter alongside \`files\`.
|
|
5538
5538
|
|
|
5539
5539
|
TOOL USAGE:
|
|
5540
5540
|
- Use \`test_runner\` tool for test execution
|
|
5541
|
-
- ALWAYS identify exactly what you wrote: use \`files\` for file-targetable frameworks
|
|
5541
|
+
- ALWAYS identify exactly what you wrote: use \`files\` for file-targetable frameworks, \`native_target\` for exact Go/CTest targeting, or \`targets\` for framework-native test name patterns (cargo, maven, gradle, dotnet-test, swift-test, go-test, ctest)
|
|
5542
5542
|
- Use scope: "convention" to run a specific test file you wrote OR to let the runner map a source file to its test counterpart
|
|
5543
5543
|
- NEVER use scope: "all" (not allowed — too broad)
|
|
5544
5544
|
- Use scope: "graph" ONLY if convention finds zero test files (zero-match fallback)
|
|
5545
5545
|
- If framework detection returns none: No test framework detected — fall back to reporting SKIPPED with no retry
|
|
5546
|
-
- If
|
|
5546
|
+
- If test_runner says the framework does not support targeted test-file execution, report SKIPPED with that reason and do NOT retry with broader scope. (Did you forget to use \`targets\` or \`native_target\`?)
|
|
5547
5547
|
- Test files written for supported targeted frameworks can be passed directly as the files value; otherwise pass the source file so convention can discover sibling tests
|
|
5548
5548
|
|
|
5549
5549
|
INPUT SECURITY:
|
|
@@ -6415,7 +6415,7 @@ ${body}`)}function renderAdvisoryBody(result){return result.synthesis.trim()}var
|
|
|
6415
6415
|
`):"_No persisting disagreements after deliberation._",sourcesBlock=allSources.length>0?allSources.map((s)=>`- [${s.title||s.url}](${s.url})`).join(`
|
|
6416
6416
|
`):"_No sources cited._";return["## General Council Synthesis","",`**Question:** ${question}`,`**Mode:** ${mode}`,`**Members:**
|
|
6417
6417
|
${memberLines}`,`**Rounds:** ${roundsCompleted}`,"","### Consensus",consensusBlock,"","### Persistent Disagreements",disagreementsBlock,"","### Sources",sourcesBlock].join(`
|
|
6418
|
-
`)}function synthesizeGeneralCouncil(question,mode,round1Responses,round2Responses){let safeRound1=Array.isArray(round1Responses)?round1Responses:[],safeRound2=Array.isArray(round2Responses)?round2Responses:[],disagreements=detectDisagreements(safeRound1),consensusPoints=buildConsensusClusters(safeRound1),persistingDisagreements=computePersistingDisagreements(disagreements,safeRound2),allSources=dedupeSources(safeRound1,safeRound2),roundsCompleted=safeRound2.length>0?2:1,synthesis=renderSynthesisMarkdown(question,mode,roundsCompleted,safeRound1,consensusPoints,persistingDisagreements,allSources);return{question,mode,round1Responses:safeRound1,disagreements,round2Responses:safeRound2,synthesis,consensusPoints,persistingDisagreements:persistingDisagreements.map((d)=>d.topic),allSources,timestamp:new Date().toISOString()}}init_state2();init_logger();init_create_tool();init_resolve_working_directory();var WebSearchResultSchema=exports_external.object({title:exports_external.string(),url:exports_external.string(),snippet:exports_external.string(),query:exports_external.string()}),MemberRoleEnum=exports_external.enum(["generalist","skeptic","domain_expert","devil_advocate","synthesizer"]),Round1ResponseSchema=exports_external.object({memberId:exports_external.string().min(1),model:exports_external.string().min(1),role:MemberRoleEnum,response:exports_external.string(),sources:exports_external.array(WebSearchResultSchema).default([]),searchQueries:exports_external.array(exports_external.string()).default([]),confidence:exports_external.number().min(0).max(1),areasOfUncertainty:exports_external.array(exports_external.string()).default([]),durationMs:exports_external.number().nonnegative().default(0)}),Round2ResponseSchema=Round1ResponseSchema.extend({disagreementTopics:exports_external.array(exports_external.string()).default([])}),ArgsSchema2=exports_external.object({question:exports_external.string().min(1).max(8000),mode:exports_external.enum(["general","spec_review"]).default("general"),members:exports_external.array(exports_external.string()).default([]),round1Responses:exports_external.array(Round1ResponseSchema).min(1),round2Responses:exports_external.array(Round2ResponseSchema).optional(),working_directory:exports_external.string().optional()}),convene_general_council=createSwarmTool({description:"Synthesize responses from a multi-model General Council. Accepts parallel member responses (Round 1, optionally Round 2), detects disagreements, and returns consensus points, persisting disagreements, and a structured synthesis. Architect-only. Config-gated on council.general.enabled in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides.",args:{question:exports_external.string().min(1).max(8000).describe("The question put to the council, or the spec text to review."),mode:exports_external.enum(["general","spec_review"]).optional().describe('"general" for /swarm council or pre-save PLAN advisory; "spec_review" for manual /swarm council --spec-review.'),members:exports_external.array(exports_external.string()).optional().describe("Optional list of member IDs convened (for evidence/audit)."),round1Responses:exports_external.array(exports_external.object({memberId:exports_external.string().min(1),model:exports_external.string().min(1),role:exports_external.enum(["generalist","skeptic","domain_expert","devil_advocate","synthesizer"]),response:exports_external.string(),sources:exports_external.array(exports_external.object({title:exports_external.string(),url:exports_external.string(),snippet:exports_external.string(),query:exports_external.string()})).optional(),searchQueries:exports_external.array(exports_external.string()).optional(),confidence:exports_external.number().min(0).max(1),areasOfUncertainty:exports_external.array(exports_external.string()).optional(),durationMs:exports_external.number().nonnegative().optional()})).describe("Round 1 member responses (one per council member)."),round2Responses:exports_external.array(exports_external.object({memberId:exports_external.string().min(1),model:exports_external.string().min(1),role:exports_external.enum(["generalist","skeptic","domain_expert","devil_advocate","synthesizer"]),response:exports_external.string(),sources:exports_external.array(exports_external.object({title:exports_external.string(),url:exports_external.string(),snippet:exports_external.string(),query:exports_external.string()})).optional(),searchQueries:exports_external.array(exports_external.string()).optional(),confidence:exports_external.number().min(0).max(1),areasOfUncertainty:exports_external.array(exports_external.string()).optional(),durationMs:exports_external.number().nonnegative().optional(),disagreementTopics:exports_external.array(exports_external.string()).optional()})).optional().describe("Round 2 deliberation responses (omit when no deliberation has occurred)."),working_directory:exports_external.string().optional().describe("Project root for config + evidence path resolution.")},execute:async(args2,directory,ctx)=>{let parsed=ArgsSchema2.safeParse(args2);if(!parsed.success){let fail={success:!1,reason:"invalid_args",message:parsed.error.issues.map((i)=>`${i.path.join(".")}: ${i.message}`).join("; ")};return JSON.stringify(fail,null,2)}let input=parsed.data,dirResult=resolveWorkingDirectory(input.working_directory,directory);if(!dirResult.success){let fail={success:!1,reason:"invalid_working_directory",message:dirResult.message};return JSON.stringify(fail,null,2)}let workingDir=dirResult.directory,generalConfig=loadPluginConfig(workingDir).council?.general;if(!generalConfig||generalConfig.enabled!==!0)return JSON.stringify({success:!1,reason:"council_general_disabled",message:"convene_general_council requires council.general.enabled: true in the resolved config: global ~/.config/opencode/opencode-swarm.json or project .opencode/opencode-swarm.json."},null,2);let round1=input.round1Responses,round2=input.round2Responses??[],result=synthesizeGeneralCouncil(input.question,input.mode,round1,round2),evidenceDir=path253.join(workingDir,".swarm","council","general"),evidenceFile=`${result.timestamp.replace(/[:.]/g,"-")}-${input.mode}.json`,evidencePath=path253.join(evidenceDir,evidenceFile);try{await fs143.promises.mkdir(evidenceDir,{recursive:!0}),await fs143.promises.writeFile(evidencePath,JSON.stringify(result,null,2))}catch(err){let message=err instanceof Error?err.message:String(err);log(`[convene_general_council] Failed to write evidence to ${evidencePath}: ${message}`)}try{let sessionID=ctx?.sessionID;if(sessionID){let session=getAgentSession(sessionID);if(session)pushGeneralCouncilAdvisory(session,result)}}catch{}let ok={success:!0,question:input.question,mode:input.mode,roundsCompleted:round2.length>0?2:1,consensusPoints:result.consensusPoints,disagreementsCount:result.disagreements.length,persistingDisagreements:result.persistingDisagreements,allSourcesCount:result.allSources.length,synthesis:result.synthesis,evidencePath};return JSON.stringify(ok,null,2)}});init_zod();init_config();init_schema();init_curator();init_curator();init_curator_llm_factory();init_review_receipt();init_utils2();init_create_tool();var curator_analyze=createSwarmTool({description:"Run curator phase analysis and optionally apply knowledge recommendations. Call this after reviewing a phase to apply knowledge updates. If recommendations is provided, applies them via applyCuratorKnowledgeUpdates.",args:{phase:exports_external.number().int().min(1).describe("Phase number to analyze"),recommendations:exports_external.array(exports_external.object({action:exports_external.enum(["promote","archive","flag_contradiction","rewrite"]),entry_id:exports_external.string().optional(),lesson:exports_external.string(),reason:exports_external.string(),category:exports_external.enum(["process","architecture","tooling","security","testing","debugging","performance","integration","other"]).optional(),confidence:exports_external.number().min(0).max(1).optional()})).optional().describe("Knowledge recommendations to apply. If omitted, only collects digest data.")},execute:async(args2,directory,ctx)=>{let typedArgs=args2;try{if(!Number.isInteger(typedArgs.phase)||typedArgs.phase<1)return JSON.stringify({error:"phase must be a positive integer >= 1"},null,2);if(typedArgs.recommendations){let validActions=["promote","archive","flag_contradiction","rewrite"];for(let rec of typedArgs.recommendations)if(!validActions.includes(rec.action))return JSON.stringify({error:`Invalid recommendation action: ${rec.action}`},null,2)}if(typedArgs.recommendations){let UUID_V42=/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;for(let rec of typedArgs.recommendations)if(rec.entry_id!==void 0&&!UUID_V42.test(rec.entry_id))return JSON.stringify({error:`Invalid entry_id '${rec.entry_id}': must be a UUID v4 or omitted. Use undefined/omit entry_id to create a new entry.`},null,2)}let{config:config3}=loadPluginConfigWithMeta(directory),curatorConfig=CuratorConfigSchema.parse(config3.curator??{}),knowledgeConfig=KnowledgeConfigSchema.parse(config3.knowledge??{}),agentsDispatched=[];try{let eventsContent=await readSwarmFileAsync(directory,"events.jsonl");if(eventsContent){let phaseEvents=filterPhaseEvents(eventsContent,typedArgs.phase),agentSet=new Set;for(let evt of phaseEvents){let record3=evt;if(typeof record3.agent==="string"&&record3.agent.length>0)agentSet.add(record3.agent);if(Array.isArray(record3.agents_dispatched)){for(let a of record3.agents_dispatched)if(typeof a==="string")agentSet.add(a)}}agentsDispatched=Array.from(agentSet).sort()}}catch{}let llmDelegate=createCuratorLLMDelegate(directory,"phase",ctx?.sessionID),curatorResult=await runCuratorPhase(directory,typedArgs.phase,agentsDispatched,curatorConfig,{},llmDelegate);{let scopeContent=curatorResult.digest?.summary??`Phase ${typedArgs.phase} curator analysis`,complianceWarnings=curatorResult.compliance.filter((c)=>c.severity==="warning"),receipt=complianceWarnings.length>0?buildRejectedReceipt({agent:"curator",scopeContent,scopeDescription:"phase-digest",blockingFindings:complianceWarnings.map((c)=>({location:`phase-${c.phase}`,summary:c.description,severity:c.type==="missing_reviewer"?"high":"medium"})),evidenceReferences:[],passConditions:["resolve all compliance warnings before phase completion"]}):buildApprovedReceipt({agent:"curator",scopeContent,scopeDescription:"phase-digest",checkedAspects:["phase_compliance","knowledge_recommendations","phase_digest"],validatedClaims:[`phase: ${typedArgs.phase}`,`knowledge_recommendations: ${curatorResult.knowledge_recommendations.length}`]});persistReviewReceipt(directory,receipt).catch(()=>{})}let applied=0,skipped=0;if(typedArgs.recommendations&&typedArgs.recommendations.length>0){let result=await applyCuratorKnowledgeUpdates(directory,typedArgs.recommendations,knowledgeConfig);applied=result.applied,skipped=result.skipped}return JSON.stringify({phase_digest:curatorResult.digest,compliance_count:curatorResult.compliance.length,applied,skipped},null,2)}catch(error93){return JSON.stringify({error:error93 instanceof Error?error93.message:String(error93),phase:typedArgs.phase},null,2)}}});init_zod();init_loader();init_create_tool();init_resolve_working_directory();var CriteriaItemSchema=exports_external.object({id:exports_external.string().min(1).max(20).regex(/^C\d+$/,'Criterion id must match C\\d+ (e.g. "C1", "C12")'),description:exports_external.string().min(10).max(500),mandatory:exports_external.boolean()}),ArgsSchema3=exports_external.object({taskId:exports_external.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/,"Task ID must be in N.M or N.M.P format"),criteria:exports_external.array(CriteriaItemSchema).min(1).max(20),working_directory:exports_external.string().optional()}),declare_council_criteria=createSwarmTool({description:"Pre-declare acceptance criteria for a task before the coder starts work. Criteria are persisted under .swarm/council/ and read back during council evaluation so reviewers assess a stable, pre-committed contract. Architect-only. Config-gated via council.enabled.",args:{taskId:exports_external.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/,"Task ID must be in N.M or N.M.P format").describe('Task ID for which criteria are declared, e.g. "1.1", "1.2.3"'),criteria:exports_external.array(exports_external.object({id:exports_external.string().min(1).max(20).regex(/^C\d+$/,"Criterion id must match C\\d+").describe('Criterion identifier, e.g. "C1", "C12"'),description:exports_external.string().min(10).max(500).describe("Human-readable description of the criterion"),mandatory:exports_external.boolean().describe("Whether the criterion is mandatory. Mandatory criteria block APPROVE when unmet.")})).min(1).max(20).describe("Array of acceptance criteria items. Must contain between 1 and 20 entries with unique ids."),working_directory:exports_external.string().optional().describe("Explicit project root directory. When provided, .swarm/council/ is resolved relative to this path instead of the plugin context directory.")},async execute(args2,directory){let parsed=ArgsSchema3.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,reason:"invalid arguments",errors:parsed.error.issues.map((i)=>({path:i.path.join("."),message:i.message}))},null,2);let input=parsed.data,dirResult=resolveWorkingDirectory(input.working_directory,directory);if(!dirResult.success)return JSON.stringify({success:!1,reason:dirResult.message},null,2);let workingDir=dirResult.directory;if(!loadPluginConfig(workingDir).council?.enabled)return JSON.stringify({success:!1,reason:"council feature is disabled — set council.enabled: true in .opencode/opencode-swarm.json to enable"},null,2);let ids=input.criteria.map((c)=>c.id);if(new Set(ids).size<ids.length){let seen=new Set,duplicates=[];for(let id of ids){if(seen.has(id)&&!duplicates.includes(id))duplicates.push(id);seen.add(id)}return JSON.stringify({success:!1,reason:"duplicate criterion ids",errors:duplicates},null,2)}let replaced=readCriteria(workingDir,input.taskId)!==null;return await writeCriteria(workingDir,input.taskId,input.criteria),JSON.stringify({success:!0,taskId:input.taskId,criteriaCount:input.criteria.length,mandatoryCount:input.criteria.filter((c)=>c.mandatory).length,declaredAt:new Date().toISOString(),replaced},null,2)}});init_zod();init_config();init_plan_schema();init_file_authority();init_path_identity();init_scope_binding();init_scope_persistence();init_state2();init_project_boundary();init_task_id();init_create_tool();import*as fs144 from"node:fs";import*as path254 from"node:path";function validateTaskIdFormat2(taskId){return validateTaskIdFormat(taskId)}function validateFiles(files){let errors5=[],totalBytes=0;for(let file3 of files){if(file3.includes("\x00")){errors5.push(`Invalid file "${file3}": null bytes are not allowed`);continue}let unsafeReason=unsafePathTextReason(file3);if(unsafeReason){errors5.push(`Invalid file path: ${unsafeReason}`);continue}if(file3.replace(/\\/g,"/").split("/").includes(".."))errors5.push(`Invalid file "${file3}": path traversal sequences (..) are not allowed`);let bytes=Buffer.byteLength(file3,"utf8");if(totalBytes+=bytes,bytes>MAX_SCOPE_PATH_BYTES)errors5.push(`Invalid file "${file3}": path exceeds maximum length of ${MAX_SCOPE_PATH_BYTES} UTF-8 bytes`)}if(totalBytes>MAX_SCOPE_FILES_BYTES)errors5.push(`Invalid scope: file paths exceed the aggregate limit of ${MAX_SCOPE_FILES_BYTES} UTF-8 bytes`);return errors5}async function executeDeclareScope(args2,fallbackDir,owner,authorityConfig){let taskIdError=validateTaskIdFormat2(args2.taskId);if(taskIdError)return{success:!1,message:"Validation failed",errors:[taskIdError]};if(!Array.isArray(args2.files)||args2.files.length===0)return{success:!1,message:"Validation failed",errors:["files must be a non-empty array"]};let fileErrors=validateFiles(args2.files);if(fileErrors.length>0)return{success:!1,message:"Validation failed",errors:fileErrors};if(args2.whitelist){let whitelistErrors=validateFiles(args2.whitelist);if(whitelistErrors.length>0)return{success:!1,message:"Validation failed",errors:whitelistErrors}}let normalizedDir;if(args2.working_directory!=null&&args2.working_directory.trim()!==""){if(args2.working_directory.includes("\x00"))return{success:!1,message:"Invalid working_directory: null bytes are not allowed",errors:["Invalid working_directory: null bytes are not allowed"]};if(/^\\\\|^(NUL|CON|AUX|COM[1-9]|LPT[1-9])(\..*)?$/i.test(args2.working_directory))return{success:!1,message:"Invalid working_directory: Windows device paths are not allowed",errors:["Invalid working_directory: Windows device paths are not allowed"]};if(normalizedDir=path254.normalize(args2.working_directory),normalizedDir.split(path254.sep).includes(".."))return{success:!1,message:"Invalid working_directory: path traversal sequences (..) are not allowed",errors:["Invalid working_directory: path traversal sequences (..) are not allowed"]};let resolvedDir=path254.resolve(normalizedDir);try{let realPath=fs144.realpathSync(resolvedDir),planPath2=path254.join(realPath,".swarm","plan.json");if(!fs144.existsSync(planPath2))return{success:!1,message:`Invalid working_directory: plan not found in "${realPath}"`,errors:[`Invalid working_directory: plan not found in "${realPath}"`]}}catch{return{success:!1,message:`Invalid working_directory: path "${resolvedDir}" does not exist or is inaccessible`,errors:[`Invalid working_directory: path "${resolvedDir}" does not exist or is inaccessible`]}}if(normalizedDir&&fallbackDir)try{let canonicalWorkingDir=fs144.realpathSync(path254.resolve(normalizedDir)),canonicalProjectRoot=fs144.realpathSync(path254.resolve(fallbackDir));if(isStrictPathDescendant(canonicalWorkingDir,canonicalProjectRoot)&&!hasExplicitProjectBoundary(canonicalWorkingDir))return{success:!1,message:`working_directory "${normalizedDir}" is a subdirectory of the project root. Use the project root "${fallbackDir}" instead.`,errors:[`Subdirectory working_directory not allowed — use project root "${fallbackDir}"`]}}catch{}}if(!normalizedDir&&!fallbackDir)return{success:!1,message:"Cannot resolve project directory",errors:["Provide working_directory or ensure the tool is invoked from a project root"]};let directory=normalizedDir||fallbackDir,planPath=path254.resolve(directory,".swarm","plan.json");if(!fs144.existsSync(planPath))return{success:!1,message:"No plan found",errors:["plan.json not found"]};let rawPlanContent;try{rawPlanContent=JSON.parse(fs144.readFileSync(planPath,"utf-8"))}catch{return{success:!1,message:"Failed to parse plan.json",errors:["plan.json is not valid JSON"]}}let parsedPlan=PlanSchema.safeParse(rawPlanContent);if(!parsedPlan.success)return{success:!1,message:"Failed to validate plan.json",errors:["plan.json does not match the supported plan schema"]};let planContent=parsedPlan.data,allTasks=planContent.phases?.flatMap((p)=>p.tasks??[])??[];if(!allTasks.some((t)=>t.id===args2.taskId))return{success:!1,message:`Task ${args2.taskId} not found in plan`,errors:[`Task ${args2.taskId} does not exist in plan.json`]};let taskInPlan=allTasks.find((t)=>t.id===args2.taskId);if(taskInPlan&&taskInPlan.status==="completed")return{success:!1,message:`Task ${args2.taskId} is already completed`,errors:[`Cannot declare scope for completed task ${args2.taskId}`]};let rawMergedFiles=[...args2.files,...args2.whitelist??[]],warnings=[],normalizeErrors=[],dir=directory,mergedFiles=rawMergedFiles.map((file3)=>{if(path254.isAbsolute(file3)){let relativePath2=path254.relative(dir,file3).replace(/\\/g,"/");if(relativePath2.startsWith(".."))return normalizeErrors.push(`Path '${file3}' resolves outside the project directory`),file3;return warnings.push(`Absolute path normalized to relative: '${relativePath2}' (was '${file3}')`),relativePath2}return file3});if(normalizeErrors.length>0)return{success:!1,message:"Validation failed",errors:normalizeErrors};let lstatErrors=[];for(let file3 of mergedFiles){let block=checkWriteTargetForSymlink(file3,dir);if(block)lstatErrors.push(block)}if(lstatErrors.length>0)return{success:!1,message:"Scope contains symlink-backed paths",errors:lstatErrors};let authorityErrors=[];for(let file3 of mergedFiles){let decision=checkFileAuthority("coder",file3,dir,authorityConfig,{declaredScope:[file3]});if(!decision.allowed)authorityErrors.push(decision.reason)}if(authorityErrors.length>0)return{success:!1,message:"Scope denied by effective coder authority",errors:authorityErrors};if(owner?.sessionID&&owner.messageID){let binding=createScopeBinding({directory:dir,plan:planContent,taskId:args2.taskId,files:mergedFiles,ownerSessionId:owner.sessionID,ownerMessageId:owner.messageID,source:"declare_scope"});if(!binding)return{success:!1,message:"Failed to bind scope to the calling session",errors:["Scope identity could not be validated"]};let persistence=await replaceExistingScopeDeclaration({directory:dir,binding,replaceExisting:args2.replace_existing??!1});if(!persistence.ok)return{success:!1,message:"Failed to persist scope declaration",errors:[`${persistence.code}: ${persistence.message}`]};let session=ensureAgentSession(owner.sessionID,owner.agentName??"architect",dir);session.declaredCoderScope=mergedFiles,session.lastScopeViolation=null}return warnings.push("SCOPE ENFORCEMENT: This declaration is bound to the caller session and current plan. Direct writes and statically detected shell/interpreter writes must stay inside the active Task-correlated scope; missing or unverifiable coder write authority fails closed with SCOPE_NOT_DECLARED or SCOPE_VIOLATION."),{success:!0,message:"Scope declared successfully",taskId:args2.taskId,fileCount:mergedFiles.length,warnings}}var declare_scope=createSwarmTool({description:"Declare the file scope for the next coder delegation. Sets the list of files the coder is permitted to modify for a specific task. Must be called before delegating to coder to enable scope containment checking.",args:{taskId:exports_external.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/,"Task ID must be in N.M or N.M.P format").describe('Task ID for which scope is being declared, e.g. "1.1", "1.2.3"'),files:exports_external.array(exports_external.string().min(1).max(4096)).min(1).describe("Array of file paths the coder is permitted to modify"),whitelist:exports_external.array(exports_external.string().min(1).max(4096)).optional().describe("Additional file paths to whitelist (merged with files)"),replace_existing:exports_external.boolean().optional().describe("Set true to atomically revoke and replace this session's existing live declaration for the same task"),working_directory:exports_external.string().optional().describe("Working directory where the plan is located")},execute:async(args2,_directory,ctx)=>{let{config:config3}=loadPluginConfigWithMeta(_directory);return JSON.stringify(await executeDeclareScope(args2,_directory,{sessionID:ctx?.sessionID??"",messageID:ctx?.messageID??"",agentName:ctx?.agent},config3.authority),null,2)}});init_zod();import*as child_process12 from"node:child_process";import*as fs145 from"node:fs";import*as path255 from"node:path";init_create_tool();var MAX_DIFF_LINES=500,DIFF_TIMEOUT_MS=30000,MAX_BUFFER_BYTES=5242880,MAX_AST_FILES=50,CONTRACT_PATTERNS=[/^[+-]\s*export\s+(function|const|class|interface|type|enum|default)\b/,/^[+-]\s*(interface|type)\s+\w+/,/^[+-]\s*public\s+/,/^[+-]\s*(async\s+)?function\s+\w+\s*\(/],SAFE_REF_PATTERN=/^[a-zA-Z0-9._\-/~^@{}]+$/,MAX_REF_LENGTH2=256,MAX_PATH_LENGTH=500,SHELL_METACHARACTERS2=/[;|&$`(){}<>!'"]/,CONTROL_CHAR_PATTERN2=/[\u0000-\u001F\u007F]/;function validateBase(base){if(base.length>MAX_REF_LENGTH2)return`base ref exceeds maximum length of ${MAX_REF_LENGTH2}`;if(!SAFE_REF_PATTERN.test(base))return"base contains invalid characters for git ref";return null}function validatePaths(paths){if(!paths)return null;for(let path256 of paths){if(!path256||path256.length===0)return"empty path not allowed";if(path256.length>MAX_PATH_LENGTH)return`path exceeds maximum length of ${MAX_PATH_LENGTH}`;if(SHELL_METACHARACTERS2.test(path256))return"path contains shell metacharacters";if(path256.startsWith("-"))return'path cannot start with "-" (option-like arguments not allowed)';if(CONTROL_CHAR_PATTERN2.test(path256))return"path contains control characters"}return null}var diff=createSwarmTool({description:"Analyze git diff for changed files, exports, interfaces, and function signatures. Returns structured output with contract change detection.",args:{base:exports_external.string().optional().describe('Base ref to diff against (default: HEAD). Use "staged" for staged changes, "unstaged" for working tree changes.'),paths:exports_external.array(exports_external.string()).optional().describe("Optional file paths to restrict diff scope."),summaryOnly:exports_external.boolean().optional().describe("When true, return only file list with additions/deletions counts and hasContractChanges. No hunk content or AST diff. Default false.")},async execute(args2,directory,_ctx){let typedArgs=args2,summaryOnly=typedArgs.summaryOnly===!0;try{let fileExistsInRef=function(refPath){try{return child_process12.execFileSync("git",["cat-file","-e",refPath],{encoding:"utf-8",timeout:3000,cwd:directory,stdio:["ignore","pipe","pipe"]}),!0}catch(e){if(e&&typeof e==="object"&&"code"in e){if(e.code==="ENOENT")throw e}return!1}},getContentFromRef=function(refPath){return child_process12.execFileSync("git",["show",refPath],{encoding:"utf-8",timeout:15000,cwd:directory,stdio:["ignore","pipe","pipe"]})};if(!directory||typeof directory!=="string"||directory.trim()==="")return JSON.stringify({error:"project directory is required but was not provided",files:[],contractChanges:[],hasContractChanges:!1},null,2);let base=typedArgs.base??"HEAD",baseValidationError=validateBase(base);if(baseValidationError){let errorResult={error:`invalid base: ${baseValidationError}`,files:[],contractChanges:[],hasContractChanges:!1};return JSON.stringify(errorResult,null,2)}let pathsValidationError=validatePaths(typedArgs.paths);if(pathsValidationError){let errorResult={error:`invalid paths: ${pathsValidationError}`,files:[],contractChanges:[],hasContractChanges:!1};return JSON.stringify(errorResult,null,2)}let gitArgs;if(base==="staged")gitArgs=["--no-pager","diff","--cached"];else if(base==="unstaged")gitArgs=["--no-pager","diff"];else gitArgs=["--no-pager","diff",base];let numstatArgs=[...gitArgs,"--numstat"],fullDiffArgs=[...gitArgs,"-U3"];if(typedArgs.paths?.length)numstatArgs.push("--",...typedArgs.paths),fullDiffArgs.push("--",...typedArgs.paths);let numstatOutput=child_process12.execFileSync("git",numstatArgs,{encoding:"utf-8",timeout:DIFF_TIMEOUT_MS,maxBuffer:MAX_BUFFER_BYTES,cwd:directory,stdio:["ignore","pipe","pipe"]}),files=[],numstatLines=numstatOutput.split(`
|
|
6418
|
+
`)}function synthesizeGeneralCouncil(question,mode,round1Responses,round2Responses){let safeRound1=Array.isArray(round1Responses)?round1Responses:[],safeRound2=Array.isArray(round2Responses)?round2Responses:[],disagreements=detectDisagreements(safeRound1),consensusPoints=buildConsensusClusters(safeRound1),persistingDisagreements=computePersistingDisagreements(disagreements,safeRound2),allSources=dedupeSources(safeRound1,safeRound2),roundsCompleted=safeRound2.length>0?2:1,synthesis=renderSynthesisMarkdown(question,mode,roundsCompleted,safeRound1,consensusPoints,persistingDisagreements,allSources);return{question,mode,round1Responses:safeRound1,disagreements,round2Responses:safeRound2,synthesis,consensusPoints,persistingDisagreements:persistingDisagreements.map((d)=>d.topic),allSources,timestamp:new Date().toISOString()}}init_state2();init_logger();init_create_tool();init_resolve_working_directory();var WebSearchResultSchema=exports_external.object({title:exports_external.string(),url:exports_external.string(),snippet:exports_external.string(),query:exports_external.string()}),MemberRoleEnum=exports_external.enum(["generalist","skeptic","domain_expert","devil_advocate","synthesizer"]),Round1ResponseSchema=exports_external.object({memberId:exports_external.string().min(1),model:exports_external.string().min(1),role:MemberRoleEnum,response:exports_external.string(),sources:exports_external.array(WebSearchResultSchema).default([]),searchQueries:exports_external.array(exports_external.string()).default([]),confidence:exports_external.number().min(0).max(1),areasOfUncertainty:exports_external.array(exports_external.string()).default([]),durationMs:exports_external.number().nonnegative().default(0)}),Round2ResponseSchema=Round1ResponseSchema.extend({disagreementTopics:exports_external.array(exports_external.string()).default([])}),ArgsSchema2=exports_external.object({question:exports_external.string().min(1).max(8000),mode:exports_external.enum(["general","spec_review"]).default("general"),members:exports_external.array(exports_external.string()).default([]),round1Responses:exports_external.array(Round1ResponseSchema).min(1),round2Responses:exports_external.array(Round2ResponseSchema).optional(),working_directory:exports_external.string().optional()}),convene_general_council=createSwarmTool({description:"Synthesize responses from a multi-model General Council. Accepts parallel member responses (Round 1, optionally Round 2), detects disagreements, and returns consensus points, persisting disagreements, and a structured synthesis. Architect-only. Config-gated on council.general.enabled in the resolved config: global ~/.config/opencode/opencode-swarm.json, then project .opencode/opencode-swarm.json overrides.",args:{question:exports_external.string().min(1).max(8000).describe("The question put to the council, or the spec text to review."),mode:exports_external.enum(["general","spec_review"]).optional().describe('"general" for /swarm council or pre-save PLAN advisory; "spec_review" for manual /swarm council --spec-review.'),members:exports_external.array(exports_external.string()).optional().describe("Optional list of member IDs convened (for evidence/audit)."),round1Responses:exports_external.array(exports_external.object({memberId:exports_external.string().min(1),model:exports_external.string().min(1),role:exports_external.enum(["generalist","skeptic","domain_expert","devil_advocate","synthesizer"]),response:exports_external.string(),sources:exports_external.array(exports_external.object({title:exports_external.string(),url:exports_external.string(),snippet:exports_external.string(),query:exports_external.string()})).optional(),searchQueries:exports_external.array(exports_external.string()).optional(),confidence:exports_external.number().min(0).max(1),areasOfUncertainty:exports_external.array(exports_external.string()).optional(),durationMs:exports_external.number().nonnegative().optional()})).describe("Round 1 member responses (one per council member)."),round2Responses:exports_external.array(exports_external.object({memberId:exports_external.string().min(1),model:exports_external.string().min(1),role:exports_external.enum(["generalist","skeptic","domain_expert","devil_advocate","synthesizer"]),response:exports_external.string(),sources:exports_external.array(exports_external.object({title:exports_external.string(),url:exports_external.string(),snippet:exports_external.string(),query:exports_external.string()})).optional(),searchQueries:exports_external.array(exports_external.string()).optional(),confidence:exports_external.number().min(0).max(1),areasOfUncertainty:exports_external.array(exports_external.string()).optional(),durationMs:exports_external.number().nonnegative().optional(),disagreementTopics:exports_external.array(exports_external.string()).optional()})).optional().describe("Round 2 deliberation responses (omit when no deliberation has occurred)."),working_directory:exports_external.string().optional().describe("Project root for config + evidence path resolution.")},execute:async(args2,directory,ctx)=>{let parsed=ArgsSchema2.safeParse(args2);if(!parsed.success){let fail={success:!1,reason:"invalid_args",message:parsed.error.issues.map((i)=>`${i.path.join(".")}: ${i.message}`).join("; ")};return JSON.stringify(fail,null,2)}let input=parsed.data,dirResult=resolveWorkingDirectory(input.working_directory,directory);if(!dirResult.success){let fail={success:!1,reason:"invalid_working_directory",message:dirResult.message};return JSON.stringify(fail,null,2)}let workingDir=dirResult.directory,generalConfig=loadPluginConfig(workingDir).council?.general;if(!generalConfig||generalConfig.enabled!==!0)return JSON.stringify({success:!1,reason:"council_general_disabled",message:"convene_general_council requires council.general.enabled: true in the resolved config: global ~/.config/opencode/opencode-swarm.json or project .opencode/opencode-swarm.json."},null,2);let round1=input.round1Responses,round2=input.round2Responses??[],result=synthesizeGeneralCouncil(input.question,input.mode,round1,round2),evidenceDir=path253.join(workingDir,".swarm","council","general"),evidenceFile=`${result.timestamp.replace(/[:.]/g,"-")}-${input.mode}.json`,evidencePath=path253.join(evidenceDir,evidenceFile);try{await fs143.promises.mkdir(evidenceDir,{recursive:!0}),await fs143.promises.writeFile(evidencePath,JSON.stringify(result,null,2))}catch(err){let message=err instanceof Error?err.message:String(err);log(`[convene_general_council] Failed to write evidence to ${evidencePath}: ${message}`)}try{let sessionID=ctx?.sessionID;if(sessionID){let session=getAgentSession(sessionID);if(session)pushGeneralCouncilAdvisory(session,result)}}catch{}let ok={success:!0,question:input.question,mode:input.mode,roundsCompleted:round2.length>0?2:1,consensusPoints:result.consensusPoints,disagreementsCount:result.disagreements.length,persistingDisagreements:result.persistingDisagreements,allSourcesCount:result.allSources.length,synthesis:result.synthesis,evidencePath};return JSON.stringify(ok,null,2)}});init_zod();init_config();init_schema();init_curator();init_curator();init_curator_llm_factory();init_review_receipt();init_utils2();init_create_tool();var curator_analyze=createSwarmTool({description:"Run curator phase analysis and optionally apply knowledge recommendations. Call this after reviewing a phase to apply knowledge updates. If recommendations is provided, applies them via applyCuratorKnowledgeUpdates.",args:{phase:exports_external.number().int().min(1).describe("Phase number to analyze"),recommendations:exports_external.array(exports_external.object({action:exports_external.enum(["promote","archive","flag_contradiction","rewrite"]),entry_id:exports_external.string().optional(),lesson:exports_external.string(),reason:exports_external.string(),category:exports_external.enum(["process","architecture","tooling","security","testing","debugging","performance","integration","other"]).optional(),confidence:exports_external.number().min(0).max(1).optional()})).optional().describe("Knowledge recommendations to apply. If omitted, only collects digest data.")},execute:async(args2,directory,ctx)=>{let typedArgs=args2;try{if(!Number.isInteger(typedArgs.phase)||typedArgs.phase<1)return JSON.stringify({error:"phase must be a positive integer >= 1"},null,2);if(typedArgs.recommendations){let validActions=["promote","archive","flag_contradiction","rewrite"];for(let rec of typedArgs.recommendations)if(!validActions.includes(rec.action))return JSON.stringify({error:`Invalid recommendation action: ${rec.action}`},null,2)}if(typedArgs.recommendations){let UUID_V42=/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;for(let rec of typedArgs.recommendations)if(rec.entry_id!==void 0&&!UUID_V42.test(rec.entry_id))return JSON.stringify({error:`Invalid entry_id '${rec.entry_id}': must be a UUID v4 or omitted. Use undefined/omit entry_id to create a new entry.`},null,2)}let{config:config3}=loadPluginConfigWithMeta(directory),curatorConfig=CuratorConfigSchema.parse(config3.curator??{}),knowledgeConfig=KnowledgeConfigSchema.parse(config3.knowledge??{}),agentsDispatched=[];try{let eventsContent=await readSwarmFileAsync(directory,"events.jsonl");if(eventsContent){let phaseEvents=filterPhaseEvents(eventsContent,typedArgs.phase),agentSet=new Set;for(let evt of phaseEvents){let record3=evt;if(typeof record3.agent==="string"&&record3.agent.length>0)agentSet.add(record3.agent);if(Array.isArray(record3.agents_dispatched)){for(let a of record3.agents_dispatched)if(typeof a==="string")agentSet.add(a)}}agentsDispatched=Array.from(agentSet).sort()}}catch{}let llmDelegate=createCuratorLLMDelegate(directory,"phase",ctx?.sessionID),curatorResult=await runCuratorPhase(directory,typedArgs.phase,agentsDispatched,curatorConfig,{},llmDelegate);{let scopeContent=curatorResult.digest?.summary??`Phase ${typedArgs.phase} curator analysis`,complianceWarnings=curatorResult.compliance.filter((c)=>c.severity==="warning"),receipt=complianceWarnings.length>0?buildRejectedReceipt({agent:"curator",scopeContent,scopeDescription:"phase-digest",blockingFindings:complianceWarnings.map((c)=>({location:`phase-${c.phase}`,summary:c.description,severity:c.type==="missing_reviewer"?"high":"medium"})),evidenceReferences:[],passConditions:["resolve all compliance warnings before phase completion"]}):buildApprovedReceipt({agent:"curator",scopeContent,scopeDescription:"phase-digest",checkedAspects:["phase_compliance","knowledge_recommendations","phase_digest"],validatedClaims:[`phase: ${typedArgs.phase}`,`knowledge_recommendations: ${curatorResult.knowledge_recommendations.length}`]});persistReviewReceipt(directory,receipt).catch(()=>{})}let applied=0,skipped=0;if(typedArgs.recommendations&&typedArgs.recommendations.length>0){let result=await applyCuratorKnowledgeUpdates(directory,typedArgs.recommendations,knowledgeConfig);applied=result.applied,skipped=result.skipped}return JSON.stringify({phase_digest:curatorResult.digest,compliance_count:curatorResult.compliance.length,applied,skipped},null,2)}catch(error93){return JSON.stringify({error:error93 instanceof Error?error93.message:String(error93),phase:typedArgs.phase},null,2)}}});init_zod();init_loader();init_create_tool();init_resolve_working_directory();var CriteriaItemSchema=exports_external.object({id:exports_external.string().min(1).max(20).regex(/^C\d+$/,'Criterion id must match C\\d+ (e.g. "C1", "C12")'),description:exports_external.string().min(10).max(500),mandatory:exports_external.boolean()}),ArgsSchema3=exports_external.object({taskId:exports_external.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/,"Task ID must be in N.M or N.M.P format"),criteria:exports_external.array(CriteriaItemSchema).min(1).max(20),working_directory:exports_external.string().optional()}),declare_council_criteria=createSwarmTool({description:"Pre-declare acceptance criteria for a task before the coder starts work. Criteria are persisted under .swarm/council/ and read back during council evaluation so reviewers assess a stable, pre-committed contract. Architect-only. Config-gated via council.enabled.",args:{taskId:exports_external.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/,"Task ID must be in N.M or N.M.P format").describe('Task ID for which criteria are declared, e.g. "1.1", "1.2.3"'),criteria:exports_external.array(exports_external.object({id:exports_external.string().min(1).max(20).regex(/^C\d+$/,"Criterion id must match C\\d+").describe('Criterion identifier, e.g. "C1", "C12"'),description:exports_external.string().min(10).max(500).describe("Human-readable description of the criterion"),mandatory:exports_external.boolean().describe("Whether the criterion is mandatory. Mandatory criteria block APPROVE when unmet.")})).min(1).max(20).describe("Array of acceptance criteria items. Must contain between 1 and 20 entries with unique ids."),working_directory:exports_external.string().optional().describe("Explicit project root directory. When provided, .swarm/council/ is resolved relative to this path instead of the plugin context directory.")},async execute(args2,directory){let parsed=ArgsSchema3.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,reason:"invalid arguments",errors:parsed.error.issues.map((i)=>({path:i.path.join("."),message:i.message}))},null,2);let input=parsed.data,dirResult=resolveWorkingDirectory(input.working_directory,directory);if(!dirResult.success)return JSON.stringify({success:!1,reason:dirResult.message},null,2);let workingDir=dirResult.directory;if(!loadPluginConfig(workingDir).council?.enabled)return JSON.stringify({success:!1,reason:"council feature is disabled — set council.enabled: true in .opencode/opencode-swarm.json to enable"},null,2);let ids=input.criteria.map((c)=>c.id);if(new Set(ids).size<ids.length){let seen=new Set,duplicates=[];for(let id of ids){if(seen.has(id)&&!duplicates.includes(id))duplicates.push(id);seen.add(id)}return JSON.stringify({success:!1,reason:"duplicate criterion ids",errors:duplicates},null,2)}let replaced=readCriteria(workingDir,input.taskId)!==null;return await writeCriteria(workingDir,input.taskId,input.criteria),JSON.stringify({success:!0,taskId:input.taskId,criteriaCount:input.criteria.length,mandatoryCount:input.criteria.filter((c)=>c.mandatory).length,declaredAt:new Date().toISOString(),replaced},null,2)}});init_zod();init_config();init_plan_schema();init_file_authority();init_path_identity();init_scope_binding();init_scope_persistence();init_state2();init_project_boundary();init_task_id();init_create_tool();import*as fs144 from"node:fs";import*as path254 from"node:path";function validateTaskIdFormat2(taskId){return validateTaskIdFormat(taskId)}function validateFiles(files){let errors5=[],totalBytes=0;for(let file3 of files){if(file3.includes("\x00")){errors5.push(`Invalid file "${file3}": null bytes are not allowed`);continue}let unsafeReason=unsafePathTextReason(file3);if(unsafeReason){errors5.push(`Invalid file path: ${unsafeReason}`);continue}if(file3.replace(/\\/g,"/").split("/").includes(".."))errors5.push(`Invalid file "${file3}": path traversal sequences (..) are not allowed`);let bytes=Buffer.byteLength(file3,"utf8");if(totalBytes+=bytes,bytes>MAX_SCOPE_PATH_BYTES)errors5.push(`Invalid file "${file3}": path exceeds maximum length of ${MAX_SCOPE_PATH_BYTES} UTF-8 bytes`)}if(totalBytes>MAX_SCOPE_FILES_BYTES)errors5.push(`Invalid scope: file paths exceed the aggregate limit of ${MAX_SCOPE_FILES_BYTES} UTF-8 bytes`);return errors5}async function executeDeclareScope(args2,fallbackDir,owner,authorityConfig){let taskIdError=validateTaskIdFormat2(args2.taskId);if(taskIdError)return{success:!1,message:"Validation failed",errors:[taskIdError]};if(!Array.isArray(args2.files)||args2.files.length===0)return{success:!1,message:"Validation failed",errors:["files must be a non-empty array"]};let fileErrors=validateFiles(args2.files);if(fileErrors.length>0)return{success:!1,message:"Validation failed",errors:fileErrors};if(args2.whitelist){let whitelistErrors=validateFiles(args2.whitelist);if(whitelistErrors.length>0)return{success:!1,message:"Validation failed",errors:whitelistErrors}}let normalizedDir;if(args2.working_directory!=null&&args2.working_directory.trim()!==""){if(args2.working_directory.includes("\x00"))return{success:!1,message:"Invalid working_directory: null bytes are not allowed",errors:["Invalid working_directory: null bytes are not allowed"]};if(/^\\\\|^(NUL|CON|AUX|COM[1-9]|LPT[1-9])(\..*)?$/i.test(args2.working_directory))return{success:!1,message:"Invalid working_directory: Windows device paths are not allowed",errors:["Invalid working_directory: Windows device paths are not allowed"]};if(normalizedDir=path254.normalize(args2.working_directory),normalizedDir.split(path254.sep).includes(".."))return{success:!1,message:"Invalid working_directory: path traversal sequences (..) are not allowed",errors:["Invalid working_directory: path traversal sequences (..) are not allowed"]};let resolvedDir=path254.resolve(normalizedDir);try{let realPath=fs144.realpathSync(resolvedDir),planPath2=path254.join(realPath,".swarm","plan.json");if(!fs144.existsSync(planPath2))return{success:!1,message:`Invalid working_directory: plan not found in "${realPath}"`,errors:[`Invalid working_directory: plan not found in "${realPath}"`]}}catch{return{success:!1,message:`Invalid working_directory: path "${resolvedDir}" does not exist or is inaccessible`,errors:[`Invalid working_directory: path "${resolvedDir}" does not exist or is inaccessible`]}}if(normalizedDir&&fallbackDir)try{let canonicalWorkingDir=fs144.realpathSync(path254.resolve(normalizedDir)),canonicalProjectRoot=fs144.realpathSync(path254.resolve(fallbackDir));if(isStrictPathDescendant(canonicalWorkingDir,canonicalProjectRoot)&&!hasExplicitProjectBoundary(canonicalWorkingDir))return{success:!1,message:`working_directory "${normalizedDir}" is a subdirectory of the project root. Use the project root "${fallbackDir}" instead.`,errors:[`Subdirectory working_directory not allowed — use project root "${fallbackDir}"`]}}catch{}}if(!normalizedDir&&!fallbackDir)return{success:!1,message:"Cannot resolve project directory",errors:["Provide working_directory or ensure the tool is invoked from a project root"]};let directory=normalizedDir||fallbackDir,planPath=path254.resolve(directory,".swarm","plan.json");if(!fs144.existsSync(planPath))return{success:!1,message:"No plan found",errors:["plan.json not found"]};let rawPlanContent;try{rawPlanContent=JSON.parse(fs144.readFileSync(planPath,"utf-8"))}catch{return{success:!1,message:"Failed to parse plan.json",errors:["plan.json is not valid JSON"]}}let parsedPlan=PlanSchema.safeParse(rawPlanContent);if(!parsedPlan.success)return{success:!1,message:"Failed to validate plan.json",errors:["plan.json does not match the supported plan schema"]};let planContent=parsedPlan.data,allTasks=planContent.phases?.flatMap((p)=>p.tasks??[])??[];if(!allTasks.some((t)=>t.id===args2.taskId))return{success:!1,message:`Task ${args2.taskId} not found in plan`,errors:[`Task ${args2.taskId} does not exist in plan.json`]};let taskInPlan=allTasks.find((t)=>t.id===args2.taskId);if(taskInPlan&&taskInPlan.status==="completed")return{success:!1,message:`Task ${args2.taskId} is already completed`,errors:[`Cannot declare scope for completed task ${args2.taskId}`]};let rawMergedFiles=[...args2.files,...args2.whitelist??[]],warnings=[],normalizeErrors=[],dir=directory,mergedFiles=rawMergedFiles.map((file3)=>{if(path254.isAbsolute(file3)){let relativePath2=path254.relative(dir,file3).replace(/\\/g,"/");if(relativePath2.startsWith(".."))return normalizeErrors.push(`Path '${file3}' resolves outside the project directory`),file3;return warnings.push(`Absolute path normalized to relative: '${relativePath2}' (was '${file3}')`),relativePath2}return file3});if(normalizeErrors.length>0)return{success:!1,message:"Validation failed",errors:normalizeErrors};let lstatErrors=[];for(let file3 of mergedFiles){let block=checkWriteTargetForSymlink(file3,dir);if(block)lstatErrors.push(block)}if(lstatErrors.length>0)return{success:!1,message:"Scope contains symlink-backed paths",errors:lstatErrors};let authorityErrors=[];for(let file3 of mergedFiles){let decision=checkFileAuthority("coder",file3,dir,authorityConfig,{declaredScope:[file3]});if(!decision.allowed)authorityErrors.push(decision.reason)}if(authorityErrors.length>0)return{success:!1,message:"Scope denied by effective coder authority",errors:authorityErrors};if(owner?.sessionID&&owner.messageID){let binding=createScopeBinding({directory:dir,plan:planContent,taskId:args2.taskId,files:mergedFiles,ownerSessionId:owner.sessionID,ownerMessageId:owner.messageID,source:"declare_scope"});if(!binding)return{success:!1,message:"Failed to bind scope to the calling session",errors:["Scope identity could not be validated"]};let persistence=await replaceExistingScopeDeclaration({directory:dir,binding,replaceExisting:args2.replace_existing??!1});if(!persistence.ok)return{success:!1,message:"Failed to persist scope declaration",errors:[`${persistence.code}: ${persistence.message}`]};let session=ensureAgentSession(owner.sessionID,owner.agentName??"architect",dir);session.declaredCoderScope=mergedFiles,session.lastScopeViolation=null}return warnings.push("SCOPE ENFORCEMENT: This declaration is bound to the caller session and current plan. Direct writes and statically detected shell/interpreter writes must stay inside the active Task-correlated scope; missing or unverifiable coder write authority fails closed with SCOPE_NOT_DECLARED or SCOPE_VIOLATION."),{success:!0,message:"Scope declared successfully",taskId:args2.taskId,fileCount:mergedFiles.length,warnings}}var declare_scope=createSwarmTool({description:"Declare the file scope for the next coder delegation. Sets the list of files the coder is permitted to modify for a specific task. Must be called before delegating to coder to enable scope containment checking.",args:{taskId:exports_external.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/,"Task ID must be in N.M or N.M.P format").describe('Task ID for which scope is being declared, e.g. "1.1", "1.2.3"'),files:exports_external.array(exports_external.string().min(1).max(4096)).min(1).describe("Array of file paths the coder is permitted to modify"),whitelist:exports_external.array(exports_external.string().min(1).max(4096)).optional().describe("Additional file paths to whitelist (merged with files)"),replace_existing:exports_external.boolean().optional().describe("Set true to atomically revoke and replace this session's existing live declaration for the same task"),working_directory:exports_external.string().optional().describe("Working directory where the plan is located")},execute:async(args2,_directory,ctx)=>{let{config:config3}=loadPluginConfigWithMeta(_directory);return JSON.stringify(await executeDeclareScope(args2,_directory,{sessionID:ctx?.sessionID??"",messageID:ctx?.messageID??"",agentName:ctx?.agent},config3.authority),null,2)}});init_zod();import*as child_process12 from"node:child_process";import*as fs145 from"node:fs";import*as path255 from"node:path";init_create_tool();var MAX_DIFF_LINES=500,DIFF_TIMEOUT_MS=30000,MAX_BUFFER_BYTES=5242880,MAX_AST_FILES=50,CONTRACT_PATTERNS=[/^[+-]\s*export\s+(function|const|class|interface|type|enum|default)\b/,/^[+-]\s*(interface|type)\s+\w+/,/^[+-]\s*public\s+/,/^[+-]\s*(async\s+)?function\s+\w+\s*\(/],SAFE_REF_PATTERN=/^[a-zA-Z0-9._\-/~^@{}]+$/,MAX_REF_LENGTH2=256,MAX_PATH_LENGTH=500,SHELL_METACHARACTERS3=/[;|&$`(){}<>!'"]/,CONTROL_CHAR_PATTERN2=/[\u0000-\u001F\u007F]/;function validateBase(base){if(base.length>MAX_REF_LENGTH2)return`base ref exceeds maximum length of ${MAX_REF_LENGTH2}`;if(!SAFE_REF_PATTERN.test(base))return"base contains invalid characters for git ref";return null}function validatePaths(paths){if(!paths)return null;for(let path256 of paths){if(!path256||path256.length===0)return"empty path not allowed";if(path256.length>MAX_PATH_LENGTH)return`path exceeds maximum length of ${MAX_PATH_LENGTH}`;if(SHELL_METACHARACTERS3.test(path256))return"path contains shell metacharacters";if(path256.startsWith("-"))return'path cannot start with "-" (option-like arguments not allowed)';if(CONTROL_CHAR_PATTERN2.test(path256))return"path contains control characters"}return null}var diff=createSwarmTool({description:"Analyze git diff for changed files, exports, interfaces, and function signatures. Returns structured output with contract change detection.",args:{base:exports_external.string().optional().describe('Base ref to diff against (default: HEAD). Use "staged" for staged changes, "unstaged" for working tree changes.'),paths:exports_external.array(exports_external.string()).optional().describe("Optional file paths to restrict diff scope."),summaryOnly:exports_external.boolean().optional().describe("When true, return only file list with additions/deletions counts and hasContractChanges. No hunk content or AST diff. Default false.")},async execute(args2,directory,_ctx){let typedArgs=args2,summaryOnly=typedArgs.summaryOnly===!0;try{let fileExistsInRef=function(refPath){try{return child_process12.execFileSync("git",["cat-file","-e",refPath],{encoding:"utf-8",timeout:3000,cwd:directory,stdio:["ignore","pipe","pipe"]}),!0}catch(e){if(e&&typeof e==="object"&&"code"in e){if(e.code==="ENOENT")throw e}return!1}},getContentFromRef=function(refPath){return child_process12.execFileSync("git",["show",refPath],{encoding:"utf-8",timeout:15000,cwd:directory,stdio:["ignore","pipe","pipe"]})};if(!directory||typeof directory!=="string"||directory.trim()==="")return JSON.stringify({error:"project directory is required but was not provided",files:[],contractChanges:[],hasContractChanges:!1},null,2);let base=typedArgs.base??"HEAD",baseValidationError=validateBase(base);if(baseValidationError){let errorResult={error:`invalid base: ${baseValidationError}`,files:[],contractChanges:[],hasContractChanges:!1};return JSON.stringify(errorResult,null,2)}let pathsValidationError=validatePaths(typedArgs.paths);if(pathsValidationError){let errorResult={error:`invalid paths: ${pathsValidationError}`,files:[],contractChanges:[],hasContractChanges:!1};return JSON.stringify(errorResult,null,2)}let gitArgs;if(base==="staged")gitArgs=["--no-pager","diff","--cached"];else if(base==="unstaged")gitArgs=["--no-pager","diff"];else gitArgs=["--no-pager","diff",base];let numstatArgs=[...gitArgs,"--numstat"],fullDiffArgs=[...gitArgs,"-U3"];if(typedArgs.paths?.length)numstatArgs.push("--",...typedArgs.paths),fullDiffArgs.push("--",...typedArgs.paths);let numstatOutput=child_process12.execFileSync("git",numstatArgs,{encoding:"utf-8",timeout:DIFF_TIMEOUT_MS,maxBuffer:MAX_BUFFER_BYTES,cwd:directory,stdio:["ignore","pipe","pipe"]}),files=[],numstatLines=numstatOutput.split(`
|
|
6419
6419
|
`);for(let line of numstatLines){if(!line.trim())continue;let parts=line.split("\t");if(parts.length>=3){let additions=parseInt(parts[0],10)||0,deletions=parseInt(parts[1],10)||0,path256=parts[2];files.push({path:path256,additions,deletions})}}if(summaryOnly){let hasContractChanges2=!1;try{let contractDiffArgs=[...gitArgs,"-U0"];if(typedArgs.paths?.length)contractDiffArgs.push("--",...typedArgs.paths);let contractDiffLines=child_process12.execFileSync("git",contractDiffArgs,{encoding:"utf-8",timeout:DIFF_TIMEOUT_MS,maxBuffer:MAX_BUFFER_BYTES,cwd:directory,stdio:["ignore","pipe","pipe"]}).split(`
|
|
6420
6420
|
`);for(let line of contractDiffLines){for(let pattern of CONTRACT_PATTERNS)if(pattern.test(line)){hasContractChanges2=!0;break}if(hasContractChanges2)break}}catch{hasContractChanges2=!0}let result2={files,contractChanges:[],hasContractChanges:hasContractChanges2,summary:`${files.length} files changed (summary only)`};return JSON.stringify(result2,null,2)}let fullDiffOutput=child_process12.execFileSync("git",fullDiffArgs,{encoding:"utf-8",timeout:DIFF_TIMEOUT_MS,maxBuffer:MAX_BUFFER_BYTES,cwd:directory,stdio:["ignore","pipe","pipe"]}),contractChanges=[],diffLines=fullDiffOutput.split(`
|
|
6421
6421
|
`),currentFile="";for(let line of diffLines){let gitLineMatch=line.match(/^diff --git.* b\/(.+)$/);if(gitLineMatch)currentFile=gitLineMatch[1];for(let pattern of CONTRACT_PATTERNS)if(pattern.test(line)){let trimmed=line.trim();if(currentFile)contractChanges.push(`[${currentFile}] ${trimmed}`);else contractChanges.push(trimmed);break}}let hasContractChanges=contractChanges.length>0,fileCount=files.length,astDiffs=[],filesForAST=files.slice(0,MAX_AST_FILES);for(let file3 of filesForAST)try{let oldContent,newContent;if(base==="staged"){let oldRef=`HEAD:${file3.path}`;oldContent=fileExistsInRef(oldRef)?getContentFromRef(oldRef):"",newContent=getContentFromRef(`:${file3.path}`)}else if(base==="unstaged"){let oldRef=`:${file3.path}`;oldContent=fileExistsInRef(oldRef)?getContentFromRef(oldRef):"",newContent=fs145.readFileSync(path255.join(directory,file3.path),"utf-8")}else{let oldRef=`${base}:${file3.path}`;oldContent=fileExistsInRef(oldRef)?getContentFromRef(oldRef):"",newContent=getContentFromRef(`HEAD:${file3.path}`)}let astResult=await computeASTDiff(file3.path,oldContent,newContent);if(astResult&&(astResult.changes.length>0||astResult.error))astDiffs.push(astResult)}catch(e){if(e&&typeof e==="object"&&"code"in e){if(e.code==="ENOENT")throw e}astDiffs.push({filePath:file3.path,language:null,changes:[{type:"modified",category:"other",name:"(parse failed)",lineStart:0,lineEnd:0}],durationMs:0,usedAST:!1,error:"AST parse unavailable — tree-sitter analysis failed for this file"})}let semanticSummary;if(astDiffs.length>0)try{let classifiedChanges=classifyChanges(astDiffs);semanticSummary=generateSummary(classifiedChanges)}catch{}let markdownSummary;if(semanticSummary)try{markdownSummary=generateSummaryMarkdown(semanticSummary)}catch{}let astSkippedCount=files.length>MAX_AST_FILES?files.length-MAX_AST_FILES:0,summary=diffLines.length>MAX_DIFF_LINES?`${fileCount} files changed. Contract changes: ${hasContractChanges?"YES":"NO"}. (truncated to ${MAX_DIFF_LINES} lines)`:`${fileCount} files changed. Contract changes: ${hasContractChanges?"YES":"NO"}`,result={files,contractChanges,hasContractChanges,summary,...astDiffs.length>0?{astDiffs}:{},...semanticSummary?{semanticSummary}:{},...markdownSummary?{markdownSummary}:{},...astSkippedCount>0?{astSkippedCount}:{}};return JSON.stringify(result,null,2)}catch(e){let errorResult={error:e instanceof Error?`git diff failed: ${e.message}`:"git diff failed: unknown error",files:[],contractChanges:[],hasContractChanges:!1};return JSON.stringify(errorResult,null,2)}}});init_zod();import*as child_process13 from"node:child_process";import*as fs146 from"node:fs";import*as path256 from"node:path";init_git_binary_missing_error();init_create_tool();init_resolve_working_directory();async function execGit2(workingDir,args2,options){try{return await new Promise((resolve104,reject2)=>{let execOpts={encoding:"utf-8",cwd:workingDir,timeout:options?.timeout,maxBuffer:options?.maxBuffer,stdio:["ignore","pipe","pipe"]};child_process13.execFile("git",args2,execOpts,(error93,output,_stderr)=>{if(error93){reject2(error93);return}resolve104(output??"")})})}catch(err){if(isGitBinaryMissing(err))throw new GitBinaryMissingError("git binary is not available",{cause:err});throw err}}var diff_summary=createSwarmTool({description:"Generate a filtered semantic diff summary from AST analysis. Returns SemanticDiffSummary with optional filtering by classification or riskLevel.",args:{files:exports_external.array(exports_external.string()).describe("Array of file paths to analyze"),classification:exports_external.string().optional().describe("Filter results to only this ChangeCategory"),riskLevel:exports_external.string().optional().describe("Filter results to only this RiskLevel")},async execute(args2,directory,_ctx){let typedArgs=args2;try{if(!typedArgs.files||!Array.isArray(typedArgs.files)||typedArgs.files.length===0)return JSON.stringify({error:"files must be a non-empty array of file paths",success:!1},null,2);let resolved=resolveWorkingDirectory(void 0,directory);if(!resolved.success)return JSON.stringify({success:!1,error:resolved.message},null,2);let workingDir=resolved.directory,astDiffs=[];for(let filePath of typedArgs.files){let astResult=null,fileExistsInHead=!1;try{await execGit2(workingDir,["cat-file","-e",`HEAD:${filePath}`],{timeout:3000}),fileExistsInHead=!0}catch(e){if(e instanceof GitBinaryMissingError)throw e}try{let oldContent,newContent=await fs146.promises.readFile(path256.join(workingDir,filePath),"utf-8");if(fileExistsInHead)oldContent=await execGit2(workingDir,["show",`HEAD:${filePath}`],{timeout:5000,maxBuffer:5242880});else oldContent="";astResult=await computeASTDiff(filePath,oldContent,newContent)}catch(e){if(e instanceof GitBinaryMissingError)throw e;astResult=null}if(astResult&&(astResult.changes.length>0||astResult.error!==void 0))astDiffs.push(astResult)}let filteredChanges=classifyChanges(astDiffs);if(typedArgs.classification)filteredChanges=filteredChanges.filter((change)=>change.category===typedArgs.classification);if(typedArgs.riskLevel)filteredChanges=filteredChanges.filter((change)=>change.riskLevel===typedArgs.riskLevel);let summary=generateSummary(filteredChanges);return JSON.stringify(summary,null,2)}catch(e){let errorResult={error:e instanceof Error?`diff_summary failed: ${e.message}`:"diff_summary failed: unknown error",success:!1};return JSON.stringify(errorResult,null,2)}}});init_p_limit();init_zod();init_candidate_contract();import{createHash as createHash49}from"node:crypto";init_lane_output_store();import*as fs147 from"node:fs";import*as path257 from"node:path";var LANE_DELIVERY_CACHE_FILENAME="lane-delivery-cache.json",MAX_DELIVERED_LANE_OUTPUT_KEYS=1024,MAX_TRACKED_SESSIONS10=16,MAX_TRACKED_DIRECTORIES=16,CORRUPT_SUFFIX=".corrupt",directoryBuckets=new Map;function bucketKey(directory){return directory?path257.normalize(path257.resolve(directory)):""}function emptyBucket(){return{order:[],sessions:new Map,total:0}}function cacheFilePath(directory){return path257.join(directory,".swarm",LANE_DELIVERY_CACHE_FILENAME)}function isValidCacheFile(value){if(!value||typeof value!=="object"||value.version!==1)return!1;let{order,sessions}=value;if(!Array.isArray(order)||order.some((id)=>typeof id!=="string"))return!1;if(!sessions||typeof sessions!=="object")return!1;return Object.values(sessions).every((keys)=>Array.isArray(keys)&&keys.every((key)=>typeof key==="string"))}function loadBucketFromDisk(directory){let file3=cacheFilePath(directory),raw;try{raw=fs147.readFileSync(file3,"utf-8")}catch{return emptyBucket()}let parsed;try{parsed=JSON.parse(raw)}catch{parsed=null}if(!isValidCacheFile(parsed)){try{let corruptPath=`${file3}${CORRUPT_SUFFIX}`,lastRenameError;for(let attempt=0;attempt<3;attempt++)try{fs147.renameSync(file3,corruptPath),lastRenameError=void 0;break}catch(err){lastRenameError=err;let code=err.code;if(code!=="EEXIST"&&code!=="EBUSY"&&code!=="EPERM")break}if(lastRenameError)throw lastRenameError}catch{}return emptyBucket()}let bucket=emptyBucket(),seen=new Set;for(let sessionID of parsed.order){if(seen.has(sessionID))continue;let keys=parsed.sessions[sessionID];if(!keys||keys.length===0)continue;seen.add(sessionID),bucket.order.push(sessionID),bucket.sessions.set(sessionID,[...keys]),bucket.total+=keys.length}return bucket}function persistBucket(directory,bucket){let file3={version:1,order:bucket.order,sessions:Object.fromEntries(bucket.sessions)};try{writeAtomicJson(cacheFilePath(directory),file3)}catch{}}function evictOverflow(bucket){while(bucket.total>MAX_DELIVERED_LANE_OUTPUT_KEYS){let evicted=!1;for(let sessionID of bucket.order){let keys=bucket.sessions.get(sessionID);if(!keys||keys.length===0)continue;if(keys.shift(),bucket.total-=1,keys.length===0)bucket.sessions.delete(sessionID),bucket.order=bucket.order.filter((id)=>id!==sessionID);evicted=!0;break}if(!evicted)break}}function bucketFor(directory){let key=bucketKey(directory),existing=directoryBuckets.get(key);if(existing)return existing;while(directoryBuckets.size>=MAX_TRACKED_DIRECTORIES){let oldestDirectory=directoryBuckets.keys().next().value;if(oldestDirectory===void 0)break;directoryBuckets.delete(oldestDirectory)}let bucket=directory?loadBucketFromDisk(directory):emptyBucket();return directoryBuckets.set(key,bucket),bucket}function sessionKeys(bucket,sessionID){let key=sessionID??"",keys=bucket.sessions.get(key);if(!keys){while(bucket.order.length>=MAX_TRACKED_SESSIONS10){let oldest=bucket.order.shift();if(oldest===void 0)break;let oldestKeys=bucket.sessions.get(oldest);bucket.sessions.delete(oldest),bucket.total-=oldestKeys?.length??0}keys=[],bucket.sessions.set(key,keys),bucket.order.push(key)}return keys}function hasLaneOutputBeenDelivered(directory,sessionID,key){if(!key)return!1;return bucketFor(directory).sessions.get(sessionID??"")?.includes(key)??!1}function markLaneOutputDelivered(directory,sessionID,key){if(!key)return;let bucket=bucketFor(directory),keys=sessionKeys(bucket,sessionID);if(keys.includes(key))return;if(keys.push(key),bucket.total+=1,evictOverflow(bucket),directory)persistBucket(directory,bucket)}init_lane_output_store();init_pending_delegations();init_pr_review_trigger_contract();init_workspace_snapshot();init_constants();init_schema();init_pr_workflow_gate();init_p_limit();function createParallelDispatcher(config3){let limit=pLimit(config3.maxConcurrentTasks),activeSlots=new Map,slotCounter=0,shutdownCalled=!1;return{config:config3,dispatch(taskId){if(!config3.enabled)return{action:"reject",reason:"dispatcher_disabled"};if(shutdownCalled)return{action:"reject",reason:"dispatcher_shutdown"};if(activeSlots.size>=config3.maxConcurrentTasks)return{action:"defer",reason:"max_concurrent_tasks_reached"};let slotId=`slot-${++slotCounter}`,runId=`run-${taskId}-${slotId}`,slot={slotId,taskId,runId,startedAt:Date.now()};return activeSlots.set(slotId,slot),limit(async()=>{}),{action:"dispatch",reason:"slot_available",slot}},handles(){return[...activeSlots.values()].map((slot)=>({slotId:slot.slotId,taskId:slot.taskId,runId:slot.runId,cancel:()=>{activeSlots.delete(slot.slotId)}}))},releaseSlot(slotId){activeSlots.delete(slotId)},shutdown(){shutdownCalled=!0,activeSlots.clear(),limit.clearQueue()}}}init_state2();init_ephemeral_session_teardown();init_logger();init_create_tool();var MAX_LANES=8,MAX_PROMPT_CHARS=80000,COMMON_PROMPT_SEPARATOR=`
|
|
@@ -6522,7 +6522,7 @@ Return a JSON array where each element has:
|
|
|
6522
6522
|
|
|
6523
6523
|
Return ONLY a valid JSON array. No markdown, no code fences, no explanation. Start your response with [ and end with ].`,promptResult=await client.session.prompt({path:{id:ephemeralSessionId},body:{agent:void 0,tools:{write:!1,edit:!1,patch:!1},parts:[{type:"text",text:promptText}]},signal:promptController.signal});if(!promptResult.data)return log(`[generateMutants] LLM prompt failed: ${JSON.stringify(promptResult.error)}; returning empty patch set`),[];let rawText=promptResult.data.parts.filter((p)=>p.type==="text").map((p)=>p.text).join(`
|
|
6524
6524
|
`),parsed;try{parsed=JSON.parse(extractJsonArray(rawText))}catch(error93){let msg=error93 instanceof Error?error93.message:String(error93),hint=msg.includes("EOF")||msg.includes("Unexpected end")?" (response appears truncated — LLM may have hit an output token limit)":"";return log(`[generateMutants] Failed to parse LLM response as MutationPatch[]: ${msg}${hint}; returning empty patch set`),[]}if(!Array.isArray(parsed)||parsed.length===0)return[];let patches=[];for(let item of parsed){if(typeof item!=="object"||item===null||typeof item.filePath!=="string"||typeof item.functionName!=="string"||typeof item.mutationType!=="string"||typeof item.patch!=="string")continue;let mutationType=item.mutationType,fileSlug=slugify3(item.filePath),fnSlug=slugify3(item.functionName),typeSlug=slugify3(mutationType),idStr=typeof item.id==="string"?item.id:"",id=idStr.startsWith("mut-")?idStr:`mut-${fileSlug}-${fnSlug}-${typeSlug}-${String(patches.length+1).padStart(3,"0")}`;patches.push({id,filePath:item.filePath,functionName:item.functionName,mutationType,patch:item.patch,lineNumber:typeof item.lineNumber==="number"?item.lineNumber:void 0})}return patches}catch(error93){return log(`[generateMutants] LLM call failed: ${error93 instanceof Error?error93.message:String(error93)}; returning empty patch set`),[]}finally{await cleanup()}}init_create_tool();var generate_mutants=createSwarmTool({description:"Generate LLM-based mutation testing patches for the specified source files. Returns MutationPatch[] for direct consumption by the mutation_test tool. On LLM failure or when no patches can be generated, returns a SKIP verdict with a diagnostic message rather than throwing.",args:{files:exports_external.array(exports_external.string()).describe("Array of source file paths to generate mutation patches for")},async execute(args2,_directory,ctx){let typedArgs=args2;if(!typedArgs.files||!Array.isArray(typedArgs.files)||typedArgs.files.length===0)return JSON.stringify({verdict:"SKIP",patches:[],count:0,message:"generate_mutants: files must be a non-empty array"},null,2);try{let patches=await generateMutants(typedArgs.files,ctx);if(patches.length===0)return JSON.stringify({verdict:"SKIP",patches:[],count:0,message:"generate_mutants: LLM returned no patches — skipping mutation gate"},null,2);let result={verdict:"ready",patches,count:patches.length};return JSON.stringify(result,null,2)}catch(error93){let result={verdict:"SKIP",patches:[],count:0,message:`generate_mutants: unexpected error — ${error93 instanceof Error?error93.message:String(error93)}`};return JSON.stringify(result,null,2)}}});init_zod();init_qa_gate_profile();init_ledger();init_manager();init_utils3();init_create_tool();function buildQaProfileMetadata(directory,currentPlan){let profileLookup=getProfileLookupForIdentity(directory,currentPlan);if(profileLookup.kind==="bound")return{qa_profile_hash:computeProfileHash(profileLookup.profile),qa_profile_status:"bound"};if(profileLookup.kind==="unbound_legacy")return{qa_profile_hash:null,qa_profile_status:"unbound_legacy",qa_profile_error:"QA_GATE_IDENTITY_UNBOUND: the current plan has a legacy QA gate profile row that is not exact-bound.",qa_profile_recovery_guidance:formatLegacyQaBindingRecovery(currentPlan,"retry get_approved_plan with the identical identity")};return{qa_profile_hash:null,qa_profile_status:"missing"}}function summarizePlan(plan){return{title:plan.title,swarm:plan.swarm,current_phase:plan.current_phase??0,phase_count:plan.phases.length,phases:plan.phases.map((p)=>({id:p.id,name:p.name,status:p.status,task_count:p.tasks.length}))}}async function executeGetApprovedPlan(args2,directory){let currentPlan=await loadPlanJsonOnly(directory);if(!currentPlan){if(await loadLastApprovedPlan(directory))return{success:!0,approved_plan:void 0,current_plan:null,drift_detected:"unknown",current_plan_error:"plan.json not found or invalid"};return{success:!1,reason:"no_approved_snapshot"}}let expectedPlanId=derivePlanId(currentPlan),qaProfileMetadata=buildQaProfileMetadata(directory,currentPlan),approved=await loadLastApprovedPlan(directory,expectedPlanId);if(!approved){if(await loadLastApprovedPlan(directory))return{success:!0,approved_plan:void 0,current_plan:null,drift_detected:!0,current_plan_error:"Plan identity (swarm/title) was mutated after approval — "+`expected plan_id '${expectedPlanId}' but approved snapshot has a different identity. This is a form of plan tampering.`,...qaProfileMetadata};return{success:!1,reason:"no_approved_snapshot",...qaProfileMetadata}}let summaryOnly=args2.summary_only===!0,approvedPayload={plan:summaryOnly?summarizePlan(approved.plan):approved.plan,approval_metadata:approved.approval,snapshot_seq:approved.seq,snapshot_timestamp:approved.timestamp,payload_hash:approved.payloadHash,execution_profile:approved.plan.execution_profile??null},currentHash=computePlanHash(currentPlan),driftDetected=currentHash!==approved.payloadHash,currentPayload={plan:summaryOnly?summarizePlan(currentPlan):currentPlan,current_hash:currentHash};return{success:!0,approved_plan:approvedPayload,current_plan:currentPayload,drift_detected:driftDetected,...qaProfileMetadata}}var get_approved_plan=createSwarmTool({allowWorkingDirectoryOverride:!0,description:"Retrieve the last critic-approved immutable plan snapshot for baseline drift comparison. Returns the approved plan, its approval metadata, and optionally compares against the current plan.json to detect silent mutations. Read-only.",args:{summary_only:exports_external.boolean().optional().describe("When true, returns only structural metadata (title, phases, task counts) instead of full plan objects. Reduces output size for large plans.")},execute:async(args2,directory)=>{return JSON.stringify(await executeGetApprovedPlan(args2,directory),null,2)}});init_zod();init_qa_gate_profile();init_manager();init_create_tool();init_utils3();function resolveQaGatePlanIdentity(plan,args2){let hasSwarmId=args2.swarm_id!==void 0,hasPlanTitle=args2.plan_title!==void 0;if(hasSwarmId!==hasPlanTitle)return{success:!1,reason:"plan_identity_incomplete",message:"QA gate identity is incomplete: provide both swarm_id and plan_title, or neither when using the current plan."};if(!hasSwarmId&&!hasPlanTitle){if(!plan)return{success:!1,reason:"plan_identity_required",message:"Cannot resolve QA gate identity before plan.json exists. Provide both swarm_id and plan_title."};return{success:!0,planId:derivePlanId(plan),identity:plan}}let{swarm_id:swarmId,plan_title:planTitle}=args2;if(typeof swarmId!=="string"||swarmId.trim().length===0||typeof planTitle!=="string"||planTitle.trim().length===0)return{success:!1,reason:"plan_identity_invalid",message:"QA gate identity is invalid: swarm_id and plan_title must both contain non-whitespace text."};if(plan&&(plan.swarm!==swarmId||plan.title!==planTitle)&&args2.confirm_identity_change!==!0)return{success:!1,reason:"plan_identity_mismatch",message:"The explicit QA gate identity does not exactly match the current plan. Verify swarm_id and plan_title, or set confirm_identity_change: true for an intentional replacement."};return{success:!0,planId:derivePlanId({swarm:swarmId,title:planTitle}),identity:{swarm:swarmId,title:planTitle}}}async function executeGetQaGateProfile(args2,directory){let plan=await loadPlanJsonOnly(directory),identity=resolveQaGatePlanIdentity(plan,args2);if(!identity.success)return{success:!1,reason:identity.reason,message:identity.message};let planId=identity.planId,lookup=getProfileLookupForIdentity(directory,identity.identity);if(lookup.kind==="missing")return{success:!1,reason:"no_profile",plan_id:planId};if(lookup.kind==="unbound_legacy")return{success:!1,reason:"plan_identity_unbound",plan_id:planId,message:`The current plan has a legacy QA gate profile row that is not exact-bound. ${formatLegacyQaBindingRecovery(identity.identity,"retry this read-only QA profile lookup")}`};let profile=lookup.profile;return{success:!0,plan_id:planId,profile:{plan_id:profile.plan_id,project_type:profile.project_type,gates:{...profile.gates},locked_at:profile.locked_at,locked_by_snapshot_seq:profile.locked_by_snapshot_seq,created_at:profile.created_at,profile_hash:computeProfileHash(profile)}}}var get_qa_gate_profile=createSwarmTool({allowWorkingDirectoryOverride:!0,description:"Retrieve the QA gate profile for the current plan. Returns the spec-level "+"gates, lock state, and a SHA-256 profile hash. Read-only — does not "+"create a profile if none exists. Uses the current plan identity by default, or an exact swarm_id + plan_title pair before plan.json exists.",args:{swarm_id:exports_external.string().refine((value)=>value.trim().length>0,"Must not be blank").optional().describe("Exact swarm identity for a pre-plan profile lookup. Must be provided with plan_title."),plan_title:exports_external.string().refine((value)=>value.trim().length>0,"Must not be blank").optional().describe("Exact future plan title for a pre-plan profile lookup. Must be provided with swarm_id."),confirm_identity_change:exports_external.boolean().optional().describe("Confirm that an explicit swarm_id/plan_title pair intentionally replaces the current plan identity.")},execute:async(args2,directory)=>{return JSON.stringify(await executeGetQaGateProfile(args2??{},directory),null,2)}});init_zod();init_external_tool_runner();init_path_security();import path264 from"node:path";init_create_tool();var GH_TIMEOUT_MS=20000,GH_MAX_STDOUT_BYTES=2097152,GH_MAX_STDERR_BYTES=131072,DEFAULT_PR_FIELDS=["number","title","state","isDraft","author","headRefName","headRefOid","baseRefName","baseRefOid","mergeable","mergeStateStatus","reviewDecision","statusCheckRollup","url"],DEFAULT_ISSUE_FIELDS=["number","title","state","author","labels","assignees","url"],PR_FIELD_ALLOWLIST=new Set([...DEFAULT_PR_FIELDS,"additions","assignees","body","changedFiles","closedAt","comments","commits","createdAt","deletions","files","labels","latestReviews","mergedAt","milestone","reviews","updatedAt"]),ISSUE_FIELD_ALLOWLIST=new Set([...DEFAULT_ISSUE_FIELDS,"body","comments","closed","closedAt","createdAt","milestone","updatedAt"]),DEFAULT_RUN_FIELDS=["status","conclusion","htmlUrl","headBranch","headSha"],RUN_FIELD_ALLOWLIST=new Set([...DEFAULT_RUN_FIELDS,"name","workflowId","runNumber","event","runStartedAt","createdAt","updatedAt"]),PR_FIELD_ALIASES=new Map([["changed_files","changedFiles"]]);function resolveGhBinaryCandidates(options={}){if((options.platform??process.platform)!=="win32")return["gh"];let env=options.env??process.env,candidates=["gh"],pushCandidate=(...parts)=>{let candidate2=path264.join(...parts);if(!candidates.includes(candidate2))candidates.push(candidate2)};if(env.ProgramFiles)pushCandidate(env.ProgramFiles,"GitHub CLI","gh.exe");if(env["ProgramFiles(x86)"])pushCandidate(env["ProgramFiles(x86)"],"GitHub CLI","gh.exe");if(env.LOCALAPPDATA)pushCandidate(env.LOCALAPPDATA,"GitHub CLI","gh.exe"),pushCandidate(env.LOCALAPPDATA,"Programs","GitHub CLI","gh.exe");return candidates}function resolveGhBinary(){return _internals205.resolveExecutableFromPath(resolveGhBinaryCandidates())}function normalizeRepo(value){if(value===void 0||value===null||value==="")return;if(typeof value!=="string"||containsControlChars(value))return{error:!0,type:"invalid-input",message:"repo must be an owner/name string"};if(!/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(value))return{error:!0,type:"invalid-input",message:"repo must match owner/name"};return value}function normalizeFields(target,value){let defaults=target==="pr"?Array.from(DEFAULT_PR_FIELDS):target==="issue"?Array.from(DEFAULT_ISSUE_FIELDS):Array.from(DEFAULT_RUN_FIELDS);if(value===void 0||value===null||value==="")return defaults;let raw=Array.isArray(value)?value:typeof value==="string"?value.split(","):null;if(!raw||raw.some((f)=>typeof f!=="string"))return{error:!0,type:"invalid-input",message:"fields must be a comma-separated string or string array"};let canonicalizeField=(field)=>target==="pr"?PR_FIELD_ALIASES.get(field)??field:field,allowlist=target==="pr"?PR_FIELD_ALLOWLIST:target==="issue"?ISSUE_FIELD_ALLOWLIST:RUN_FIELD_ALLOWLIST,fields=Array.from(new Set(raw.map((f)=>canonicalizeField(f.trim())).filter(Boolean))),allowedList=Array.from(allowlist).sort().join(", ");if(fields.length===0)return{error:!0,type:"invalid-input",message:`no ${target} fields provided. Allowed ${target} fields: ${allowedList}.`};let rejected=fields.filter((f)=>containsControlChars(f)||!allowlist.has(f));if(rejected.length>0){let printable=rejected.filter((f)=>!containsControlChars(f)).map((f)=>f.length>60?`${f.slice(0,60)}...`:f).slice(0,12),rejectedText=printable.length>0?printable.join(", "):"(names omitted: contain control characters)";return{error:!0,type:"invalid-input",message:`unsupported ${target} field(s): ${rejectedText}. Allowed ${target} fields: ${allowedList}.`}}return fields}function sanitizeParsedJson(value){if(Array.isArray(value))return value.map(sanitizeParsedJson);if(value&&typeof value==="object"){let out={};for(let[key,entry]of Object.entries(value)){if(typeof entry==="string"){let bounded=entry.length>20000?`${entry.slice(0,20000)}... [truncated]`:entry;out[key]=key==="body"?neutralizeUntrustedMarkdown(bounded,"GitHub body"):bounded;continue}out[key]=sanitizeParsedJson(entry)}return out}return value}function ghNotFoundGuidance(target,number7,repo,logFailed){let repoSlug=repo??"<owner>/<name>",restPath=target==="pr"?`pulls/${number7}`:target==="issue"?`issues/${number7}`:`actions/runs/${number7}`,lines=["GitHub CLI (gh) not found on PATH. Install gh for full evidence.",`Degraded read-only path: fetch ${`https://api.github.com/repos/${repoSlug}/${restPath}`} with the web fetch tool (a gate-allowed observation).`];if(!repo)lines.push('No repo argument was provided, so the URL uses an <owner>/<name> placeholder; pass repo as "owner/name" to make it fetchable.');if(lines.push("Caveats: REST returns snake_case keys and omits gh-only fields (statusCheckRollup, reviewDecision, mergeStateStatus). Public repos work unauthenticated; private repos need gh or an authenticated client."),target==="run"&&logFailed)lines.push("Note: log_failed job logs are gh-only and have no REST-URL equivalent.");return lines.join(" ")}var gh_evidence=createSwarmTool({description:"Fetch bounded GitHub pull request or issue metadata via gh for review evidence. Read-only; resolves gh lazily.",args:{target:exports_external.enum(["pr","issue","run"]).default("pr").describe("GitHub object type to view: pr, issue, or run"),number:exports_external.number().describe("Pull request, issue, or run number"),repo:exports_external.string().optional().describe("Optional owner/repo. If omitted, gh uses the current repo."),fields:exports_external.union([exports_external.string(),exports_external.array(exports_external.string())]).optional().describe("Optional JSON fields. Defaults to high-signal bounded PR or issue fields. Ignored for run with log_failed."),log_failed:exports_external.boolean().optional().default(!1).describe("When true with target=run, fetches failed job logs instead of JSON")},execute:async(args2,directory)=>{let obj=typeof args2==="object"&&args2!==null?args2:{},rawTarget=obj.target,target=rawTarget==="issue"?"issue":rawTarget==="run"?"run":"pr",number7=typeof obj.number==="number"?obj.number:NaN;if(!Number.isInteger(number7)||number7<=0)return JSON.stringify({error:!0,type:"invalid-input",message:"number must be a positive integer"},null,2);let repo=normalizeRepo(obj.repo);if(repo&&typeof repo==="object")return JSON.stringify(repo,null,2);let logFailed=obj.log_failed===!0,fields=normalizeFields(target,obj.fields);if(!Array.isArray(fields))return JSON.stringify(fields,null,2);let executable=_internals205.resolveGhBinary();if(!executable)return JSON.stringify({error:!0,type:"gh-not-found",message:ghNotFoundGuidance(target,number7,repo,logFailed)},null,2);let ghArgs=[target,"view",String(number7)],isLogFailedMode=target==="run"&&logFailed;if(!isLogFailedMode)ghArgs.push("--json",fields.join(","));if(repo)ghArgs.push("--repo",repo);if(isLogFailedMode)ghArgs.push("--log-failed");let run=await _internals205.runExternalTool({executable,args:ghArgs,cwd:directory,timeoutMs:GH_TIMEOUT_MS,maxStdoutBytes:GH_MAX_STDOUT_BYTES,maxStderrBytes:GH_MAX_STDERR_BYTES});if(run.status==="timeout")return JSON.stringify({error:!0,type:"timeout",message:`gh ${target} view timed out after ${GH_TIMEOUT_MS}ms`},null,2);if(run.status==="spawn-error")return JSON.stringify({error:!0,type:"unknown",message:run.message??"gh failed to start"},null,2);if(run.exitCode!==0)return JSON.stringify({error:!0,type:"unknown",message:run.stderr.split(`
|
|
6525
|
-
`)[0]||`gh exited ${run.exitCode}`},null,2);let data,runStatus,runConclusion,runHtmlUrl,runHeadBranch,runHeadSha;if(isLogFailedMode)data=neutralizeUntrustedMarkdown(run.stdout,"GitHub Actions failed-job log");else{let parsed;try{parsed=JSON.parse(run.stdout)}catch{return JSON.stringify({error:!0,type:"unknown",message:"gh output was not valid JSON"},null,2)}if(data=sanitizeParsedJson(parsed),target==="run"&&parsed!==null&&(Array.isArray(parsed)||typeof parsed!=="object"))return JSON.stringify({error:!0,type:"invalid-input",message:"gh run view --json returned an array or primitive instead of a run object"},null,2);if(target==="run"&&parsed&&typeof parsed==="object"){let runData=parsed;runStatus=typeof runData.status==="string"?runData.status:void 0,runConclusion=runData.conclusion===null?null:typeof runData.conclusion==="string"?runData.conclusion:void 0,runHtmlUrl=typeof runData.htmlUrl==="string"?runData.htmlUrl:void 0,runHeadBranch=typeof runData.headBranch==="string"?runData.headBranch:void 0,runHeadSha=typeof runData.headSha==="string"?runData.headSha:void 0}}return JSON.stringify({target,number:number7,repo,fields:isLogFailedMode?[]:fields,command:["gh",...ghArgs],data,outputTruncated:run.stdoutTruncated||run.stderrTruncated,...target==="run"&&{runStatus,runConclusion,runHtmlUrl,runHeadBranch,runHeadSha}},null,2)}}),_internals205={resolveGhBinaryCandidates,resolveExecutableFromPath,resolveGhBinary,runExternalTool};init_zod();init_path_security();init_create_tool();import*as child_process14 from"node:child_process";import*as fs153 from"node:fs";import*as path265 from"node:path";var BLAME_TIMEOUT_MS=30000,MAX_OUTPUT_LINES2=500,MAX_PATH_LENGTH2=500,MAX_LINE_NUMBER=1e6,
|
|
6525
|
+
`)[0]||`gh exited ${run.exitCode}`},null,2);let data,runStatus,runConclusion,runHtmlUrl,runHeadBranch,runHeadSha;if(isLogFailedMode)data=neutralizeUntrustedMarkdown(run.stdout,"GitHub Actions failed-job log");else{let parsed;try{parsed=JSON.parse(run.stdout)}catch{return JSON.stringify({error:!0,type:"unknown",message:"gh output was not valid JSON"},null,2)}if(data=sanitizeParsedJson(parsed),target==="run"&&parsed!==null&&(Array.isArray(parsed)||typeof parsed!=="object"))return JSON.stringify({error:!0,type:"invalid-input",message:"gh run view --json returned an array or primitive instead of a run object"},null,2);if(target==="run"&&parsed&&typeof parsed==="object"){let runData=parsed;runStatus=typeof runData.status==="string"?runData.status:void 0,runConclusion=runData.conclusion===null?null:typeof runData.conclusion==="string"?runData.conclusion:void 0,runHtmlUrl=typeof runData.htmlUrl==="string"?runData.htmlUrl:void 0,runHeadBranch=typeof runData.headBranch==="string"?runData.headBranch:void 0,runHeadSha=typeof runData.headSha==="string"?runData.headSha:void 0}}return JSON.stringify({target,number:number7,repo,fields:isLogFailedMode?[]:fields,command:["gh",...ghArgs],data,outputTruncated:run.stdoutTruncated||run.stderrTruncated,...target==="run"&&{runStatus,runConclusion,runHtmlUrl,runHeadBranch,runHeadSha}},null,2)}}),_internals205={resolveGhBinaryCandidates,resolveExecutableFromPath,resolveGhBinary,runExternalTool};init_zod();init_path_security();init_create_tool();import*as child_process14 from"node:child_process";import*as fs153 from"node:fs";import*as path265 from"node:path";var BLAME_TIMEOUT_MS=30000,MAX_OUTPUT_LINES2=500,MAX_PATH_LENGTH2=500,MAX_LINE_NUMBER=1e6,SHELL_METACHARACTERS4=/[;|&$`(){}<>!'"]/,BINARY_EXTENSIONS=new Set([".png",".jpg",".jpeg",".gif",".bmp",".ico",".svg",".webp",".mp3",".mp4",".wav",".avi",".mov",".wmv",".flv",".zip",".tar",".gz",".rar",".7z",".bz2",".pdf",".doc",".docx",".xls",".xlsx",".ppt",".pptx",".exe",".dll",".so",".dylib",".bin",".dat",".o",".obj",".woff",".woff2",".ttf",".eot",".otf",".sqlite",".db"]);function validateFilePath(filePath){if(!filePath||filePath.length===0)return"file path is required";if(filePath.length>MAX_PATH_LENGTH2)return`file path exceeds maximum length of ${MAX_PATH_LENGTH2}`;if(path265.isAbsolute(filePath)||/^[A-Za-z]:[\\/]/.test(filePath)||filePath.startsWith("\\\\"))return"absolute paths are not allowed; use a relative path from the project root";if(containsPathTraversal(filePath))return"path traversal detected";if(containsControlChars(filePath))return"file path contains control characters";if(SHELL_METACHARACTERS4.test(filePath))return"file path contains shell metacharacters";if(filePath.startsWith("-"))return'file path cannot start with "-"';return null}function validateLineNumber(value,name){if(typeof value>"u")return null;if(typeof value!=="number"||!Number.isInteger(value)||value<1)return`${name} must be a positive integer`;if(value>MAX_LINE_NUMBER)return`${name} exceeds maximum value of ${MAX_LINE_NUMBER}`;return null}function isBinaryFile2(filePath){let ext=path265.extname(filePath).toLowerCase();return BINARY_EXTENSIONS.has(ext)}function parsePorcelainBlame(output,linesCap){let entries=[],cappedLines=output.split(`
|
|
6526
6526
|
`).slice(0,linesCap*8),commitCache=new Map,currentSha="",currentLine=0,currentAuthor="",currentAuthorTime="",currentSummary="";for(let rawLine of cappedLines){let headerMatch=rawLine.match(/^([0-9a-f]{40})\s+(\d+)\s+(\d+)/);if(headerMatch){currentSha=headerMatch[1],currentLine=Number.parseInt(headerMatch[3],10);let cached3=commitCache.get(currentSha);if(cached3)currentAuthor=cached3.author,currentAuthorTime=cached3.authorTime,currentSummary=cached3.summary;else currentAuthor="",currentAuthorTime="",currentSummary="";continue}if(rawLine.startsWith("author ")){currentAuthor=rawLine.slice(7);let meta3=commitCache.get(currentSha);if(!meta3)meta3={author:"",authorTime:"",summary:""},commitCache.set(currentSha,meta3);meta3.author=currentAuthor;continue}if(rawLine.startsWith("author-time ")){currentAuthorTime=rawLine.slice(12);let meta3=commitCache.get(currentSha);if(!meta3)meta3={author:"",authorTime:"",summary:""},commitCache.set(currentSha,meta3);meta3.authorTime=currentAuthorTime;continue}if(rawLine.startsWith("summary ")){currentSummary=rawLine.slice(8);let meta3=commitCache.get(currentSha);if(!meta3)meta3={author:"",authorTime:"",summary:""},commitCache.set(currentSha,meta3);meta3.summary=currentSummary;continue}if(rawLine.startsWith("\t")){if(entries.push({line:currentLine,sha:currentSha.slice(0,8),author:currentAuthor,authorTime:currentAuthorTime,summary:currentSummary,content:rawLine.slice(1)}),entries.length>=linesCap)break}}return entries.slice(0,linesCap)}var git_blame=createSwarmTool({description:"Analyze per-line git blame metadata for a file. Returns sha (abbreviated), author, date (ISO), summary, and content for each line. Uses git blame --porcelain. Rejects binary files and validates paths.",args:{file:exports_external.string().describe("Relative file path to blame (required, relative to project root)"),start:exports_external.number().optional().describe("Optional start line number (1-indexed). Requires end parameter."),end:exports_external.number().optional().describe("Optional end line number (1-indexed, inclusive). Requires start parameter.")},async execute(args2,directory){let fileInput,startInput,endInput;try{if(args2&&typeof args2==="object"){let obj=args2;fileInput=typeof obj.file==="string"?obj.file:void 0,startInput=typeof obj.start==="number"?obj.start:void 0,endInput=typeof obj.end==="number"?obj.end:void 0}}catch{}if(!fileInput)return JSON.stringify({error:"file path is required",file:String(fileInput??""),lineCount:0,lines:[]});let file3=fileInput,pathError=validateFilePath(file3);if(pathError)return JSON.stringify({error:pathError,file:file3,lineCount:0,lines:[]});let startError=validateLineNumber(startInput,"start");if(startError)return JSON.stringify({error:startError,file:file3,lineCount:0,lines:[]});let endError=validateLineNumber(endInput,"end");if(endError)return JSON.stringify({error:endError,file:file3,lineCount:0,lines:[]});if(startInput!==void 0&&endInput===void 0||startInput===void 0&&endInput!==void 0)return JSON.stringify({error:"both start and end must be provided together for a line range",file:file3,lineCount:0,lines:[]});if(startInput!==void 0&&endInput!==void 0&&startInput>endInput)return JSON.stringify({error:"start must be less than or equal to end",file:file3,lineCount:0,lines:[]});let resolvedPath=path265.resolve(directory,file3);if(!fs153.existsSync(resolvedPath))return JSON.stringify({error:`file not found: ${file3}`,file:file3,lineCount:0,lines:[]});let realDir=fs153.realpathSync(directory),realPath=fs153.realpathSync(resolvedPath),relative64=path265.relative(realDir,realPath);if(relative64.startsWith("..")||path265.isAbsolute(relative64))return JSON.stringify({error:"file path resolves outside the workspace",file:file3,lineCount:0,lines:[]});if(fs153.statSync(resolvedPath).isDirectory())return JSON.stringify({error:"path is a directory, not a file",file:file3,lineCount:0,lines:[]});if(isBinaryFile2(file3))return JSON.stringify({error:"binary files are not supported for git blame",file:file3,lineCount:0,lines:[]});let gitArgs=["blame","--porcelain"];if(startInput!==void 0&&endInput!==void 0)gitArgs.push("-L",`${startInput},${endInput}`);gitArgs.push("--",file3);let result=child_process14.spawnSync("git",gitArgs,{cwd:directory,encoding:"utf-8",timeout:BLAME_TIMEOUT_MS,windowsHide:!0,maxBuffer:5242880,stdio:["ignore","pipe","pipe"]});if(result.error){if("code"in result.error&&result.error.code==="ETIMEDOUT")return JSON.stringify({error:"git blame timed out",file:file3,lineCount:0,lines:[]});let message=result.error instanceof Error?result.error.message:String(result.error);if(message.includes("ENOENT")||message.includes("not found"))return JSON.stringify({error:"git is not available or not in PATH",file:file3,lineCount:0,lines:[]});return JSON.stringify({error:`git execution failed: ${message}`,file:file3,lineCount:0,lines:[]})}if(result.status!==0){let stderr=(result.stderr??"").trim();if(stderr.includes("not a git repository")||stderr.includes("not in a git repository"))return JSON.stringify({error:"not a git repository",file:file3,lineCount:0,lines:[]});if(stderr.includes("no such path")||stderr.includes("did not match any files"))return JSON.stringify({error:`file not tracked by git: ${file3}`,file:file3,lineCount:0,lines:[]});return JSON.stringify({error:`git blame failed: ${stderr||`exit code ${result.status}`}`,file:file3,lineCount:0,lines:[]})}if(result.signal==="SIGTERM"||result.signal==="SIGKILL")return JSON.stringify({error:"git blame timed out",file:file3,lineCount:0,lines:[]});let stdout=result.stdout??"";if(!stdout.trim())return JSON.stringify({error:"no blame output (file may be empty or untracked)",file:file3,lineCount:0,lines:[]});let lines=parsePorcelainBlame(stdout,MAX_OUTPUT_LINES2).map((entry)=>({line:entry.line,sha:entry.sha,author:entry.author,date:Number.parseInt(entry.authorTime,10)>0?new Date(Number.parseInt(entry.authorTime,10)*1000).toISOString().slice(0,10):entry.authorTime,summary:entry.summary,content:entry.content})),resultJson={file:file3,lineCount:lines.length,lines};return JSON.stringify(resultJson,null,2)}});init_zod();init_knowledge_validator();function scanInvisibleFormatChars2(text){let findings=[],matches=text.match(INVISIBLE_FORMAT_CHARS);if(matches!==null&&matches.length>0)for(let match of matches)findings.push({pattern:"invisible_format_chars",field:"external_content",description:`Invisible format characters detected (${matches.length} occurrence(s))`,severity:"error",match:match.slice(0,100)});return findings}function neutralizeThreatPatterns(text,findings){if(findings.length===0)return text;let result=text;for(let finding of findings.filter((f)=>f.severity==="error")){let escapedMatch=finding.match.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),pattern=new RegExp(escapedMatch,"g");result=result.replace(pattern,()=>`[EXTERNAL_CONTENT_THREAT: ${finding.pattern}] ${finding.match} [/EXTERNAL_CONTENT_THREAT]`)}return result}function scanExternalContent(text,options){let trustLevel=options?.trustLevel??"low",maxLength=options?.maxLength??50000;if(text==null)text="";let originalLength=text.length,findings=[];if(text.length>maxLength)findings.push({pattern:"oversized_content",field:"external_content",description:`External content exceeds safe size threshold (${text.length} > ${maxLength} bytes)`,severity:"error",match:`${text.length} bytes`});findings.push(...scanInvisibleFormatChars2(text));for(let entry of PROMPT_INJECTION_PATTERNS){let match=entry.pattern.exec(text);if(match!==null)findings.push({pattern:entry.name,field:"external_content",description:entry.description,severity:entry.severity,match:match[0]})}for(let entry of UNSAFE_INSTRUCTION_PATTERNS){let match=entry.pattern.exec(text);if(match!==null)findings.push({pattern:entry.name,field:"external_content",description:entry.description,severity:entry.severity,match:match[0]})}let promoteWarnings=trustLevel==="low",modulatedFindings=findings.map((f)=>promoteWarnings&&f.severity==="warning"?{...f,severity:"error"}:f),hasErrors=modulatedFindings.some((f)=>f.severity==="error"),hasWarnings=modulatedFindings.some((f)=>f.severity==="warning"),threatLevel;if(hasErrors)threatLevel="error";else if(hasWarnings)threatLevel="warning";else threatLevel="none";let neutralized=neutralizeThreatPatterns(text,modulatedFindings.filter((f)=>f.severity==="error"));return{clean:threatLevel==="none",findings:modulatedFindings,threatLevel,originalLength,neutralized}}init_create_tool();var GITINGEST_TIMEOUT_MS=1e4,GITINGEST_MAX_RESPONSE_BYTES=5242880,GITINGEST_MAX_RETRIES=2,delay3=(ms)=>new Promise((resolve107)=>setTimeout(resolve107,ms));async function fetchGitingest(args2){for(let attempt=0;attempt<=GITINGEST_MAX_RETRIES;attempt++)try{let controller=new AbortController,timeoutId=setTimeout(()=>controller.abort(),GITINGEST_TIMEOUT_MS),response=await fetch("https://gitingest.com/api/ingest",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({input_text:args2.url,max_file_size:args2.maxFileSize??50000,pattern:args2.pattern??"",pattern_type:args2.patternType??"exclude"}),signal:controller.signal});if(clearTimeout(timeoutId),response.status>=500&&attempt<GITINGEST_MAX_RETRIES){let backoff=200*2**attempt;await delay3(backoff);continue}if(response.status>=400&&response.status<500)throw Error(`gitingest API error: ${response.status} ${response.statusText}`);if(!response.ok)throw Error(`gitingest API error: ${response.status} ${response.statusText}`);let contentLength=Number(response.headers.get("content-length"));if(Number.isFinite(contentLength)&&contentLength>GITINGEST_MAX_RESPONSE_BYTES)throw Error("gitingest response too large");let text,reader=response.body?.getReader();if(reader){let buffer="",decoder=new TextDecoder,totalBytes=0;try{while(!0){let{done,value}=await reader.read();if(done)break;if(totalBytes+=value.byteLength,totalBytes>GITINGEST_MAX_RESPONSE_BYTES)throw Error("gitingest response too large");buffer+=decoder.decode(value,{stream:!0})}buffer+=decoder.decode(),text=buffer}finally{reader.cancel().catch(()=>{})}}else text=await response.text();if(Buffer.byteLength(text)>GITINGEST_MAX_RESPONSE_BYTES)throw Error("gitingest response too large");let data;try{data=JSON.parse(text)}catch{throw Error(`gitingest API returned non-JSON response (${text.length} chars, starts: ${text.slice(0,80)})`)}let combined=`${data.summary}
|
|
6527
6527
|
|
|
6528
6528
|
${data.tree}
|