opencode-swarm 7.200.5 → 7.200.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/binaries/win32-arm64/swarm-sandbox-runner.exe +0 -0
- package/binaries/win32-x64/swarm-sandbox-runner.exe +0 -0
- package/dist/cli/{attest-task-0k72fh70.js → attest-task-rp4xn5wh.js} +31 -27
- package/dist/cli/{auto-checkpoint-8g004dar.js → auto-checkpoint-a6x7bw5k.js} +4 -4
- package/dist/cli/{checkpoint-18wx2473.js → checkpoint-kpgmse11.js} +8 -8
- package/dist/cli/{coder-settlement-r2q6pkxc.js → coder-settlement-f54sfmaj.js} +4 -3
- package/dist/cli/{config-doctor-h071vxsj.js → config-doctor-hpakt9zz.js} +7 -7
- package/dist/cli/{core-6767154r.js → core-m2x9w49f.js} +1 -1
- package/dist/cli/{curator-drift-gd7tckag.js → curator-drift-hxfzkkhg.js} +5 -5
- package/dist/cli/{curator-pf0edk2z.js → curator-ghjq55v7.js} +25 -25
- package/dist/cli/{curator-llm-factory-mf701qb7.js → curator-llm-factory-b3hk73vd.js} +25 -25
- package/dist/cli/{doctor-knowledge-receipt-phase-id-zz0tz3pt.js → doctor-knowledge-receipt-phase-id-wk9vry5a.js} +4 -4
- package/dist/cli/{evidence-summary-service-awjxt2am.js → evidence-summary-service-gf50zpwx.js} +9 -9
- package/dist/cli/{gate-evidence-tvkhkqwy.js → gate-evidence-7my0f82h.js} +7 -2
- package/dist/cli/{guardrail-explain-m70anx1g.js → guardrail-explain-e1ck0csp.js} +26 -26
- package/dist/cli/{guardrail-log-3sf6n33b.js → guardrail-log-hkkkwmj1.js} +3 -3
- package/dist/cli/{guardrail-reset-t94jbv1q.js → guardrail-reset-wwnbcexb.js} +25 -25
- package/dist/cli/{hive-promoter-60h9tqgs.js → hive-promoter-4nzbfwcd.js} +25 -25
- package/dist/cli/{index-hfnj4s6r.js → index-0fbtnkyw.js} +25 -25
- package/dist/cli/{index-ryrg48c7.js → index-223g5dj9.js} +5 -5
- package/dist/cli/{index-yamz6830.js → index-39pge60a.js} +1 -1
- package/dist/cli/{index-cy2gbs5b.js → index-5djd4vrn.js} +1 -1
- package/dist/cli/{index-1by2qd8n.js → index-6e75mvmn.js} +1 -1
- package/dist/cli/{index-b4amh1n3.js → index-6phyfsvn.js} +3 -3
- package/dist/cli/{index-se501ytb.js → index-7r9yg7h1.js} +1 -1
- package/dist/cli/{index-8c51asrp.js → index-87kk5dqm.js} +232 -97
- package/dist/cli/{index-687c2ze1.js → index-8k6jd7a9.js} +3 -3
- package/dist/cli/{index-10myvh2k.js → index-bgcanr26.js} +1 -1
- package/dist/cli/{index-5qajesjq.js → index-c0dbzf9v.js} +3 -3
- package/dist/cli/{index-3x8mz39c.js → index-f3ed5wde.js} +1 -1
- package/dist/cli/{index-twwdx79t.js → index-f4tht67a.js} +1 -1
- package/dist/cli/{index-74n7sz4s.js → index-g5hghxgw.js} +1 -1
- package/dist/cli/{index-dsqavehz.js → index-h9hgxbsw.js} +1 -1
- package/dist/cli/{index-k01n01sc.js → index-jfkzhyqs.js} +3 -3
- package/dist/cli/{index-1asbb0r4.js → index-k69vjyfm.js} +1 -1
- package/dist/cli/{index-xh861gf3.js → index-kmnyh4r1.js} +2 -2
- package/dist/cli/{index-ee59rzwk.js → index-mkkwhrtn.js} +2 -2
- package/dist/cli/{index-vxbj42j0.js → index-mnpcwcqf.js} +2 -2
- package/dist/cli/{index-g1b5xxzc.js → index-p61vaebj.js} +5 -4
- package/dist/cli/{index-826kptfe.js → index-q8fy8cxa.js} +3 -3
- package/dist/cli/{index-h8419k5d.js → index-qc3qqknb.js} +4 -4
- package/dist/cli/{index-4mjfdpte.js → index-ramxwbtt.js} +6 -6
- package/dist/cli/{index-1akazdbj.js → index-rjtf507t.js} +48 -3
- package/dist/cli/{index-pvj101jx.js → index-sy15gtjr.js} +3 -3
- package/dist/cli/{index-xdk3cxs9.js → index-vhkk8grb.js} +27 -27
- package/dist/cli/{index-phz90w3t.js → index-vsqc38a0.js} +1 -1
- package/dist/cli/{index-vz1fh1v3.js → index-wkz6w3yy.js} +3 -3
- package/dist/cli/{index-wyfag7r7.js → index-y76sev7j.js} +2 -2
- package/dist/cli/index.js +26 -26
- package/dist/cli/{knowledge-escalator-3096yt7j.js → knowledge-escalator-cx03qhmc.js} +7 -7
- package/dist/cli/{knowledge-events-st3j22za.js → knowledge-events-cfdd3syn.js} +5 -5
- package/dist/cli/{knowledge-store-9q8jvd0p.js → knowledge-store-fgwc40g2.js} +1 -1
- package/dist/cli/{knowledge-validator-fak1fvdm.js → knowledge-validator-hvah3jxx.js} +2 -2
- package/dist/cli/{mcp-shvt5c9b.js → mcp-1crekab3.js} +1 -1
- package/dist/cli/{model-preflight-cxhdzc9c.js → model-preflight-knjgtnwb.js} +25 -25
- package/dist/cli/{pending-delegations-tjj8nhmm.js → pending-delegations-3a2tgmgq.js} +2 -2
- package/dist/cli/{pr-subscriptions-xtnbfg8m.js → pr-subscriptions-8yprtmt7.js} +1 -1
- package/dist/cli/{pr-workflow-gate-24ytg64p.js → pr-workflow-gate-fcpvkwg8.js} +25 -25
- package/dist/cli/{scan-cursor-drax4dt3.js → scan-cursor-a776c7b6.js} +2 -2
- package/dist/cli/{schema-epr5xxb0.js → schema-evj1vbxz.js} +1 -1
- package/dist/cli/{scope-persistence-pyn9vb4r.js → scope-persistence-s1e120ba.js} +5 -5
- package/dist/cli/{server-c5b651kg.js → server-exd3q95h.js} +25 -25
- package/dist/cli/{skill-generator-r8kvvbh2.js → skill-generator-6r8pxx5z.js} +8 -8
- package/dist/cli/{snapshot-coordination-init-wnt85258.js → snapshot-coordination-init-z8b9twvf.js} +25 -25
- package/dist/cli/{speckit-checkoff-64p4d5hf.js → speckit-checkoff-hhbcq87w.js} +3 -3
- package/dist/cli/{worktree-collision-ownership-eej2phhm.js → worktree-collision-ownership-waf8d48d.js} +2 -2
- package/dist/cli/{worktree-isolation-xsc0k2n3.js → worktree-isolation-ea4qe5f5.js} +25 -25
- package/dist/gate-evidence.d.ts +20 -0
- package/dist/hooks/guardrails/tool-before.d.ts +1 -1
- package/dist/hooks/shell-executor-context.d.ts +17 -0
- package/dist/hooks/shell-write-detect.d.ts +26 -0
- package/dist/host/v2/hooks.d.ts +20 -0
- package/dist/host/v2/types.d.ts +27 -0
- package/dist/index.js +17 -17
- 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.200.5",description:"Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",main:"dist/index.js",types:"dist/index.d.ts",exports:{".":{types:"./dist/index.d.ts",default:"./dist/index.js"},"./package.json":"./package.json"},bin:{"opencode-swarm":"./dist/cli/index.js"},type:"module",engines:{bun:">=1.3.13",node:">=22.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/swarm-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/swarm-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","tests/fixtures/memory-recall-heldout","opencode-swarm.schema.json","README.md","LICENSE"],scripts:{clean:`bun -e "require('fs').rmSync('dist',{recursive:true,force:true})"`,build:"bun run clean && bun run scripts/generate-config-schema.ts && 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","validate:repo":"bun scripts/ci/repository-validation.ts","drift:check":"bun run scripts/drift-check.ts","check:pre-push":"bun run scripts/drift-check.ts --enforce --no-report && bun run check:registry-citations","schema:generate":"bun run scripts/generate-config-schema.ts","generate:commands-docs":"bun run scripts/generate-commands-docs.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:2669":"node scripts/repro-2669.mjs","repro:2670":"node scripts/repro-2670.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","repro:2487":"bun build scripts/repro-2487-parity-entry.ts --outdir dist-build-test/repro-2487 --target node --format esm && node scripts/repro-2487-parity.mjs","check:events":"bun run scripts/check-event-contract.ts","check:retention":"bun run scripts/check-retention-registry.ts","check:core-events":"bun run scripts/check-core-events-usage.ts","check:shell-audit":"bun run scripts/check-shell-audit-usage.ts","check:trajectory-store":"bun run scripts/check-trajectory-store-usage.ts","check:mock-cleanup":"bun run scripts/check-mock-cleanup.ts","check:invariants":"bun run scripts/check-invariants.ts","check:token-formula":"bun run scripts/check-token-formula.ts","check:cross-contamination":"bun run scripts/check-cross-contamination.ts","check:test-clock":"bun run scripts/check-test-clock.ts","check:test-file-cap":"bun run scripts/check-test-file-cap.ts","check:test-tmpdir":"bun run scripts/check-test-tmpdir.ts","check:bash-portability":"bun run scripts/check-bash-portability.ts","check:pending-fragment":"bun run scripts/check-pending-fragment.ts","check:gate-portability":"bun run scripts/check-gate-portability.ts","check:bare-spawn":"bun run scripts/check-bare-executable-spawn.ts","check:error-channel-discard":"bun run scripts/check-error-channel-discard.ts","check:path-identity":"bun run scripts/check-path-identity.ts","check:registry-citations":"bun run scripts/check-registry-citations.ts","check:memory-recall":"bun run scripts/memory-recall-regression.ts","check:retrieval-quality":"bun run scripts/retrieval-quality-regression.ts"},dependencies:{"@modelcontextprotocol/sdk":"^1.30.0","@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.3.6"},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"},peerDependencies:{"@xenova/transformers":"^2.17.2"},peerDependenciesMeta:{"@xenova/transformers":{optional:!0}}}});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, Python, Rust, Go, Dart, Ruby, PHP, and Java",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; with task_id, records the high-priority count as todo_scan gate evidence",agents:["architect","researcher","docs","explorer","coder"],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"]},authorize_pr_review_reentry:{description:"issue a one-use, identity-bound reviewer/test_engineer re-entry authorization for the active PR_REVIEW workflow (issue #2383)",agents:["architect"]},submit_pr_review_result:{description:"submit one child-bound typed result for an active PR-review base or micro discovery lane",agents:[],prWorkflow:{modes:["PR_REVIEW"],capability:"validate"}},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), or as the sanctioned recovery for a bookkeeping-grade hashed-field repair under the critic-gate PLAN FREEZE rule (the reason must state which case applies)",agents:["architect"]},approve_retry_sounding_board:{description:"record a MANUAL critic_sounding_board gate entry to unblock the coder retry circuit-breaker gate when the sounding board returned APPROVED but the mechanical recorder missed it (issue #2703)",agents:["architect"]},recover_rework_task:{description:"recover a task wedged at rework_required when the reviewer/test_engineer verdict did not require a code change: write a supervised stage_a_passed so those gates can be re-dispatched without re-running the coder (issue #2755)",agents:["architect"]},recover_stage_a_task:{description:"recover a task wedged in the settlement-backed Stage A deadlock — workflow at idle/blocked while a COMMITTED accepted coder settlement and green post-settlement pre-check proof justify Stage A: write a settlement-backed stage_a_passed so reviewer/test_engineer can be dispatched, without re-running the coder (issue #2828)",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"]},invalidate_pr_feedback_publication:{description:"invalidate the armed PR_FEEDBACK publication generation so approved content can change, superseding every content-dependent approval and reopening the exact scoped rework + fresh-review path (issue #2108)",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, related-problems results) so the /swarm issue --trace workflow can satisfy its recurrence gate before commit-pr handoff",agents:["architect"]},record_branch_freshness:{description:"record the Phase 0 branch-freshness outcome (synced / behind:<n> / fetch-failed:<reason> plus optional user override) so the /swarm issue --trace workflow can pass its freshness gate before transitioning to PLAN (issue #2564)",agents:["architect"]},record_trace_validation:{description:"record one per-phase trace-check.sh validator outcome (phase, pass/fail, reviewedCommit, treeId) so the /swarm issue --trace workflow can satisfy its validator-receipt gate before commit-pr handoff (issue #2564)",agents:["architect"]},record_merge_approval:{description:"record the human merge approval bound to the exact PR head SHA so the /swarm issue --trace workflow reaches its terminal merge_approval_recorded state — recorded for audit only, never certified or driven by the plugin (issue #2564)",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; a destructive restore previews first and requires the confirm_token issued in the preview (#2946)",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; reviewer verdicts marked `UNVERIFIED` persist to the findings ledger as `PENDING` records routed back to the reviewer — do not resubmit a row whose verdict is already recorded",agents:["architect"]},pr_review_submission:{description:"submit a settled, head-bound PR review to GitHub through the gh PR Review API after the PR_REVIEW gate clears; architect-only, refuses while a gate is active or the run was aborted after settlement",agents:["architect"]},export_pr_review_partial_results:{description:"export the validated partial results of an ABORTED PR_REVIEW run as a partial, non-authoritative artifact bound per-item to receipt-authenticated findings; architect-only, requires the gate cleared and an abort event binding session and head, never implies completion or feedback consent",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"]},prepare_pr_feedback_commit_message:{description:"author a PR_FEEDBACK commit message that cannot go inline (e.g. a Co-Authored-By trailer) into a file OUTSIDE the repository; returns the path for git commit -F",agents:["architect"]},test_runner:{description:"auto-detect and run tests",agents:["architect","reviewer","critic_finding_validator","test_engineer"]},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; test selection comes from explicit files (override) or source_files derived via the impact analyzer with a typed bounded fallback",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:"preflight every applicable phase gate, report all blockers, and atomically commit a current passing snapshot",agents:["architect"]},run_phase_review:{description:"run the bounded phase-final review engine and persist complete content-addressed review evidence",agents:["architect"]},repair_gate_evidence:{description:"quarantine recoverable exact-task gate evidence, rebuild from durable requirements, recover receipt-backed legacy marker wedges or the exact sentinel-only historical reset, and refuse every other receipt-less reconstruction",agents:["architect"]},repair_knowledge_receipt_ledger:{description:"validate or repair authoritative knowledge receipts, preserve corrupt authority in bounded quarantine, require scoped re-evaluation, and backfill stable phase ids across the whole ledger (operation backfill_phase_id; phase/session_id do not scope the backfill)",agents:["architect"]},record_directive_override:{description:"record an audited architect override for identified critical-directive violations without bypassing unreadable authority",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"]},scope_validate:{description:"validate shell writes against an inline file scope",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, usageSource (provider|estimated), model-limit with provenance (modelLimitSource: host|override|provider_cap|native|fallback; modelLimitResolution: user_provider_model|user_model|user_default|live_model_limit|static_provider_cap|static_native|static_default; fallbackActive: true when the denominator came from a static table or the flat 128k default — treat headroom as uncertain), 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 and the PR_FEEDBACK publication-generation section (state, attempts, invalidation reason, recovery guidance). For an active PR_REVIEW gate it also projects that derived state read-only: per-boundary settlement (post_explorer / post_reviewer / post_critic), per-lane coverage (accepted, rejected, one-line latest finding), and the bounded candidate inventory, each degrading to a typed unavailable state rather than an absence claim. 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","test_engineer"],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, profile hash, the calling session’s ratchet-tighter overrides, and the EFFECTIVE gates (profile merged with those overrides; durable across restart). 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_receipt_status:{description:"receipt status",agents:["architect"]},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_memory_outcome:{description:"record useful, dead-end, or corrected outcomes and, when enabled, synchronously refresh deterministic memory lessons",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; each lane agent must be a registered generated agent name (unregistered bare roles are refused on multi-swarm hosts); launch_timeout_ms is only a promptAsync acceptance budget, not a lane runtime timeout; poll incrementally with collect_lane_results (wait omitted), or join with wait: true for all results",agents:["architect"]},collect_lane_results:{description:"collect/poll a dispatch_lanes_async batch — OBSERVATION ONLY; it can never cancel or abort a lane. A presumed-stale sweep runs on every call, settling lanes past the horizon: idle host to stale, unobservable host to a typed liveness error. The wait budget (timeout_ms) bounds this observer call only — its expiry, a missing messages client, or a degraded liveness probe never kills a lane, never proves it died, and never settles anything. If a collection returns pending lanes, poll again first; busy/retry host status is live evidence, not failure. Cancellation is a distinct, explicit, authorized, potentially destructive action: use cancel_lane_batch (confirm: true + reason), never this tool. An explicit operator cancellation settles as the distinct operator_cancelled class — not liveness. Unsettled lanes are reported in pending_lanes (batch_id, lane_id, status, output_ref) regardless of include_pending. Does not advance workflow gates. Settled-lane inline output is delivered once: later polls set output_omitted_repeat: true and omit output but keep output_ref for retrieval via retrieve_lane_output.",agents:["architect"]},cancel_lane_batch:{description:"cancel ACTIVE lanes of a dispatch_lanes_async batch — the only cancellation surface (collect_lane_results cannot cancel). Destructive and authorization-gated: requires confirm: true + a bounded reason, recorded on cancelled terminals as the distinct operator_cancelled class (never liveness; not auto-retryable, never consumes retry budget — re-dispatch explicitly). Race-safe per lane: busy/retry refused (live work is never destroyed — human force path: /swarm abort-pr-workflow); degraded/absent status probe refuses the whole batch fail-closed; idle or host-unknown sessions may be cancelled; a child completing in the race window is preserved; an abort timeout never claims cancellation.",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_critic:{description:"dispatch a read-only critic agent to evaluate boundary conditions for a completed Lean Turbo phase (satisfies the turbo.lean.phase_critic gate)",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_next_wave:{description:"Epic Mode: the single, idempotent way forward while an epic is open. Closes the active wave once every task is resolved (recording per-task outcomes and declared-vs-actual divergence, which Epic learning uses to plan later waves), keeps phases in order, and issues the next wave of disjoint tasks with dispatch instructions. Returns a status: dispatch | declare-scopes | in-progress | blocked | phase-ready-for-review | epic-complete | refused. Requires `epic.mode.enabled: true` and an epic opened by `/swarm epic start`.",agents:[]},epic_phase_review:{description:"Epic Mode phase readiness: dispatch a read-only phase reviewer, then (only if it APPROVES) a read-only phase critic over the completed phase; parse both verdicts from the agents and record them to .swarm/evidence/{phase}/epic-phase-review.json. Required by phase_complete while an epic is open for the current plan; re-run after any fix (evidence is bound to the plan and phase task evidence).",agents:[]}},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 scanOverrideForDangerousKeys(value,path,depth){if(depth>=10)return;if(Array.isArray(value)){for(let i=0;i<value.length;i++)scanOverrideForDangerousKeys(value[i],`${path}[${i}]`,depth+1);return}if(typeof value!=="object"||value===null)return;for(let key of Object.keys(value)){if(DANGEROUS_MERGE_KEYS.has(key))throw new DangerousMergeKeyError(key,path);scanOverrideForDangerousKeys(value[key],`${path}.${key}`,depth+1)}}function deepMergeInternal(base,override,depth,path){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,`${path}.${key}`);else result[key]=overrideVal}return result}function deepMerge(base,override){if(!base)return override;if(!override)return base;return scanOverrideForDangerousKeys(override,"$",0),deepMergeInternal(base,override,0,"$")}var MAX_MERGE_DEPTH=10,DANGEROUS_MERGE_KEYS,DangerousMergeKeyError;var init_merge=__esm(()=>{DANGEROUS_MERGE_KEYS=new Set(["__proto__","constructor","prototype"]);DangerousMergeKeyError=class DangerousMergeKeyError extends Error{key;path;constructor(key,path){super(`deepMerge refused dangerous key "${key}" at "${path}": prototype-pollution carriers (__proto__/constructor/prototype) are never merged`);this.key=key;this.path=path;this.name="DangerousMergeKeyError"}}});function freezeSet(items,name="CLAUDE_CODE_NATIVE_COMMANDS"){let set=new Set(items),proxy=new Proxy(set,{get(target,prop){if(prop==="add"||prop==="delete"||prop==="clear")return()=>{throw TypeError(`${name} 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(`${name} is readonly`)},deleteProperty(){throw TypeError(`${name} is readonly`)},defineProperty(){throw TypeError(`${name} is readonly`)},setPrototypeOf(){throw TypeError(`${name} 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,OPENCODE_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,EPIC_TOOL_NAMES,EPIC_AGENT_TOOL_MAP,SKILL_TOOL_NAMES,SKILL_AGENT_TOOL_MAP,PR_REVIEW_CHILD_TOOL_NAMES,PR_REVIEW_CHILD_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.200.7",description:"Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",main:"dist/index.js",types:"dist/index.d.ts",exports:{".":{types:"./dist/index.d.ts",default:"./dist/index.js"},"./package.json":"./package.json"},bin:{"opencode-swarm":"./dist/cli/index.js"},type:"module",engines:{bun:">=1.3.13",node:">=22.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/swarm-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/swarm-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","tests/fixtures/memory-recall-heldout","opencode-swarm.schema.json","README.md","LICENSE"],scripts:{clean:`bun -e "require('fs').rmSync('dist',{recursive:true,force:true})"`,build:"bun run clean && bun run scripts/generate-config-schema.ts && 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","validate:repo":"bun scripts/ci/repository-validation.ts","drift:check":"bun run scripts/drift-check.ts","check:pre-push":"bun run scripts/drift-check.ts --enforce --no-report && bun run check:registry-citations","schema:generate":"bun run scripts/generate-config-schema.ts","generate:commands-docs":"bun run scripts/generate-commands-docs.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:2669":"node scripts/repro-2669.mjs","repro:2670":"node scripts/repro-2670.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","repro:2487":"bun build scripts/repro-2487-parity-entry.ts --outdir dist-build-test/repro-2487 --target node --format esm && node scripts/repro-2487-parity.mjs","check:events":"bun run scripts/check-event-contract.ts","check:retention":"bun run scripts/check-retention-registry.ts","check:core-events":"bun run scripts/check-core-events-usage.ts","check:shell-audit":"bun run scripts/check-shell-audit-usage.ts","check:trajectory-store":"bun run scripts/check-trajectory-store-usage.ts","check:mock-cleanup":"bun run scripts/check-mock-cleanup.ts","check:invariants":"bun run scripts/check-invariants.ts","check:token-formula":"bun run scripts/check-token-formula.ts","check:cross-contamination":"bun run scripts/check-cross-contamination.ts","check:test-clock":"bun run scripts/check-test-clock.ts","check:test-file-cap":"bun run scripts/check-test-file-cap.ts","check:test-tmpdir":"bun run scripts/check-test-tmpdir.ts","check:bash-portability":"bun run scripts/check-bash-portability.ts","check:pending-fragment":"bun run scripts/check-pending-fragment.ts","check:gate-portability":"bun run scripts/check-gate-portability.ts","check:bare-spawn":"bun run scripts/check-bare-executable-spawn.ts","check:error-channel-discard":"bun run scripts/check-error-channel-discard.ts","check:path-identity":"bun run scripts/check-path-identity.ts","check:registry-citations":"bun run scripts/check-registry-citations.ts","check:memory-recall":"bun run scripts/memory-recall-regression.ts","check:retrieval-quality":"bun run scripts/retrieval-quality-regression.ts"},dependencies:{"@modelcontextprotocol/sdk":"^1.30.0","@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.3.6"},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"},peerDependencies:{"@xenova/transformers":"^2.17.2"},peerDependenciesMeta:{"@xenova/transformers":{optional:!0}}}});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, Python, Rust, Go, Dart, Ruby, PHP, and Java",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; with task_id, records the high-priority count as todo_scan gate evidence",agents:["architect","researcher","docs","explorer","coder"],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"]},authorize_pr_review_reentry:{description:"issue a one-use, identity-bound reviewer/test_engineer re-entry authorization for the active PR_REVIEW workflow (issue #2383)",agents:["architect"]},submit_pr_review_result:{description:"submit one child-bound typed result for an active PR-review base or micro discovery lane",agents:[],prWorkflow:{modes:["PR_REVIEW"],capability:"validate"}},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), or as the sanctioned recovery for a bookkeeping-grade hashed-field repair under the critic-gate PLAN FREEZE rule (the reason must state which case applies)",agents:["architect"]},approve_retry_sounding_board:{description:"record a MANUAL critic_sounding_board gate entry to unblock the coder retry circuit-breaker gate when the sounding board returned APPROVED but the mechanical recorder missed it (issue #2703)",agents:["architect"]},recover_rework_task:{description:"recover a task wedged at rework_required when the reviewer/test_engineer verdict did not require a code change: write a supervised stage_a_passed so those gates can be re-dispatched without re-running the coder (issue #2755)",agents:["architect"]},recover_stage_a_task:{description:"recover a task wedged in the settlement-backed Stage A deadlock — workflow at idle/blocked while a COMMITTED accepted coder settlement and green post-settlement pre-check proof justify Stage A: write a settlement-backed stage_a_passed so reviewer/test_engineer can be dispatched, without re-running the coder (issue #2828)",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"]},invalidate_pr_feedback_publication:{description:"invalidate the armed PR_FEEDBACK publication generation so approved content can change, superseding every content-dependent approval and reopening the exact scoped rework + fresh-review path (issue #2108)",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, related-problems results) so the /swarm issue --trace workflow can satisfy its recurrence gate before commit-pr handoff",agents:["architect"]},record_branch_freshness:{description:"record the Phase 0 branch-freshness outcome (synced / behind:<n> / fetch-failed:<reason> plus optional user override) so the /swarm issue --trace workflow can pass its freshness gate before transitioning to PLAN (issue #2564)",agents:["architect"]},record_trace_validation:{description:"record one per-phase trace-check.sh validator outcome (phase, pass/fail, reviewedCommit, treeId) so the /swarm issue --trace workflow can satisfy its validator-receipt gate before commit-pr handoff (issue #2564)",agents:["architect"]},record_merge_approval:{description:"record the human merge approval bound to the exact PR head SHA so the /swarm issue --trace workflow reaches its terminal merge_approval_recorded state — recorded for audit only, never certified or driven by the plugin (issue #2564)",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; a destructive restore previews first and requires the confirm_token issued in the preview (#2946)",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; reviewer verdicts marked `UNVERIFIED` persist to the findings ledger as `PENDING` records routed back to the reviewer — do not resubmit a row whose verdict is already recorded",agents:["architect"]},pr_review_submission:{description:"submit a settled, head-bound PR review to GitHub through the gh PR Review API after the PR_REVIEW gate clears; architect-only, refuses while a gate is active or the run was aborted after settlement",agents:["architect"]},export_pr_review_partial_results:{description:"export the validated partial results of an ABORTED PR_REVIEW run as a partial, non-authoritative artifact bound per-item to receipt-authenticated findings; architect-only, requires the gate cleared and an abort event binding session and head, never implies completion or feedback consent",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"]},prepare_pr_feedback_commit_message:{description:"author a PR_FEEDBACK commit message that cannot go inline (e.g. a Co-Authored-By trailer) into a file OUTSIDE the repository; returns the path for git commit -F",agents:["architect"]},test_runner:{description:"auto-detect and run tests",agents:["architect","reviewer","critic_finding_validator","test_engineer"]},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; test selection comes from explicit files (override) or source_files derived via the impact analyzer with a typed bounded fallback",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:"preflight every applicable phase gate, report all blockers, and atomically commit a current passing snapshot",agents:["architect"]},run_phase_review:{description:"run the bounded phase-final review engine and persist complete content-addressed review evidence",agents:["architect"]},repair_gate_evidence:{description:"quarantine recoverable exact-task gate evidence, rebuild from durable requirements, recover receipt-backed legacy marker wedges or the exact sentinel-only historical reset, and refuse every other receipt-less reconstruction",agents:["architect"]},repair_knowledge_receipt_ledger:{description:"validate or repair authoritative knowledge receipts, preserve corrupt authority in bounded quarantine, require scoped re-evaluation, and backfill stable phase ids across the whole ledger (operation backfill_phase_id; phase/session_id do not scope the backfill)",agents:["architect"]},record_directive_override:{description:"record an audited architect override for identified critical-directive violations without bypassing unreadable authority",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"]},scope_validate:{description:"validate shell writes against an inline file scope",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, usageSource (provider|estimated), model-limit with provenance (modelLimitSource: host|override|provider_cap|native|fallback; modelLimitResolution: user_provider_model|user_model|user_default|live_model_limit|static_provider_cap|static_native|static_default; fallbackActive: true when the denominator came from a static table or the flat 128k default — treat headroom as uncertain), 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 and the PR_FEEDBACK publication-generation section (state, attempts, invalidation reason, recovery guidance). For an active PR_REVIEW gate it also projects that derived state read-only: per-boundary settlement (post_explorer / post_reviewer / post_critic), per-lane coverage (accepted, rejected, one-line latest finding), and the bounded candidate inventory, each degrading to a typed unavailable state rather than an absence claim. 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","test_engineer"],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, profile hash, the calling session’s ratchet-tighter overrides, and the EFFECTIVE gates (profile merged with those overrides; durable across restart). 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_receipt_status:{description:"receipt status",agents:["architect"]},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_memory_outcome:{description:"record useful, dead-end, or corrected outcomes and, when enabled, synchronously refresh deterministic memory lessons",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; each lane agent must be a registered generated agent name (unregistered bare roles are refused on multi-swarm hosts); launch_timeout_ms is only a promptAsync acceptance budget, not a lane runtime timeout; poll incrementally with collect_lane_results (wait omitted), or join with wait: true for all results",agents:["architect"]},collect_lane_results:{description:"collect/poll a dispatch_lanes_async batch — OBSERVATION ONLY; it can never cancel or abort a lane. A presumed-stale sweep runs on every call, settling lanes past the horizon: idle host to stale, unobservable host to a typed liveness error. The wait budget (timeout_ms) bounds this observer call only — its expiry, a missing messages client, or a degraded liveness probe never kills a lane, never proves it died, and never settles anything. If a collection returns pending lanes, poll again first; busy/retry host status is live evidence, not failure. Cancellation is a distinct, explicit, authorized, potentially destructive action: use cancel_lane_batch (confirm: true + reason), never this tool. An explicit operator cancellation settles as the distinct operator_cancelled class — not liveness. Unsettled lanes are reported in pending_lanes (batch_id, lane_id, status, output_ref) regardless of include_pending. Does not advance workflow gates. Settled-lane inline output is delivered once: later polls set output_omitted_repeat: true and omit output but keep output_ref for retrieval via retrieve_lane_output.",agents:["architect"]},cancel_lane_batch:{description:"cancel ACTIVE lanes of a dispatch_lanes_async batch — the only cancellation surface (collect_lane_results cannot cancel). Destructive and authorization-gated: requires confirm: true + a bounded reason, recorded on cancelled terminals as the distinct operator_cancelled class (never liveness; not auto-retryable, never consumes retry budget — re-dispatch explicitly). Race-safe per lane: busy/retry refused (live work is never destroyed — human force path: /swarm abort-pr-workflow); degraded/absent status probe refuses the whole batch fail-closed; idle or host-unknown sessions may be cancelled; a child completing in the race window is preserved; an abort timeout never claims cancellation.",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_critic:{description:"dispatch a read-only critic agent to evaluate boundary conditions for a completed Lean Turbo phase (satisfies the turbo.lean.phase_critic gate)",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_next_wave:{description:"Epic Mode: the single, idempotent way forward while an epic is open. Closes the active wave once every task is resolved (recording per-task outcomes and declared-vs-actual divergence, which Epic learning uses to plan later waves), keeps phases in order, and issues the next wave of disjoint tasks with dispatch instructions. Returns a status: dispatch | declare-scopes | in-progress | blocked | phase-ready-for-review | epic-complete | refused. Requires `epic.mode.enabled: true` and an epic opened by `/swarm epic start`.",agents:[]},epic_phase_review:{description:"Epic Mode phase readiness: dispatch a read-only phase reviewer, then (only if it APPROVES) a read-only phase critic over the completed phase; parse both verdicts from the agents and record them to .swarm/evidence/{phase}/epic-phase-review.json. Required by phase_complete while an epic is open for the current plan; re-run after any fix (evidence is bound to the plan and phase task evidence).",agents:[]}},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 scanOverrideForDangerousKeys(value,path,depth){if(depth>=10)return;if(Array.isArray(value)){for(let i=0;i<value.length;i++)scanOverrideForDangerousKeys(value[i],`${path}[${i}]`,depth+1);return}if(typeof value!=="object"||value===null)return;for(let key of Object.keys(value)){if(DANGEROUS_MERGE_KEYS.has(key))throw new DangerousMergeKeyError(key,path);scanOverrideForDangerousKeys(value[key],`${path}.${key}`,depth+1)}}function deepMergeInternal(base,override,depth,path){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,`${path}.${key}`);else result[key]=overrideVal}return result}function deepMerge(base,override){if(!base)return override;if(!override)return base;return scanOverrideForDangerousKeys(override,"$",0),deepMergeInternal(base,override,0,"$")}var MAX_MERGE_DEPTH=10,DANGEROUS_MERGE_KEYS,DangerousMergeKeyError;var init_merge=__esm(()=>{DANGEROUS_MERGE_KEYS=new Set(["__proto__","constructor","prototype"]);DangerousMergeKeyError=class DangerousMergeKeyError extends Error{key;path;constructor(key,path){super(`deepMerge refused dangerous key "${key}" at "${path}": prototype-pollution carriers (__proto__/constructor/prototype) are never merged`);this.key=key;this.path=path;this.name="DangerousMergeKeyError"}}});function freezeSet(items,name="CLAUDE_CODE_NATIVE_COMMANDS"){let set=new Set(items),proxy=new Proxy(set,{get(target,prop){if(prop==="add"||prop==="delete"||prop==="clear")return()=>{throw TypeError(`${name} 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(`${name} is readonly`)},deleteProperty(){throw TypeError(`${name} is readonly`)},defineProperty(){throw TypeError(`${name} is readonly`)},setPrototypeOf(){throw TypeError(`${name} 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,OPENCODE_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,EPIC_TOOL_NAMES,EPIC_AGENT_TOOL_MAP,SKILL_TOOL_NAMES,SKILL_AGENT_TOOL_MAP,PR_REVIEW_CHILD_TOOL_NAMES,PR_REVIEW_CHILD_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
|
|
|
@@ -610,7 +610,7 @@ ${squashResult.stdout}`,restore=await runGit3(["checkout","-q","HEAD","--",...in
|
|
|
610
610
|
`.split(`
|
|
611
611
|
`)){let line=rawLine.endsWith("\r")?rawLine.slice(0,-1):rawLine;if(line.startsWith("worktree ")){worktreePath=line.slice(9);continue}if(!line.startsWith("branch ")||!worktreePath)continue;try{fs22.statSync(worktreePath)}catch(error49){let code=error49.code;if(code==="ENOENT"||code==="ENOTDIR")continue;return{status:"uncertain",reason:`registered worktree path "${worktreePath}" is unreadable: ${error49 instanceof Error?error49.message:String(error49)}`}}let branch=line.slice(7);liveBranches.push(branch.startsWith("refs/heads/")?branch.slice(11):branch)}return{status:"ok",liveBranches}}async function readLaneBranchHead(branchName,primaryDir){return runGit3(["rev-parse","--verify","--quiet",`refs/heads/${branchName}`],primaryDir)}async function captureLaneSourceHead(worktreePath,branchName,primaryDir,knownMissing){if(!knownMissing){let fromWorktree=await runGit3(["rev-parse","HEAD"],worktreePath);if(fromWorktree.spawnFailure?.kind!=="cwd-missing")return{result:fromWorktree,sourceWorktreeMissing:!1}}return{result:await readLaneBranchHead(branchName,primaryDir),sourceWorktreeMissing:!0}}async function handleSourceWorktreeGone(branchHead,worktreePath,branchName,primaryDir,provenance){if(!(branchHead.spawnFailure===void 0&&branchHead.exitCode===0&&branchHead.stdout.trim().length>0)){let definitelyAbsent=branchHead.spawnFailure===void 0&&branchHead.exitCode===1;return{failed:!0,stage:definitelyAbsent?SOURCE_WORKTREE_GONE_STAGE:SOURCE_WORKTREE_UNCERTAIN_STAGE,message:definitelyAbsent?`Lane worktree "${worktreePath}" is gone and branch "${branchName}" no longer exists; nothing is recoverable`:`Lane worktree "${worktreePath}" is gone and branch "${branchName}" existence could not be determined: ${branchHead.stderr.trim()||`git exited ${branchHead.exitCode}`}`,...provenance?{provenance}:{}}}let prune=await runGit3(["worktree","prune"],primaryDir);if(prune.exitCode!==0)log(`[worktree] attemptMergeBackFromDirty: worktree prune failed for "${worktreePath}": ${prune.stderr.trim()||prune.stdout.trim()}`);return advisoryWarn(`STALE_LANE_WORKTREE_DETECTED: lane worktree "${worktreePath}" no longer exists. Its stale git registration was pruned, and the merge-back for branch "${branchName}" is being taken from "${primaryDir}" instead. Any uncommitted work in that worktree is unrecoverable; every commit on the branch is preserved.`),null}async function attemptMergeBackFromDirty(worktreePath,branchName,primaryDir,strategy,options={}){let autoCommitted=!1,cleaned=!1,autoCommitFailed=!1,cleanFailed=!1,provenance=options.resume,sourceWorktreeMissing=!1;if(provenance){if(provenance.branchName!==branchName||provenance.strategy!==strategy||options.operationId!==void 0&&provenance.operationId!==options.operationId)return{failed:!0,stage:"reconciliation",message:"Stored merge operation identity does not match this dispatch",provenance};let reconciliation=await reconcileLandedMerge(primaryDir,provenance);if("error"in reconciliation&&reconciliation.error)return{failed:!0,stage:"reconciliation",message:`Unable to reconcile prior merge-back: ${reconciliation.error}`,provenance};if(reconciliation.landed)return{merged:!0,strategy:reconciliation.method==="worktree-match"?"squash-unstaged":strategy,autoCommitted:!1,cleaned:!1,reconciled:!0,provenance};let source=await captureLaneSourceHead(worktreePath,branchName,primaryDir,!1);if(source.sourceWorktreeMissing){let unrecoverable=await handleSourceWorktreeGone(source.result,worktreePath,branchName,primaryDir,provenance);if(unrecoverable)return unrecoverable;sourceWorktreeMissing=!0}let sourceHead=source.result,targetHead=await runGit3(["rev-parse","HEAD"],primaryDir);if(sourceHead.exitCode!==0||targetHead.exitCode!==0||sourceHead.stdout.trim()!==provenance.sourceHead||targetHead.stdout.trim()!==provenance.targetHeadBefore)return{failed:!0,stage:"reconciliation",message:"Stored merge operation did not land and its source or target HEAD has changed",provenance}}if(!provenance&&!sourceWorktreeMissing){let commitResult=await autoCommitDirty(worktreePath);if(commitResult.committed)autoCommitted=!0;else if(commitResult.reason!=="Nothing to commit")autoCommitFailed=!0,log(`[worktree] attemptMergeBackFromDirty: auto-commit failed for worktree "${worktreePath}" branch "${branchName}": ${commitResult.reason}`)}if(!sourceWorktreeMissing){let cleanResult=await cleanUntrackedFiles(worktreePath);if(cleanResult.cleaned)cleaned=!0;else cleanFailed=!0,log(`[worktree] attemptMergeBackFromDirty: clean untracked failed for worktree "${worktreePath}" branch "${branchName}": ${cleanResult.error}`)}if(autoCommitFailed&&cleanFailed)if((await runGit3(["rev-parse","--git-dir"],worktreePath)).spawnFailure?.kind==="cwd-missing"){let unrecoverable=await handleSourceWorktreeGone(await readLaneBranchHead(branchName,primaryDir),worktreePath,branchName,primaryDir,provenance);if(unrecoverable)return unrecoverable;sourceWorktreeMissing=!0,autoCommitFailed=!1,cleanFailed=!1,cleaned=!1}else return{failed:!0,stage:"cleanup",message:"Auto-commit and clean both failed; abandoning worktree",...provenance?{provenance}:{}};let initialOverlapSnapshot=await _internals36.captureMergeOverlapSnapshot(primaryDir,branchName);if("error"in initialOverlapSnapshot)return{failed:!0,stage:"pre-merge",message:initialOverlapSnapshot.error,...provenance?{provenance}:{}};if(!provenance&&(options.operationId||options.onBeforeMerge)){if(!options.operationId)return{failed:!0,stage:"pre-merge",message:"A pre-merge callback requires a stable operationId"};if(provenance={operationId:options.operationId,sourceHead:initialOverlapSnapshot.snapshot.laneHead,targetHeadBefore:initialOverlapSnapshot.snapshot.targetHead,branchName,strategy},options.onBeforeMerge)try{await options.onBeforeMerge(provenance)}catch(error49){return{failed:!0,stage:"pre-merge",message:`Unable to persist merge operation provenance: ${String(error49)}`,provenance}}}let finalOverlapSnapshot=await _internals36.captureMergeOverlapSnapshot(primaryDir,branchName);if("error"in finalOverlapSnapshot)return{failed:!0,stage:"pre-merge",message:finalOverlapSnapshot.error,...provenance?{provenance}:{}};if(finalOverlapSnapshot.snapshot.overlapPaths.length>0)return{partial:!0,stage:"pre-merge-overlap",autoCommitted,cleaned,message:`Primary checkout has overlapping dirty paths with incoming lane changes: ${finalOverlapSnapshot.snapshot.overlapPaths.join(", ")}`,conflictFiles:finalOverlapSnapshot.snapshot.overlapPaths,code:"SETTLEMENT_OVERLAP_BLOCKED",recoveryHint:`ACTION: commit or stash your local changes to the overlapping paths (or run /swarm recover for the preserved lane), then re-dispatch the lane. Overlapping paths: ${finalOverlapSnapshot.snapshot.overlapPaths.join(", ")}`,...provenance?{provenance}:{}};if(!sameOverlapSnapshot(initialOverlapSnapshot.snapshot,finalOverlapSnapshot.snapshot))return{failed:!0,stage:"pre-merge",message:"Primary or lane state changed during overlap preflight; refusing merge-back",...provenance?{provenance}:{}};let landingStrategy=strategy==="merge"&&!options.commitLanding?"squash-unstaged":strategy,mergeResult=await mergeLaneBranch(primaryDir,branchName,landingStrategy,landingStrategy==="merge"&&options.commitLanding?options.landingCommitMessage:void 0);if("merged"in mergeResult&&mergeResult.merged)return{merged:!0,strategy:landingStrategy,autoCommitted,cleaned,...provenance?{reconciled:!1,provenance}:{}};if("conflict"in mergeResult)return{partial:!0,stage:"merge",autoCommitted,cleaned,message:mergeResult.message,conflictFiles:mergeResult.files,...provenance?{provenance}:{}};if("error"in mergeResult)return{failed:!0,stage:"merge",message:mergeResult.error,...provenance?{provenance}:{}};return{failed:!0,stage:"merge",message:"Merge failed with unexpected result",...provenance?{provenance}:{}}}function extractSessionId(branchName){let segments=branchName.trim().split("/");if(segments.length>=3&&segments[0]==="swarm-lane")return segments[1];if(segments.length>=4&&segments[0]==="swarm"&&segments[1]==="lane")return segments[2];return null}async function listLaneBranches(directory){let branches=new Set,result=await runGit3(["branch","--format=%(refname:short)"],directory);if(result.exitCode===0)for(let line of result.stdout.split(`
|
|
612
612
|
`)){let branch=line.trim();if(branch.length>0&&(branch.startsWith("swarm-lane/")||branch.startsWith("swarm/lane/")))branches.add(branch)}return[...branches]}async function cleanupOrphanedBranches(directory,activeSessionIds=[],options={}){let removed=[],skipped=[],skippedRecoveryBranches=[],errors3=[];if(recoveryReadErrored(directory)){log("[worktree] cleanupOrphanedBranches: .swarm/recovery/ read error — skipping all "+"lane-branch deletions this pass (fail-safe for preserved recovery branches).");let branches2=await listLaneBranches(directory);return{removed,skipped:branches2,skippedRecoveryBranches,errors:errors3,recoveryReadError:!0}}let branches=await listLaneBranches(directory);await runGit3(["worktree","prune"],directory);for(let branch of branches){let sessionId=extractSessionId(branch);if(sessionId!==null&&activeSessionIds.includes(sessionId)){skipped.push(branch);continue}if(hasRecoveryRecordForBranch(directory,branch)){skippedRecoveryBranches.push(branch);continue}let deleteResult=await runGit3(["branch",options.preserveUnmerged?"-d":"-D",branch],directory);if(deleteResult.exitCode===0)removed.push(branch);else errors3.push({branch,error:deleteResult.stderr.trim()||deleteResult.stdout.trim()})}return{removed,skipped,skippedRecoveryBranches,errors:errors3}}async function startupOrphanRecovery(directory,activeSessionIds=[]){let warnings=[],pruneResult=await runGit3(["worktree","prune"],directory);if(pruneResult.exitCode!==0)warnings.push(`git worktree prune failed: ${pruneResult.stderr.trim()||pruneResult.stdout.trim()}`);let allBranches=await listLaneBranches(directory),orphanBranches=[];for(let branch of allBranches){let sessionId=extractSessionId(branch);if(sessionId===null||!activeSessionIds.includes(sessionId))orphanBranches.push(branch),warnings.push(`Orphaned swarm-lane branch "${branch}" detected in "${directory}"`)}for(let warning of warnings)log(warning);return{prunedWorktrees:pruneResult.exitCode===0,remainingBranches:orphanBranches,warnings}}var _internals36,MERGE_TIMEOUT_MS=30000,GIT_SPAWN_FAILURE_EXIT_CODE2=1,SOURCE_WORKTREE_GONE_STAGE="source-worktree-gone",SOURCE_WORKTREE_UNCERTAIN_STAGE="source-worktree-uncertain",GIT_OBJECT_ID_PATTERN;var init_merge2=__esm(()=>{init_warning_buffer();init_recovery();init_utils();init_bun_compat();init_git_binary_missing_error();init_git_executable();init_core3();_internals36={bunSpawn,platform:process.platform,sleep:(ms)=>new Promise((resolve22)=>setTimeout(resolve22,ms)),cleanupOrphanedBranches,startupOrphanRecovery,captureMergeOverlapSnapshot,extractSessionId,resolveGitExecutable};GIT_OBJECT_ID_PATTERN=/^[0-9a-f]{40}$|^[0-9a-f]{64}$/});function isSafeGitBranchName(value){if(typeof value!=="string"||!BRANCH_NAME_PATTERN.test(value))return!1;if(value.includes("..")||value.endsWith("/")||value.endsWith("."))return!1;return!value.split("/").some((segment)=>segment.length===0||segment.startsWith(".")||segment.endsWith(".lock"))}function isSafeWorktreePath(value){return typeof value==="string"&&value.length>0&&value.length<=4096&&!value.startsWith("-")&&unsafePathTextReason(value)===null}function formatUnreadableMessage(code,filePath,detail,remediation){throw Error(`${code}: ${filePath} ${detail}. ${remediation}`)}function parseWalObject(raw,filePath,code,remediation){let parsed;try{parsed=JSON.parse(raw)}catch(error49){formatUnreadableMessage(code,filePath,`is not valid JSON (${error49 instanceof Error?error49.message:String(error49)})`,remediation)}if(typeof parsed!=="object"||parsed===null||Array.isArray(parsed))formatUnreadableMessage(code,filePath,"is not a JSON object",remediation);return parsed}function parseCoderSettlementWal(raw,filePath,expectedTaskId){let parsed=parseWalObject(raw,filePath,"CODER_SETTLEMENT_WAL_UNREADABLE","Preserve this file, reconcile the task lane, and only then move it aside."),context=parsed.context,baseline=context?.baseline,worktree=parsed.worktree,provenance=parsed.mergeProvenance;if(parsed.version!==1||!["ABORTED","COMMITTED","DISPATCHED","PREPARED"].includes(String(parsed.state))||typeof parsed.taskId!=="string"||!TASK_ID_PATTERN.test(parsed.taskId)||typeof parsed.transitionId!=="string"||parsed.transitionId.length===0||parsed.transitionId.length>512||typeof parsed.actor!=="string"||parsed.actor.length===0||parsed.actor.length>512||!Number.isInteger(parsed.processId)||(parsed.processId??0)<=0||typeof parsed.runtimeId!=="string"||parsed.runtimeId.length===0||!Number.isInteger(parsed.expectedGeneration)||(parsed.expectedGeneration??-1)<0||!context||!baseline||typeof baseline.directory!=="string"||baseline.directory.length===0||baseline.directory.length>4096||typeof baseline.gitHead!=="string"&&baseline.gitHead!==null||typeof baseline.dirtyHash!=="string"&&baseline.dirtyHash!==null||typeof baseline.prHeadSha!=="string"&&baseline.prHeadSha!==null||typeof baseline.scope!=="string"&&baseline.scope!==null||!Array.isArray(baseline.changedFiles)&&baseline.changedFiles!==null&&baseline.changedFiles!==void 0||Array.isArray(baseline.changedFiles)&&(baseline.changedFiles.length>50000||baseline.changedFiles.some((candidatePath)=>typeof candidatePath!=="string"||candidatePath.length>4096))||!Array.isArray(context.declaredFiles)&&context.declaredFiles!==null||Array.isArray(context.declaredFiles)&&(context.declaredFiles.length>50000||context.declaredFiles.some((candidatePath)=>typeof candidatePath!=="string"||candidatePath.length>4096))||parsed.observedFiles!==void 0&&(!Array.isArray(parsed.observedFiles)||parsed.observedFiles.length>50000||parsed.observedFiles.some((candidatePath)=>typeof candidatePath!=="string"||candidatePath.length>4096||Array.isArray(context.declaredFiles)&&context.declaredFiles.length>0&&!isPathWithinDeclaredScope(candidatePath,context.declaredFiles,baseline.directory)))||worktree!==void 0&&(typeof worktree.callID!=="string"||typeof worktree.parentSessionId!=="string"||typeof worktree.taskId!=="string"||worktree.taskId!==parsed.taskId||!isSafeWorktreePath(worktree.worktreePath)||!isSafeGitBranchName(worktree.branchName)||typeof worktree.worktreeId!=="string"||typeof worktree.worktreeSessionId!=="string"||!["merge","rebase","cherry-pick"].includes(String(worktree.mergeStrategy))||!Number.isInteger(worktree.laneIndex))||provenance!==void 0&&(typeof provenance.operationId!=="string"||provenance.operationId!==parsed.transitionId||typeof provenance.sourceHead!=="string"||!GIT_OBJECT_ID_PATTERN.test(provenance.sourceHead)||typeof provenance.targetHeadBefore!=="string"||!GIT_OBJECT_ID_PATTERN.test(provenance.targetHeadBefore)||!isSafeGitBranchName(provenance.branchName)||worktree!==void 0&&(provenance.branchName!==worktree.branchName||provenance.strategy!==worktree.mergeStrategy)||!["merge","rebase","cherry-pick"].includes(String(provenance.strategy)))||typeof parsed.recordedAt!=="string"||parsed.state==="PREPARED"&&typeof parsed.accepted!=="boolean"||parsed.cleanupComplete!==void 0&&typeof parsed.cleanupComplete!=="boolean"||parsed.settlementFailed!==void 0&&typeof parsed.settlementFailed!=="boolean"||parsed.abortReason!==void 0&&(typeof parsed.abortReason!=="string"||parsed.abortReason.length===0||parsed.abortReason.length>512))formatUnreadableMessage("CODER_SETTLEMENT_WAL_UNREADABLE",filePath,"is not a valid v1 coder-settlement WAL","Preserve this file, reconcile the task lane, and only then move it aside.");if(expectedTaskId&&parsed.taskId!==expectedTaskId)formatUnreadableMessage("CODER_SETTLEMENT_WAL_TASK_MISMATCH",filePath,`records task ${parsed.taskId} but was read for task ${expectedTaskId}`,"Preserve this file, reconcile the task lane, and only then move it aside.");return parsed}function parseTaskRepairWal(raw,filePath,expectedTaskId){let parsed=parseWalObject(raw,filePath,"TASK_REPAIR_WAL_UNREADABLE","Preserve this file, reconcile the repair transition, and only then move it aside.");if(parsed.version!==1||parsed.state!=="PREPARED"&&parsed.state!=="COMMITTED"&&parsed.state!=="ABORTED"||typeof parsed.taskId!=="string"||!TASK_ID_PATTERN.test(parsed.taskId)||typeof parsed.transitionId!=="string"||parsed.transitionId.length===0||parsed.transitionId.length>512||typeof parsed.reason!=="string"||parsed.reason.length===0||parsed.reason.length>4096||typeof parsed.actor!=="string"||parsed.actor.length===0||parsed.actor.length>512||typeof parsed.oldPlanStatus!=="string"||parsed.oldPlanStatus.length===0||parsed.oldPlanStatus.length>128||parsed.newPlanStatus!=="in_progress"||typeof parsed.oldWorkflowState!=="string"||!WORKFLOW_STATES.has(parsed.oldWorkflowState)||parsed.newWorkflowState!=="idle"||!Number.isInteger(parsed.generation)||(parsed.generation??-1)<0||!Number.isInteger(parsed.oldGeneration)||(parsed.oldGeneration??-1)<0||parsed.generation!==(parsed.oldGeneration??-1)+1||typeof parsed.recordedAt!=="string"||!Number.isFinite(Date.parse(parsed.recordedAt)))formatUnreadableMessage("TASK_REPAIR_WAL_UNREADABLE",filePath,"is not a valid v1 repair WAL (unexpected shape or version)","Preserve this file, reconcile the repair transition, and only then move it aside.");if(expectedTaskId&&parsed.taskId!==expectedTaskId)formatUnreadableMessage("TASK_REPAIR_WAL_TASK_MISMATCH",filePath,`records task ${parsed.taskId} but was read for task ${expectedTaskId}`,"Preserve this file, reconcile the repair transition, and only then move it aside.");return parsed}function parseTaskTerminalWal(raw,filePath,expectedTaskId){let parsed=parseWalObject(raw,filePath,"TASK_TERMINAL_WAL_UNREADABLE","Preserve this file and reconcile the task terminal transition before moving it aside.");if(parsed.version!==1&&parsed.version!==2||parsed.state!=="PREPARED"&&parsed.state!=="COMMITTED"&&parsed.state!=="ABORTED"||typeof parsed.taskId!=="string"||!TASK_ID_PATTERN.test(parsed.taskId)||typeof parsed.transitionId!=="string"||parsed.transitionId.length===0||parsed.transitionId.length>512||typeof parsed.actor!=="string"||parsed.actor.length===0||parsed.actor.length>512||typeof parsed.oldPlanStatus!=="string"||parsed.oldPlanStatus.length===0||parsed.oldPlanStatus.length>128||parsed.newPlanStatus!=="completed"&&parsed.newPlanStatus!=="blocked"&&parsed.newPlanStatus!=="closed"||typeof parsed.oldWorkflowState!=="string"||!WORKFLOW_STATES.has(parsed.oldWorkflowState)||parsed.newWorkflowState!=="complete"&&parsed.newWorkflowState!=="blocked"&&parsed.newWorkflowState!=="closed"||!Number.isInteger(parsed.generation)||(parsed.generation??-1)<0||typeof parsed.qaExempt!=="boolean"||parsed.readOnlyNoMutation!==void 0&&typeof parsed.readOnlyNoMutation!=="boolean"||parsed.externalEvidence!==void 0&&typeof parsed.externalEvidence!=="boolean"||typeof parsed.recordedAt!=="string"||!Number.isFinite(Date.parse(parsed.recordedAt)))formatUnreadableMessage("TASK_TERMINAL_WAL_UNREADABLE",filePath,"is not a valid terminal WAL","Preserve this file and reconcile the task terminal transition before moving it aside.");if(parsed.version===2&&(typeof parsed.planIdentityHash!=="string"||!SHA256_PATTERN.test(parsed.planIdentityHash)||typeof parsed.planEpoch!=="string"||!UUID_PATTERN.test(parsed.planEpoch)))formatUnreadableMessage("TASK_TERMINAL_WAL_UNREADABLE",filePath,"is missing the v2 plan identity fields","Preserve this file and reconcile the task terminal transition before moving it aside.");if(parsed.version===1&&(parsed.newPlanStatus==="closed"||parsed.newWorkflowState==="closed"))formatUnreadableMessage("TASK_TERMINAL_WAL_UNREADABLE",filePath,"claims a closed transition in a legacy v1 terminal WAL","Preserve this file and reconcile the task terminal transition before moving it aside.");if(parsed.readOnlyNoMutation===!0&&(parsed.newPlanStatus!=="completed"||parsed.newWorkflowState!=="complete"||parsed.generation!==0||parsed.qaExempt!==!1))throw Error(`TASK_TERMINAL_WAL_STATE_MISMATCH: ${filePath} claims read-only no-mutation completion outside generation 0`);if(!(parsed.newPlanStatus==="completed"&&parsed.newWorkflowState==="complete"||parsed.newPlanStatus==="blocked"&&parsed.newWorkflowState==="blocked"||parsed.newPlanStatus==="closed"&&parsed.newWorkflowState==="closed"))throw Error(`TASK_TERMINAL_WAL_STATE_MISMATCH: ${filePath} encodes ${String(parsed.newPlanStatus)} -> ${String(parsed.newWorkflowState)}`);if(expectedTaskId&&parsed.taskId!==expectedTaskId)formatUnreadableMessage("TASK_TERMINAL_WAL_TASK_MISMATCH",filePath,`records task ${parsed.taskId} but was read for task ${expectedTaskId}`,"Preserve this file and reconcile the task terminal transition before moving it aside.");return parsed}var TASK_ID_PATTERN,SHA256_PATTERN,BRANCH_NAME_PATTERN,UUID_PATTERN,WORKFLOW_STATES;var init_workflow_wal_schema=__esm(()=>{init_path_identity();init_merge2();TASK_ID_PATTERN=/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/,SHA256_PATTERN=/^[0-9a-f]{64}$/,BRANCH_NAME_PATTERN=/^[A-Za-z0-9_][A-Za-z0-9._/-]{0,1023}$/;UUID_PATTERN=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,WORKFLOW_STATES=new Set(["idle","coder_delegated","pre_check_passed","reviewer_run","tests_run","rework_required","complete","blocked","closed"])});import*as fs23 from"node:fs";import{mkdir as mkdir9,open as open4}from"node:fs/promises";import{dirname as dirname19}from"node:path";function maxBytesFor(kind){return kind==="coder-settlement"?CODER_SETTLEMENT_MAX_BYTES:SMALL_WORKFLOW_WAL_MAX_BYTES}function remediationFor(kind){switch(kind){case"coder-settlement":return"Preserve this file, reconcile the task lane, and only then move it aside.";case"task-repair":return"Preserve this file, reconcile the repair transition, and only then move it aside.";case"task-terminal":return"Preserve this file and reconcile the task terminal transition before moving it aside."}}function unreadableCode(kind){switch(kind){case"coder-settlement":return"CODER_SETTLEMENT_WAL_UNREADABLE";case"task-repair":return"TASK_REPAIR_WAL_UNREADABLE";case"task-terminal":return"TASK_TERMINAL_WAL_UNREADABLE"}}function walIoError(kind,filePath,action,error49){let detail=error49 instanceof Error?error49.message:String(error49);return Error(`${unreadableCode(kind)}: could not ${action} ${filePath} (${detail}). ${remediationFor(kind)}`,{cause:error49})}function oversizeCode(kind){switch(kind){case"coder-settlement":return"CODER_SETTLEMENT_WAL_OVERSIZE";case"task-repair":return"TASK_REPAIR_WAL_OVERSIZE";case"task-terminal":return"TASK_TERMINAL_WAL_OVERSIZE"}}function oversizeMessage(kind,filePath,maxBytes){if(kind==="coder-settlement")throw Error(`${oversizeCode(kind)}: ${filePath} exceeds the 64 MiB safety limit. Preserve this file, reconcile the lane, reduce or partition the declared scope, and only then move the WAL aside.`);throw Error(`${oversizeCode(kind)}: ${filePath} exceeds the ${maxBytes} byte safety limit. ${remediationFor(kind)}`)}function decodeUtf8(kind,filePath,bytes){try{return UTF8_FATAL_DECODER.decode(bytes)}catch(error49){throw Error(`${unreadableCode(kind)}: ${filePath} is not valid UTF-8 (${error49 instanceof Error?error49.message:String(error49)}). ${remediationFor(kind)}`)}}function validateWal(kind,raw,filePath,expectedTaskId){switch(kind){case"coder-settlement":return parseCoderSettlementWal(raw,filePath,expectedTaskId);case"task-repair":return parseTaskRepairWal(raw,filePath,expectedTaskId);case"task-terminal":return parseTaskTerminalWal(raw,filePath,expectedTaskId)}}async function readBoundedBytes(kind,filePath,maxBytes){let handle;try{handle=await _internals37.openFile(filePath,"r")}catch(error49){if(error49.code==="ENOENT")return null;throw walIoError(kind,filePath,"open",error49)}let result=new Uint8Array,failure=null;try{let limit=maxBytes+1,chunks=[],total=0;while(!0){let remaining=limit-total;if(remaining<=0)break;let buffer=Buffer.alloc(Math.min(CHUNK_BYTES,remaining)),{bytesRead}=await handle.read(buffer,0,buffer.length,null);if(bytesRead===0)break;if(total+=bytesRead,chunks.push(buffer.subarray(0,bytesRead)),total>maxBytes)break}result=Buffer.concat(chunks,total)}catch(error49){failure=walIoError(kind,filePath,"read",error49)}try{await handle.close()}catch(error49){failure??=walIoError(kind,filePath,"close",error49)}if(failure)throw failure;return result}function readBoundedBytesSync(kind,filePath,maxBytes){let fd;try{fd=_internals37.openFileSync(filePath,"r")}catch(error49){if(error49.code==="ENOENT")return null;throw walIoError(kind,filePath,"open",error49)}let result=new Uint8Array,failure=null;try{let limit=maxBytes+1,chunks=[],total=0;while(!0){let remaining=limit-total;if(remaining<=0)break;let buffer=Buffer.alloc(Math.min(CHUNK_BYTES,remaining)),bytesRead=_internals37.readFileSync(fd,buffer,0,buffer.length,null);if(bytesRead===0)break;if(total+=bytesRead,chunks.push(buffer.subarray(0,bytesRead)),total>maxBytes)break}result=Buffer.concat(chunks,total)}catch(error49){failure=walIoError(kind,filePath,"read",error49)}try{_internals37.closeFileSync(fd)}catch(error49){failure??=walIoError(kind,filePath,"close",error49)}if(failure)throw failure;return result}async function readWorkflowWalFile(kind,filePath,expectedTaskId){let maxBytes=maxBytesFor(kind),bytes=await readBoundedBytes(kind,filePath,maxBytes);if(bytes===null)return null;if(bytes.length===0)throw Error(`${unreadableCode(kind)}: ${filePath} is empty. ${remediationFor(kind)}`);if(bytes.length>maxBytes)oversizeMessage(kind,filePath,maxBytes);return validateWal(kind,decodeUtf8(kind,filePath,bytes),filePath,expectedTaskId)}function readWorkflowWalFileSync(kind,filePath,expectedTaskId){let maxBytes=maxBytesFor(kind),bytes=readBoundedBytesSync(kind,filePath,maxBytes);if(bytes===null)return null;if(bytes.length===0)throw Error(`${unreadableCode(kind)}: ${filePath} is empty. ${remediationFor(kind)}`);if(bytes.length>maxBytes)oversizeMessage(kind,filePath,maxBytes);return validateWal(kind,decodeUtf8(kind,filePath,bytes),filePath,expectedTaskId)}async function writeWorkflowWalFile(kind,filePath,wal){let serialized=`${JSON.stringify(wal,null,2)}
|
|
613
|
-
`,maxBytes=maxBytesFor(kind);if(Buffer.byteLength(serialized,"utf8")>maxBytes)oversizeMessage(kind,filePath,maxBytes);validateWal(kind,serialized,filePath,wal.taskId),await mkdir9(dirname19(filePath),{recursive:!0}),await atomicWriteFile(filePath,serialized)}var UTF8_FATAL_DECODER,CODER_SETTLEMENT_MAX_BYTES=67108864,SMALL_WORKFLOW_WAL_MAX_BYTES=1048576,CHUNK_BYTES=65536,_internals37;var init_workflow_wal_file=__esm(()=>{init_task_file();init_workflow_wal_schema();UTF8_FATAL_DECODER=new TextDecoder("utf-8",{fatal:!0}),_internals37={openFile:open4,openFileSync:fs23.openSync,readFileSync:fs23.readSync,closeFileSync:fs23.closeSync}});var exports_gate_evidence={};__export(exports_gate_evidence,{withTaskEvidenceTransaction:()=>withTaskEvidenceTransaction,transitionTaskWorkflowEvidenceWithStatus:()=>transitionTaskWorkflowEvidenceWithStatus,transitionTaskWorkflowEvidence:()=>transitionTaskWorkflowEvidence,reduceTaskWorkflowSnapshot:()=>reduceTaskWorkflowSnapshot,recordTodoScanEvidence:()=>recordTodoScanEvidence,recordGateEvidence:()=>recordGateEvidence,recordAgentDispatch:()=>recordAgentDispatch,readTaskEvidenceState:()=>readTaskEvidenceState,readTaskEvidenceRaw:()=>readTaskEvidenceRaw,readTaskEvidence:()=>readTaskEvidence,readCurrentTaskDeclaredFiles:()=>readCurrentTaskDeclaredFiles,parseTaskEvidence:()=>parseTaskEvidence,isValidTaskId:()=>isValidTaskId,isReadOnlyNoMutationEligible:()=>isReadOnlyNoMutationEligible,isExternalEvidenceInitialCompletionEligible:()=>isExternalEvidenceInitialCompletionEligible,hasPassedAllGates:()=>hasPassedAllGates,getTaskWorkflowSnapshot:()=>getTaskWorkflowSnapshot,externalProofCurrent:()=>externalProofCurrent,expandRequiredGates:()=>expandRequiredGates,ensureTaskGateRequirementsReceiptForSettledTransition:()=>ensureTaskGateRequirementsReceiptForSettledTransition,deriveRequiredGates:()=>deriveRequiredGates,deriveApplicableGateSet:()=>deriveApplicableGateSet,computeExternalDeclarationDigest:()=>computeExternalDeclarationDigest,compareTaskWorkflowStateRank:()=>compareTaskWorkflowStateRank,assertTaskEvidenceWriteAllowed:()=>assertTaskEvidenceWriteAllowed,_internals:()=>_internals38,TASK_WORKFLOW_SCHEMA_MARKER:()=>TASK_WORKFLOW_SCHEMA_MARKER,TASK_GATE_REQUIREMENTS_RECONSTRUCTION_SENTINEL:()=>TASK_GATE_REQUIREMENTS_RECONSTRUCTION_SENTINEL,ExternalEvidenceBundleSchema:()=>ExternalEvidenceBundleSchema,DEFAULT_REQUIRED_GATES:()=>DEFAULT_REQUIRED_GATES});import{createHash as createHash22}from"node:crypto";import{mkdirSync as mkdirSync15,readFileSync as readFileSync13,realpathSync as realpathSync10,statSync as statSync13}from"node:fs";import*as path40 from"node:path";function readCurrentTaskDeclaredFiles(directory,taskId){try{let planPath=validateSwarmPath(directory,"plan.json"),stat8=statSync13(planPath);if(!stat8.isFile()||stat8.size>MAX_PLAN_SCOPE_INSPECTION_BYTES)return null;let parsed=JSON.parse(readFileSync13(planPath,"utf8"));if(!Array.isArray(parsed.phases))return null;let declaredFiles=null;for(let phase of parsed.phases){if(!phase||typeof phase!=="object")return null;let tasks=phase.tasks;if(!Array.isArray(tasks))return null;for(let task of tasks){if(!task||typeof task!=="object")return null;let record2=task;if(record2.id!==taskId)continue;if(!Array.isArray(record2.files_touched)||!record2.files_touched.every((file2)=>typeof file2==="string"))return null;if(declaredFiles!==null)return null;declaredFiles=[...record2.files_touched]}}return declaredFiles}catch{return null}}function assertTaskEvidenceWriteAllowed(directory,taskId,event){assertValidTaskId(taskId);let coderWalPath=validateSwarmPath(directory,`coder-settlements/${taskId}.json`),coderWal=readWorkflowWalFileSync("coder-settlement",coderWalPath,taskId);if((coderWal?.state==="DISPATCHED"||coderWal?.state==="PREPARED")&&!(event!=null&&event.transitionId===coderWal.transitionId&&(event.type==="dispatch_attempted"||event.type==="dispatch_no_mutation"||event.type==="accepted_mutation")))throw Error(`CODER_SETTLEMENT_IN_PROGRESS: transition ${String(coderWal.transitionId)} owns evidence for task ${taskId}. Wait for the owning transition to settle or run /swarm recover ${taskId} (or /swarm reset-session), then retry; do not remove the WAL by hand.`);let terminalWalPath=validateSwarmPath(directory,`task-terminals/${taskId}.json`),terminalWal=readWorkflowWalFileSync("task-terminal",terminalWalPath,taskId);if(terminalWal?.state==="PREPARED"){if(!(event!=null&&event.transitionId===terminalWal.transitionId&&(event.type==="task_completed"&&terminalWal.newPlanStatus==="completed"||event.type==="task_blocked"&&terminalWal.newPlanStatus==="blocked"||event.type==="task_closed"&&terminalWal.newPlanStatus==="closed")))throw Error(`TASK_TERMINAL_PREPARED: transition ${String(terminalWal.transitionId)} owns evidence for task ${taskId}`)}let repairWalPath=validateSwarmPath(directory,`task-repairs/${taskId}.json`),repairWal=readWorkflowWalFileSync("task-repair",repairWalPath,taskId);if(repairWal?.state==="PREPARED"&&!(event?.type==="repair_idle"&&event.transitionId===repairWal.transitionId))throw Error(`TASK_REPAIR_PREPARED: transition ${String(repairWal.transitionId)} owns evidence for task ${taskId}`)}function parseTaskEvidence(raw,expectedTaskId){let parsed=TaskEvidenceSchema.parse(JSON.parse(raw));if(parsed.taskId!==expectedTaskId)throw Error(`TASK_EVIDENCE_IDENTITY_MISMATCH: expected ${expectedTaskId}, found ${parsed.taskId}`);return parsed}function isValidTaskId(taskId){return isStrictTaskId(taskId)}function assertValidTaskId(taskId){assertStrictTaskId(taskId)}function createDefaultWorkflowMetadata(nowIso2){return{schema:TASK_WORKFLOW_SCHEMA_MARKER,generation:0,state:DEFAULT_WORKFLOW_STATE,retryCount:0,retryHistory:[],retryEpoch:0,lastOutcome:"none",lastTransitionId:null,updatedAt:nowIso2}}function getEventOutcome(event){switch(event.type){case"dispatch_attempted":return"dispatch_attempted";case"dispatch_no_mutation":return"dispatch_no_mutation";case"accepted_mutation":return event.context?.settlementFailed===!0?"accepted_mutation_failed":"accepted_mutation";case"stage_a_passed":return"stage_a_passed";case"stage_a_failed":return"stage_a_failed";case"stage_b_completed":return"stage_b_completed";case"stage_b_failed":return"stage_b_failed";case"gate_recorded":return"gate_recorded";case"task_completed":return"task_completed";case"task_blocked":return"task_blocked";case"task_closed":return"task_closed";case"repair_idle":return"repair_idle";case"external_evidence_attested":return"external_evidence_attested";case"external_evidence_revoked":return"external_evidence_revoked"}}function isAuthoritativeWorkflowMetadata(workflow){return workflow?.schema===TASK_WORKFLOW_SCHEMA_MARKER}function getTaskWorkflowSnapshot(evidence){if(isAuthoritativeWorkflowMetadata(evidence?.workflow))return{...evidence.workflow,authoritative:!0};return{...createDefaultWorkflowMetadata(""),authoritative:!1}}function maybeExpandRequiredGates(existing,event){if(event.type==="accepted_mutation"){let agentType=event.agentType;if(typeof agentType==="string"&&agentType.trim()!=="")return existing?expandRequiredGates(existing.required_gates.filter((gate)=>gate!==TASK_GATE_REQUIREMENTS_RECONSTRUCTION_SENTINEL),agentType,event.context??{}):deriveRequiredGates(agentType,event.context??{})}if(event.type==="stage_b_completed"&&event.ensureDefaultStageB===!0)return expandRequiredGates(existing?.required_gates??[],"coder",{testEngineerExempt:!1});if(event.type==="stage_b_completed"||event.type==="gate_recorded")return existing?expandRequiredGates(existing.required_gates,event.gate):deriveRequiredGates(event.gate);return existing?.required_gates??[]}function hasAllRequiredGatesPassed(requiredGates,gates){return requiredGates.length>0&&requiredGates.every((gate)=>gates[gate]!=null)}function shouldTreatGateAsStageB(gate){return gate==="reviewer"||gate==="test_engineer"}function clearWorkflowGateProof(gates){let retained={...gates};return delete retained.pre_check,delete retained.reviewer,delete retained.test_engineer,delete retained.council,delete retained.critic,delete retained.critic_sounding_board,retained}function assertExpectedGeneration(snapshot,event){if(typeof event.expectedGeneration==="number"&&event.expectedGeneration!==snapshot.generation)throw Error(`TASK_WORKFLOW_GENERATION_MISMATCH: expected ${event.expectedGeneration}, current ${snapshot.generation}`)}function isDuplicateTransition(snapshot,event){if(event.type==="dispatch_no_mutation"&&event.context?.declaredFiles?.length===0&&event.context.settlementTransitionId===event.transitionId&&!snapshot.noMutationSettlement)return!1;return snapshot.authoritative&&typeof event.transitionId==="string"&&event.transitionId.length>0&&snapshot.lastTransitionId===event.transitionId&&snapshot.lastOutcome===getEventOutcome(event)}function isNoMutationSettlementMetadata(workflow){let settlement=workflow.noMutationSettlement;if(!workflow.authoritative||workflow.generation!==0||settlement?.generation!==0||typeof settlement.transitionId!=="string"||settlement.transitionId.length===0||!Array.isArray(settlement.declaredFiles)||settlement.declaredFiles.length!==0)return!1;return workflow.state==="idle"||workflow.state==="complete"}function deriveApplicableGateSet(evidence,options){if(!evidence)return{requiredGates:["pre_check"],satisfiedGates:[],missingGates:["pre_check"],readOnlyNoMutation:!1};let workflow=getTaskWorkflowSnapshot(evidence),readOnlyNoMutation=isNoMutationSettlementMetadata(workflow)&&(options?.currentDeclaredFiles===void 0?!0:options.currentDeclaredFiles!==null&&options.currentDeclaredFiles.length===0),externalEvidenceMatched=workflow.lastOutcome==="external_evidence_attested"&&(workflow.externalEvidence?.anchors.length??0)>0&&workflow.externalEvidence.anchors.every((anchor)=>anchor.matched),requiredGates=[...new Set(evidence.required_gates??[])];if(!readOnlyNoMutation&&!externalEvidenceMatched&&!requiredGates.includes("pre_check"))requiredGates.unshift("pre_check");let satisfiedGates=requiredGates.filter((gate)=>evidence.gates?.[gate]!=null);return{requiredGates,satisfiedGates,missingGates:requiredGates.filter((gate)=>evidence.gates?.[gate]==null),readOnlyNoMutation}}function isReadOnlyNoMutationEligible(evidence,options){return deriveApplicableGateSet(evidence,options).readOnlyNoMutation}function computeExternalDeclarationDigest(input){let canonical={taskId:input.taskId,evidence_class:input.evidence_class,evidence_anchors:input.evidence_anchors.map((anchor)=>({command:anchor.command,expect:anchor.expect,expect_prefix:anchor.expect_prefix})),plan_title:input.plan_title,plan_swarm:input.plan_swarm,generation:input.generation};return createHash22("sha256").update(JSON.stringify(canonical)).digest("hex")}function externalProofCurrent(plan,planTask,evidence){if(planTask.evidence_class!=="external_git")return!1;let workflow=evidence?.workflow;if(!workflow)return!1;let bundle=workflow.externalEvidence;if(!bundle||bundle.anchors.length===0)return!1;if(!bundle.anchors.every((anchor)=>anchor.matched))return!1;return bundle.declarationDigest===computeExternalDeclarationDigest({taskId:planTask.id,evidence_class:"external_git",evidence_anchors:planTask.evidence_anchors??[],plan_title:plan.title,plan_swarm:plan.swarm,generation:workflow.generation})}function isExternalEvidenceInitialCompletionEligible(plan,planTask,evidence){if(!externalProofCurrent(plan,planTask,evidence))return!1;let snapshot=getTaskWorkflowSnapshot(evidence);return snapshot.authoritative&&snapshot.state==="idle"}function reduceTaskWorkflowSnapshot(current,event,context){if((current.state==="complete"||current.state==="blocked"||current.state==="closed")&&event.type!=="repair_idle"&&!(current.state==="complete"&&event.type==="task_completed"||current.state==="blocked"&&event.type==="task_blocked"||current.state==="blocked"&&event.type==="task_closed"||current.state==="blocked"&&event.type==="stage_a_passed"&&event.settlementRecovery===!0))throw Error(`TASK_WORKFLOW_TERMINAL: cannot apply ${event.type} from ${current.state}`);let outcome=getEventOutcome(event),base={schema:TASK_WORKFLOW_SCHEMA_MARKER,generation:current.generation,state:current.state,retryCount:current.retryCount,retryHistory:current.retryHistory,retryEpoch:current.retryEpoch,lastOutcome:outcome,lastTransitionId:event.transitionId??current.lastTransitionId,updatedAt:context.nowIso,...current.forcedCompletion===!0?{forcedCompletion:!0}:{},...current.supervisedRecovery===!0?{supervisedRecovery:!0}:{},...current.settlementRecovery===!0?{settlementRecovery:!0}:{},...current.noMutationSettlement?{noMutationSettlement:current.noMutationSettlement}:{},...current.externalEvidence?{externalEvidence:current.externalEvidence}:{}};switch(event.type){case"dispatch_attempted":{let{noMutationSettlement:_clearedSettlement,externalEvidence:_clearedExternalEvidence,...withoutSettlement}=base;return withoutSettlement}case"dispatch_no_mutation":{let{noMutationSettlement:_clearedSettlement,externalEvidence:_clearedExternalEvidence,...withoutSettlement}=base;return{...withoutSettlement,retryCount:Math.min(current.retryCount+1,3),retryHistory:[...current.retryHistory,outcome].slice(-3),retryEpoch:current.retryEpoch||current.generation+1,...current.generation===0&&event.transitionId&&Array.isArray(event.context?.declaredFiles)&&event.context.declaredFiles.length===0&&event.context.settlementTransitionId===event.transitionId?{noMutationSettlement:{generation:0,transitionId:event.transitionId,declaredFiles:[]}}:{}}}case"stage_b_failed":if(current.state!=="pre_check_passed"&¤t.state!=="reviewer_run"&¤t.state!=="tests_run"&¤t.state!=="rework_required")throw Error(`TASK_WORKFLOW_STAGE_A_REQUIRED: cannot reject ${event.gate} from ${current.state}`);return{...base,state:"rework_required",retryCount:Math.min(current.retryCount+1,3),retryHistory:[...current.retryHistory,outcome].slice(-3),retryEpoch:current.retryEpoch||current.generation+1};case"accepted_mutation":{let{noMutationSettlement:_clearedSettlement,externalEvidence:_clearedExternalEvidence,...withoutSettlement}=base;if(event.context?.settlementFailed===!0)return{...withoutSettlement,generation:current.generation+1,state:"rework_required",retryCount:Math.min(current.retryCount+1,3),retryHistory:[...current.retryHistory,outcome].slice(-3),retryEpoch:current.retryEpoch||current.generation+1,supervisedRecovery:void 0,settlementRecovery:void 0};return{...withoutSettlement,generation:current.generation+1,state:"coder_delegated",supervisedRecovery:void 0,settlementRecovery:void 0}}case"stage_a_passed":if(current.state!=="coder_delegated"&¤t.state!=="pre_check_passed"&&!(current.state==="rework_required"&&event.supervisedRecovery===!0)&&!(event.settlementRecovery===!0&&(current.state==="idle"||current.state==="blocked")))throw Error(`TASK_WORKFLOW_CODER_MUTATION_REQUIRED: cannot pass Stage A from ${current.state}`);return{...base,...event.supervisedRecovery===!0?{supervisedRecovery:!0}:{},...event.settlementRecovery===!0?{settlementRecovery:!0}:{},state:"pre_check_passed"};case"stage_a_failed":if(current.state!=="coder_delegated"&¤t.state!=="pre_check_passed"&¤t.state!=="rework_required")throw Error(`TASK_WORKFLOW_CODER_MUTATION_REQUIRED: cannot fail Stage A from ${current.state}`);return{...base,state:"rework_required",retryCount:Math.min(current.retryCount+1,3),retryHistory:[...current.retryHistory,outcome].slice(-3),retryEpoch:current.retryEpoch||current.generation+1};case"stage_b_completed":if(current.state!=="pre_check_passed"&¤t.state!=="reviewer_run"&¤t.state!=="tests_run")throw Error(`TASK_WORKFLOW_STAGE_A_REQUIRED: cannot record ${event.gate} from ${current.state}`);if(event.routeComplete===!1)return{...base,state:event.gate==="reviewer"||current.state==="reviewer_run"?"reviewer_run":current.state};if(event.routeComplete===!0)return{...base,state:"tests_run"};return{...base,state:hasAllRequiredGatesPassed(context.requiredGates,context.gates)?"tests_run":"reviewer_run"};case"gate_recorded":return{...base,state:current.state};case"external_evidence_attested":{if(current.state!=="idle")throw Error(`TASK_WORKFLOW_EXTERNAL_ATTEST_STATE: external evidence can only be attested from idle (task never entered the coder QA lifecycle), not ${current.state}`);if(current.externalEvidence?.transitionId===event.bundle.transitionId)return{...base};return{...base,externalEvidence:event.bundle}}case"external_evidence_revoked":{let{externalEvidence:_revokedExternalEvidence,...withoutExternalEvidence}=base;return withoutExternalEvidence}case"task_completed":{let readOnlyNoMutation=event.readOnlyNoMutation===!0&¤t.state==="idle"&¤t.generation===0&&isNoMutationSettlementMetadata(current)&&context.requiredGates.every((gate)=>context.gates[gate]!=null),externalAdmitted=event.externalEvidence===!0&¤t.externalEvidence!==void 0&¤t.externalEvidence.anchors.length>0&¤t.externalEvidence.anchors.every((anchor)=>anchor.matched)&&(current.state==="idle"||current.state==="complete");if(event.qaExempt!==!0&¤t.state!=="tests_run"&¤t.state!=="complete"&&!(current.state==="pre_check_passed"&&context.gates.council!=null)&&!readOnlyNoMutation&&!externalAdmitted)throw Error(`TASK_WORKFLOW_QA_REQUIRED: cannot complete from ${current.state}`);return{...base,state:"complete",...event.qaExempt===!0?{forcedCompletion:!0}:{}}}case"task_blocked":return{...base,state:"blocked"};case"task_closed":return{...base,state:"closed"};case"repair_idle":{let{forcedCompletion:_cleared,supervisedRecovery:_clearedMarker,settlementRecovery:_clearedSettlementMarker,noMutationSettlement:_clearedSettlement,externalEvidence:_clearedExternalEvidence,...withoutForced}=base;return{...withoutForced,generation:current.generation+1,state:"idle",retryCount:0,retryHistory:[],retryEpoch:0}}}}function getEvidenceDir(directory){let swarmDir=path40.resolve(directory,".swarm"),evidenceDir=path40.join(swarmDir,"evidence");mkdirSync15(evidenceDir,{recursive:!0});let resolvedSwarmDir,resolvedEvidenceDir;try{resolvedSwarmDir=path40.normalize(realpathSync10(swarmDir)),resolvedEvidenceDir=path40.normalize(realpathSync10(evidenceDir))}catch(error49){throw Error(`Unable to resolve evidence directory: ${error49.message}`)}let swarmPrefix=`${resolvedSwarmDir}${path40.sep}`;if(!(process.platform==="win32"?resolvedEvidenceDir.toLowerCase().startsWith(swarmPrefix.toLowerCase()):resolvedEvidenceDir.startsWith(swarmPrefix)))throw Error(`Evidence path escapes .swarm boundary: ${resolvedEvidenceDir}`);return resolvedEvidenceDir}function getEvidencePath(directory,taskId){return assertValidTaskId(taskId),taskEvidencePath(directory,taskId)}function bindTrustedNoMutationSettlement(directory,taskId,event){if(event.type!=="dispatch_no_mutation")return event;let context=event.context;if(!context||event.transitionId===void 0)return{...event,context:void 0};try{let wal=readWorkflowWalFileSync("coder-settlement",validateSwarmPath(directory,`coder-settlements/${taskId}.json`),taskId),declaredFiles=wal?.context?.declaredFiles,trusted=wal!==null&&(wal.state==="PREPARED"||wal.state==="COMMITTED")&&wal.accepted===!1&&wal.transitionId===event.transitionId&&Array.isArray(declaredFiles)&&declaredFiles.length===0&&Array.isArray(context.declaredFiles)&&context.declaredFiles.length===0;return{...event,context:trusted?{...context,declaredFiles,settlementTransitionId:wal.transitionId}:{...context,settlementTransitionId:void 0}}}catch{return{...event,context:{...context,settlementTransitionId:void 0}}}}function readExisting(evidencePath,taskId){try{let raw=readFileSync13(evidencePath,"utf-8");return parseTaskEvidence(raw,taskId)}catch(error49){if(error49.code==="ENOENT")return null;throw telemetry.gateParseError(taskId,error49),error49}}function deriveRequiredGates(agentType,context={}){switch(agentType){case"coder":return context.testEngineerExempt===!0?["reviewer"]:["reviewer","test_engineer"];case"docs":return["docs"];case"designer":return["designer","reviewer","test_engineer"];case"explorer":return["explorer"];case"sme":return["sme"];case"reviewer":return["reviewer"];case"test_engineer":return["test_engineer"];case"critic":return["critic"];case"critic_sounding_board":return["critic_sounding_board"];case"critic_drift_verifier":return["critic_drift_verifier"];case"critic_hallucination_verifier":return["critic_hallucination_verifier"];case"critic_architecture_supervisor":return["critic_architecture_supervisor"];default:return["reviewer","test_engineer"]}}function expandRequiredGates(existingGates,newAgentType,context={}){let newGates=deriveRequiredGates(newAgentType,context);return[...new Set([...existingGates??[],...newGates])].sort()}function updateEvidenceForTransition(existing,event){let nowIso2=new Date().toISOString(),requiredGates=maybeExpandRequiredGates(existing,event),gates={...existing?.gates??{}};if(event.type==="accepted_mutation"||event.type==="repair_idle")gates=clearWorkflowGateProof(gates);if(event.type==="stage_a_passed")gates={...gates,pre_check:{sessionId:"system",timestamp:nowIso2,agent:"pre_check"}};if(event.type==="stage_a_failed")delete gates.pre_check;if(event.type==="stage_b_failed")delete gates.reviewer,delete gates.test_engineer;if(event.type==="stage_b_completed"||event.type==="gate_recorded")gates={...gates,[event.gate]:{sessionId:event.sessionId,timestamp:nowIso2,agent:event.gate}};let snapshot=getTaskWorkflowSnapshot(existing);if(assertExpectedGeneration(snapshot,event),isDuplicateTransition(snapshot,event)&&existing)return existing;let workflow=reduceTaskWorkflowSnapshot(snapshot,event,{requiredGates,gates,nowIso:nowIso2});return{taskId:existing?.taskId??"",required_gates:requiredGates,gates,turbo:"turbo"in event&&event.turbo===!0?!0:("turbo"in event)&&event.turbo===!1?existing?.turbo:existing?.turbo,test_engineer_exempt:(event.type==="dispatch_attempted"||event.type==="dispatch_no_mutation"||event.type==="accepted_mutation")&&event.agentType==="coder"?event.context?.testEngineerExempt===!0&&!requiredGates.includes("test_engineer"):existing?.test_engineer_exempt,workflow,requirements_state:existing?.requirements_state,...existing?.repair_provenance?{repair_provenance:existing.repair_provenance}:{},...existing?.todo_scan?{todo_scan:existing.todo_scan}:{}}}async function transitionTaskWorkflowEvidence(directory,taskId,event){let{evidence}=await transitionTaskWorkflowEvidenceWithStatus(directory,taskId,event);return evidence}async function transitionTaskWorkflowEvidenceWithStatus(directory,taskId,event){assertValidTaskId(taskId);let updatedEvidence=null,duplicated=!1;return await withTaskEvidenceTransaction(directory,taskId,event.type,async(transaction)=>{if(transaction.transitionWithStatus){let result=await transaction.transitionWithStatus(event);updatedEvidence=result.evidence,duplicated=result.duplicated;return}updatedEvidence=await transaction.transition(event)}),{evidence:updatedEvidence??{taskId,required_gates:[],gates:{},workflow:createDefaultWorkflowMetadata(new Date().toISOString())},duplicated}}async function withTaskEvidenceTransaction(directory,taskId,agent,callback){return assertValidTaskId(taskId),withTaskEvidenceLock(directory,taskId,agent,async()=>{let resolvedEvidenceDir=getEvidenceDir(directory),evidencePath=path40.join(resolvedEvidenceDir,`${taskId}.json`),current=null;try{current=readExisting(evidencePath,taskId)}catch(error49){throw telemetry.gateParseError(taskId,error49),error49}let persist=async(nextEvidence,event)=>{let validated=TaskEvidenceSchema.parse({...nextEvidence,taskId});if(await atomicWriteFile(evidencePath,JSON.stringify(validated,null,2)),event)await _internals38.appendTaskGateRequirementsReceiptIfNeeded(directory,taskId,current,validated,event);return current=validated,validated},transitionWithStatusImpl=async(event)=>{let boundEvent=bindTrustedNoMutationSettlement(directory,taskId,event);assertTaskEvidenceWriteAllowed(directory,taskId,boundEvent);let nextEvidence=updateEvidenceForTransition(current,boundEvent),duplicated=nextEvidence===current;return nextEvidence.taskId=taskId,{evidence:await persist(nextEvidence,boundEvent),duplicated}};return callback({taskId,read:()=>current,transition:async(event)=>{let{evidence}=await transitionWithStatusImpl(event);return evidence},transitionWithStatus:transitionWithStatusImpl,save:async(nextEvidence)=>{return assertTaskEvidenceWriteAllowed(directory,taskId,void 0),nextEvidence.taskId=taskId,persist(nextEvidence)}})})}async function ensureTaskGateRequirementsReceiptForSettledTransition(directory,taskId,evidence,event){assertValidTaskId(taskId);let validated=TaskEvidenceSchema.parse({...evidence,taskId});await _internals38.appendTaskGateRequirementsReceiptIfNeeded(directory,taskId,null,validated,event)}async function recordGateEvidence(directory,taskId,gate,sessionId,turbo,options={}){if(assertValidTaskId(taskId),shouldTreatGateAsStageB(gate)&&typeof options.expectedGeneration!=="number")throw Error(`TASK_WORKFLOW_GENERATION_REQUIRED: ${gate} for task ${taskId} must be bound at dispatch`);await transitionTaskWorkflowEvidence(directory,taskId,shouldTreatGateAsStageB(gate)?{type:"stage_b_completed",gate,sessionId,routeBinding:options.routeBinding,routeComplete:options.routeComplete,turbo,ensureDefaultStageB:options.ensureDefaultStageB,expectedGeneration:options.expectedGeneration,transitionId:options.transitionId}:{type:"gate_recorded",gate,sessionId,turbo,expectedGeneration:options.expectedGeneration,transitionId:options.transitionId}),telemetry.gatePassed(sessionId,gate,taskId)}async function recordTodoScanEvidence(directory,taskId,scan){assertValidTaskId(taskId),await withTaskEvidenceTransaction(directory,taskId,"todo_scan_recorded",async(transaction)=>{let base=transaction.read()??{taskId,required_gates:[],gates:{},workflow:createDefaultWorkflowMetadata(new Date().toISOString())};if(!transaction.save)throw Error(`TASK_EVIDENCE_SAVE_UNAVAILABLE: transaction for task ${taskId} does not support supplementary writes`);await transaction.save({...base,todo_scan:scan})})}async function recordAgentDispatch(directory,taskId,agentType,turbo,context={}){assertValidTaskId(taskId);let expectedGeneration=getTaskWorkflowSnapshot(await readTaskEvidence(directory,taskId)).generation;await transitionTaskWorkflowEvidence(directory,taskId,agentType==="coder"?{type:"accepted_mutation",agentType,turbo,context,expectedGeneration}:{type:"dispatch_attempted",agentType,turbo,context,expectedGeneration})}async function readTaskEvidence(directory,taskId){let state2=await readTaskEvidenceState(directory,taskId);return state2.kind==="ok"?state2.evidence:null}async function readTaskEvidenceState(directory,taskId){try{assertValidTaskId(taskId)}catch{return{kind:"missing"}}try{let evidencePath=getEvidencePath(directory,taskId),raw=readFileSync13(evidencePath,"utf-8");return{kind:"ok",evidence:parseTaskEvidence(raw,taskId)}}catch(error49){let evidencePath=getEvidencePathSafe(directory,taskId),code=error49.code;if(code==="ENOENT"||code==="ENAMETOOLONG")return{kind:"missing"};return telemetry.gateParseError(taskId,error49),{kind:"unparseable",evidencePath,error:error49}}}function getEvidencePathSafe(directory,taskId){try{return getEvidencePath(directory,taskId)}catch{return`${directory}/.swarm/evidence/${taskId}.json`}}function readTaskEvidenceRaw(directory,taskId){assertValidTaskId(taskId);let evidencePath=getEvidencePath(directory,taskId);try{let raw=readFileSync13(evidencePath,"utf-8");return parseTaskEvidence(raw,taskId)}catch(error49){let code=error49.code;if(code==="ENOENT"||code==="ENAMETOOLONG")return null;throw error49}}async function hasPassedAllGates(directory,taskId,currentDeclaredFiles){let evidence=await readTaskEvidence(directory,taskId);if(!evidence)return!1;if(!Array.isArray(evidence.required_gates))return!1;if(currentDeclaredFiles===void 0){if(deriveApplicableGateSet(evidence).readOnlyNoMutation)return!1;return hasAllRequiredGatesPassed(evidence.required_gates,evidence.gates)}return deriveApplicableGateSet(evidence,{currentDeclaredFiles}).missingGates.length===0}function compareTaskWorkflowStateRank(left,right){return WORKFLOW_STATE_RANK[left]-WORKFLOW_STATE_RANK[right]}var _internals38,TASK_WORKFLOW_SCHEMA_MARKER="exact-task-v1",TASK_WORKFLOW_STATES,TASK_WORKFLOW_OUTCOMES,MAX_PLAN_SCOPE_INSPECTION_BYTES=4194304,TASK_GATE_REQUIREMENTS_RECONSTRUCTION_SENTINEL="requirements_reconstruction",GateEvidenceSchema,ExternalEvidenceBundleSchema,TaskWorkflowMetadataSchema,TaskEvidenceSchema,DEFAULT_REQUIRED_GATES,DEFAULT_WORKFLOW_STATE="idle",WORKFLOW_STATE_RANK;var init_gate_evidence=__esm(()=>{init_zod();init_task_file();init_task_gate_requirements();init_utils2();init_telemetry();init_task_id();init_workflow_wal_file();_internals38={appendTaskGateRequirementsReceiptIfNeeded},TASK_WORKFLOW_STATES=["idle","coder_delegated","pre_check_passed","reviewer_run","tests_run","rework_required","complete","blocked","closed"],TASK_WORKFLOW_OUTCOMES=["none","dispatch_attempted","dispatch_no_mutation","accepted_mutation","accepted_mutation_failed","stage_a_passed","stage_a_failed","stage_b_completed","stage_b_failed","gate_recorded","task_completed","task_blocked","task_closed","repair_idle","external_evidence_attested","external_evidence_revoked"];GateEvidenceSchema=exports_external.object({sessionId:exports_external.string(),timestamp:exports_external.string(),agent:exports_external.string()}).passthrough(),ExternalEvidenceBundleSchema=exports_external.object({class:exports_external.literal("external_git"),transitionId:exports_external.string().min(1).max(512),declarationDigest:exports_external.string().regex(/^[a-f0-9]{64}$/),anchors:exports_external.array(exports_external.object({command:exports_external.string().min(1).max(400),expect:exports_external.string().max(4096).optional(),expect_prefix:exports_external.string().min(1).max(4096).optional(),matched:exports_external.boolean(),exit_code:exports_external.number().int(),stdout:exports_external.string().max(4096)})).min(1).max(16).superRefine((anchors,ctx)=>{anchors.forEach((anchor,index)=>{if(anchor.expect===void 0&&anchor.expect_prefix===void 0)ctx.addIssue({code:exports_external.ZodIssueCode.custom,message:`anchor ${index} must carry expect and/or a non-empty expect_prefix`,path:[index]})})}),attestedAt:exports_external.string().min(1)}),TaskWorkflowMetadataSchema=exports_external.object({schema:exports_external.literal(TASK_WORKFLOW_SCHEMA_MARKER),generation:exports_external.number().int().min(0),state:exports_external.enum(TASK_WORKFLOW_STATES),retryCount:exports_external.number().int().min(0).default(0),retryHistory:exports_external.array(exports_external.enum(TASK_WORKFLOW_OUTCOMES)).max(3).default([]),retryEpoch:exports_external.number().int().min(0).default(0),lastOutcome:exports_external.enum(TASK_WORKFLOW_OUTCOMES).default("none"),lastTransitionId:exports_external.string().min(1).nullable().optional().default(null),updatedAt:exports_external.string(),forcedCompletion:exports_external.boolean().optional(),supervisedRecovery:exports_external.boolean().optional(),settlementRecovery:exports_external.boolean().optional(),noMutationSettlement:exports_external.object({generation:exports_external.literal(0),transitionId:exports_external.string().min(1).max(512),declaredFiles:exports_external.array(exports_external.string()).length(0)}).optional(),externalEvidence:ExternalEvidenceBundleSchema.optional()}),TaskEvidenceSchema=exports_external.object({taskId:exports_external.string(),required_gates:exports_external.array(exports_external.string()).default([]),gates:exports_external.record(exports_external.string(),GateEvidenceSchema),turbo:exports_external.boolean().optional(),requirements_state:exports_external.enum(["known","unknown"]).optional(),test_engineer_exempt:exports_external.boolean().optional(),workflow:TaskWorkflowMetadataSchema.optional(),repair_provenance:exports_external.object({source_sha256:exports_external.string().regex(/^[a-f0-9]{64}$/).nullable(),source_generation:exports_external.number().int().min(0).nullable(),requirements_receipt_hash:exports_external.string().regex(/^[a-f0-9]{64}$/).nullable()}).optional(),todo_scan:exports_external.object({priority:exports_external.string(),count:exports_external.number().int().min(0),details:exports_external.array(exports_external.string()).max(200).optional(),recorded_at:exports_external.string().optional()}).optional()});DEFAULT_REQUIRED_GATES=["reviewer","test_engineer"],WORKFLOW_STATE_RANK={idle:0,coder_delegated:1,pre_check_passed:2,reviewer_run:3,tests_run:4,rework_required:5,blocked:6,closed:7,complete:8}});import*as path41 from"node:path";function normalizeCandidate(value){if(typeof value!=="string"||value.length===0)return null;if([...value].some((character)=>{let codePoint=character.codePointAt(0)??0;return codePoint<=31||codePoint===127}))return null;if(path41.win32.isAbsolute(value)||path41.posix.isAbsolute(value))return null;let normalized=value.replace(/\\/g,"/");if(normalized.split("/").some((segment)=>segment===""||segment==="."||segment===".."))return null;return normalized}function isExactMarkdownPath(value){let normalized=normalizeCandidate(value);return normalized!==null&&path41.posix.extname(normalized)===".md"}function isMarkdownOnlyDeclaredScope(value){return Array.isArray(value)&&value.length>0&&value.every(isExactMarkdownPath)}function isMarkdownOnlyTaskChange(declaredFiles,observedFiles){if(!Array.isArray(declaredFiles)||!Array.isArray(observedFiles))return!1;if(!isMarkdownOnlyDeclaredScope(declaredFiles)||observedFiles.length===0)return!1;if(!observedFiles.every(isExactMarkdownPath))return!1;let declared=new Set(declaredFiles.map(normalizeCandidate).filter((value)=>value!==null));return observedFiles.every((value)=>{let normalized=normalizeCandidate(value);return normalized!==null&&declared.has(normalized)})}var init_gate_evidence_classification=()=>{};import{createHash as createHash23}from"node:crypto";import*as fs24 from"node:fs";import*as path42 from"node:path";function ownerDirectory(directory){return path42.dirname(validateSwarmPath(directory,path42.join(PROVISIONING_OWNER_DIR,".containment-anchor")))}function ownerPath(directory,callID){let digest2=createHash23("sha256").update(callID).digest("hex");return validateSwarmPath(directory,path42.join(PROVISIONING_OWNER_DIR,`${digest2}.json`))}function journalPath(directory){return validateSwarmPath(directory,PROVISIONING_JOURNAL_PATH)}function isOwner(value){if(!value||typeof value!=="object"||Array.isArray(value))return!1;let candidate=value,schemaVersion=candidate.schemaVersion,validTaskIdentity=schemaVersion===1?candidate.taskId===void 0&&candidate.reservationId===void 0&&candidate.generation===void 0&&candidate.branchName===void 0:schemaVersion===2&&typeof candidate.taskId==="string"&&candidate.taskId.length>0&&candidate.taskId.length<=512&&candidate.reservationId===void 0&&candidate.generation===void 0&&candidate.branchName===void 0,validV3Identity=schemaVersion===3&&typeof candidate.taskId==="string"&&candidate.taskId.length>0&&candidate.taskId.length<=512&&typeof candidate.reservationId==="string"&&candidate.reservationId.length>0&&candidate.reservationId.length<=512&&typeof candidate.generation==="number"&&Number.isInteger(candidate.generation)&&candidate.generation>0&&typeof candidate.branchName==="string"&&candidate.branchName.length>0&&candidate.branchName.length<=1024;return(schemaVersion===1||schemaVersion===2||schemaVersion===3)&&(validTaskIdentity||validV3Identity)&&typeof candidate.callID==="string"&&candidate.callID.length>0&&candidate.callID.length<=512&&typeof candidate.parentSessionId==="string"&&candidate.parentSessionId.length>0&&candidate.parentSessionId.length<=512&&typeof candidate.worktreeSessionId==="string"&&candidate.worktreeSessionId.length>0&&candidate.worktreeSessionId.length<=512&&typeof candidate.createdAt==="number"&&Number.isFinite(candidate.createdAt)&&candidate.createdAt>=0}function isLifecycleEntry(value){if(!value||typeof value!=="object"||Array.isArray(value))return!1;let candidate=value,validState=WORKTREE_PROVISIONING_LIFECYCLE_STATES.includes(candidate.state);return candidate.schemaVersion===1&&validState&&typeof candidate.callID==="string"&&candidate.callID.length>0&&candidate.callID.length<=512&&typeof candidate.parentSessionId==="string"&&candidate.parentSessionId.length>0&&candidate.parentSessionId.length<=512&&typeof candidate.worktreeSessionId==="string"&&candidate.worktreeSessionId.length>0&&candidate.worktreeSessionId.length<=512&&(candidate.taskId===void 0||typeof candidate.taskId==="string"&&candidate.taskId.length>0&&candidate.taskId.length<=512)&&(candidate.reservationId===void 0||typeof candidate.reservationId==="string"&&candidate.reservationId.length>0&&candidate.reservationId.length<=512)&&(candidate.generation===void 0||typeof candidate.generation==="number"&&Number.isInteger(candidate.generation)&&candidate.generation>0)&&(candidate.branchName===void 0||typeof candidate.branchName==="string"&&candidate.branchName.length>0&&candidate.branchName.length<=1024)&&typeof candidate.recordedAt==="number"&&Number.isFinite(candidate.recordedAt)&&candidate.recordedAt>=0}function readBoundedJsonFile(filePath,maxBytes){try{if(fs24.statSync(filePath).size>maxBytes)return{ok:!1,reason:`${path42.basename(filePath)} exceeds the ${maxBytes}-byte safety bound`};let raw=fs24.readFileSync(filePath,"utf8");if(Buffer.byteLength(raw,"utf8")>maxBytes)return{ok:!1,reason:`${path42.basename(filePath)} changed beyond the ${maxBytes}-byte safety bound`};return{ok:!0,value:JSON.parse(raw)}}catch(error49){if(error49.code==="ENOENT")return{ok:!0,value:void 0};return{ok:!1,reason:`${path42.basename(filePath)} is unreadable or malformed: ${error49 instanceof Error?error49.message:String(error49)}`}}}function readOwner(directory,callID){let absolutePath=ownerPath(directory,callID),loaded=readBoundedJsonFile(absolutePath,MAX_PROVISIONING_OWNER_BYTES);if(!loaded.ok||loaded.value===void 0)return null;return isOwner(loaded.value)?loaded.value:null}function loadLifecycleJournal(directory){let loaded=readBoundedJsonFile(journalPath(directory),MAX_PROVISIONING_JOURNAL_BYTES);if(!loaded.ok)return{status:"uncertain",reason:loaded.reason};if(loaded.value===void 0)return{status:"ok",entries:[]};let parsed=loaded.value;if(parsed.schemaVersion!==1||!Array.isArray(parsed.entries))return{status:"uncertain",reason:"worktree provisioning lifecycle journal is malformed"};if(parsed.entries.length>MAX_PROVISIONING_JOURNAL_ENTRIES)return{status:"uncertain",reason:`worktree provisioning lifecycle journal exceeds the ${MAX_PROVISIONING_JOURNAL_ENTRIES}-entry safety bound`};let entries=[];for(let entry of parsed.entries){if(!isLifecycleEntry(entry))return{status:"uncertain",reason:"worktree provisioning lifecycle journal contains an invalid entry"};entries.push(entry)}return{status:"ok",entries}}function appendLifecycleEntry(directory,owner,state2){let loaded=loadLifecycleJournal(directory);if(loaded.status==="uncertain")throw Error(loaded.reason);let journal={schemaVersion:1,entries:[...loaded.entries,{schemaVersion:1,state:state2,callID:owner.callID,parentSessionId:owner.parentSessionId,worktreeSessionId:owner.worktreeSessionId,...owner.taskId?{taskId:owner.taskId}:{},...owner.reservationId?{reservationId:owner.reservationId}:{},...owner.generation!==void 0?{generation:owner.generation}:{},...owner.branchName?{branchName:owner.branchName}:{},recordedAt:Date.now()}].slice(-MAX_PROVISIONING_JOURNAL_ENTRIES)};atomicWriteSwarmFileSync(journalPath(directory),JSON.stringify(journal,null,2))}function recordWorktreeProvisioningOwner(directory,input){let wantsV3=input.reservationId!==void 0||input.generation!==void 0||input.branchName!==void 0;if(wantsV3&&(!input.taskId||!input.reservationId||input.generation===void 0||!input.branchName))throw Error("worktree provisioning owner v3 requires taskId, reservationId, generation, and branchName");let owner={schemaVersion:wantsV3?3:input.taskId?2:1,callID:input.callID,parentSessionId:input.parentSessionId,worktreeSessionId:input.worktreeSessionId,...input.taskId?{taskId:input.taskId}:{},...input.reservationId?{reservationId:input.reservationId}:{},...input.generation!==void 0?{generation:input.generation}:{},...input.branchName?{branchName:input.branchName}:{},createdAt:Date.now()};if(!isOwner(owner))throw Error("invalid worktree provisioning owner");let absolutePath=ownerPath(directory,input.callID);return fs24.mkdirSync(path42.dirname(absolutePath),{recursive:!0}),atomicWriteSwarmFileSync(absolutePath,`${JSON.stringify(owner)}
|
|
613
|
+
`,maxBytes=maxBytesFor(kind);if(Buffer.byteLength(serialized,"utf8")>maxBytes)oversizeMessage(kind,filePath,maxBytes);validateWal(kind,serialized,filePath,wal.taskId),await mkdir9(dirname19(filePath),{recursive:!0}),await atomicWriteFile(filePath,serialized)}var UTF8_FATAL_DECODER,CODER_SETTLEMENT_MAX_BYTES=67108864,SMALL_WORKFLOW_WAL_MAX_BYTES=1048576,CHUNK_BYTES=65536,_internals37;var init_workflow_wal_file=__esm(()=>{init_task_file();init_workflow_wal_schema();UTF8_FATAL_DECODER=new TextDecoder("utf-8",{fatal:!0}),_internals37={openFile:open4,openFileSync:fs23.openSync,readFileSync:fs23.readSync,closeFileSync:fs23.closeSync}});var exports_gate_evidence={};__export(exports_gate_evidence,{withTaskEvidenceTransaction:()=>withTaskEvidenceTransaction,transitionTaskWorkflowEvidenceWithStatus:()=>transitionTaskWorkflowEvidenceWithStatus,transitionTaskWorkflowEvidence:()=>transitionTaskWorkflowEvidence,resolveCurrentPlanIdentitySync:()=>resolveCurrentPlanIdentitySync,reduceTaskWorkflowSnapshot:()=>reduceTaskWorkflowSnapshot,recordTodoScanEvidence:()=>recordTodoScanEvidence,recordGateEvidence:()=>recordGateEvidence,recordAgentDispatch:()=>recordAgentDispatch,readTaskEvidenceState:()=>readTaskEvidenceState,readTaskEvidenceRaw:()=>readTaskEvidenceRaw,readTaskEvidence:()=>readTaskEvidence,readCurrentTaskDeclaredFiles:()=>readCurrentTaskDeclaredFiles,parseTaskEvidence:()=>parseTaskEvidence,isValidTaskId:()=>isValidTaskId,isReadOnlyNoMutationEligible:()=>isReadOnlyNoMutationEligible,isExternalEvidenceInitialCompletionEligible:()=>isExternalEvidenceInitialCompletionEligible,hasPassedAllGates:()=>hasPassedAllGates,getTaskWorkflowSnapshot:()=>getTaskWorkflowSnapshot,externalProofCurrent:()=>externalProofCurrent,expandRequiredGates:()=>expandRequiredGates,evidenceStampedForDifferentPlan:()=>evidenceStampedForDifferentPlan,ensureTaskGateRequirementsReceiptForSettledTransition:()=>ensureTaskGateRequirementsReceiptForSettledTransition,deriveRequiredGates:()=>deriveRequiredGates,deriveApplicableGateSet:()=>deriveApplicableGateSet,computeExternalDeclarationDigest:()=>computeExternalDeclarationDigest,compareTaskWorkflowStateRank:()=>compareTaskWorkflowStateRank,assertTaskEvidenceWriteAllowed:()=>assertTaskEvidenceWriteAllowed,_internals:()=>_internals38,TASK_WORKFLOW_SCHEMA_MARKER:()=>TASK_WORKFLOW_SCHEMA_MARKER,TASK_GATE_REQUIREMENTS_RECONSTRUCTION_SENTINEL:()=>TASK_GATE_REQUIREMENTS_RECONSTRUCTION_SENTINEL,ExternalEvidenceBundleSchema:()=>ExternalEvidenceBundleSchema,DEFAULT_REQUIRED_GATES:()=>DEFAULT_REQUIRED_GATES});import{createHash as createHash22}from"node:crypto";import{mkdirSync as mkdirSync15,readFileSync as readFileSync13,realpathSync as realpathSync10,statSync as statSync13}from"node:fs";import*as path40 from"node:path";function readCurrentTaskDeclaredFiles(directory,taskId){try{let planPath=validateSwarmPath(directory,"plan.json"),stat8=statSync13(planPath);if(!stat8.isFile()||stat8.size>MAX_PLAN_SCOPE_INSPECTION_BYTES)return null;let parsed=JSON.parse(readFileSync13(planPath,"utf8"));if(!Array.isArray(parsed.phases))return null;let declaredFiles=null;for(let phase of parsed.phases){if(!phase||typeof phase!=="object")return null;let tasks=phase.tasks;if(!Array.isArray(tasks))return null;for(let task of tasks){if(!task||typeof task!=="object")return null;let record2=task;if(record2.id!==taskId)continue;if(!Array.isArray(record2.files_touched)||!record2.files_touched.every((file2)=>typeof file2==="string"))return null;if(declaredFiles!==null)return null;declaredFiles=[...record2.files_touched]}}return declaredFiles}catch{return null}}function assertTaskEvidenceWriteAllowed(directory,taskId,event){assertValidTaskId(taskId);let coderWalPath=validateSwarmPath(directory,`coder-settlements/${taskId}.json`),coderWal=readWorkflowWalFileSync("coder-settlement",coderWalPath,taskId);if((coderWal?.state==="DISPATCHED"||coderWal?.state==="PREPARED")&&!(event!=null&&event.transitionId===coderWal.transitionId&&(event.type==="dispatch_attempted"||event.type==="dispatch_no_mutation"||event.type==="accepted_mutation")))throw Error(`CODER_SETTLEMENT_IN_PROGRESS: transition ${String(coderWal.transitionId)} owns evidence for task ${taskId}. Wait for the owning transition to settle or run /swarm recover ${taskId} (or /swarm reset-session), then retry; do not remove the WAL by hand.`);let terminalWalPath=validateSwarmPath(directory,`task-terminals/${taskId}.json`),terminalWal=readWorkflowWalFileSync("task-terminal",terminalWalPath,taskId);if(terminalWal?.state==="PREPARED"){if(!(event!=null&&event.transitionId===terminalWal.transitionId&&(event.type==="task_completed"&&terminalWal.newPlanStatus==="completed"||event.type==="task_blocked"&&terminalWal.newPlanStatus==="blocked"||event.type==="task_closed"&&terminalWal.newPlanStatus==="closed")))throw Error(`TASK_TERMINAL_PREPARED: transition ${String(terminalWal.transitionId)} owns evidence for task ${taskId}`)}let repairWalPath=validateSwarmPath(directory,`task-repairs/${taskId}.json`),repairWal=readWorkflowWalFileSync("task-repair",repairWalPath,taskId);if(repairWal?.state==="PREPARED"&&!(event?.type==="repair_idle"&&event.transitionId===repairWal.transitionId))throw Error(`TASK_REPAIR_PREPARED: transition ${String(repairWal.transitionId)} owns evidence for task ${taskId}`)}function parseTaskEvidence(raw,expectedTaskId){let parsed=TaskEvidenceSchema.parse(JSON.parse(raw));if(parsed.taskId!==expectedTaskId)throw Error(`TASK_EVIDENCE_IDENTITY_MISMATCH: expected ${expectedTaskId}, found ${parsed.taskId}`);return parsed}function resolveCurrentPlanIdentitySync(directory){if(!directory)return null;try{let planPath=path40.join(directory,".swarm","plan.json"),raw=readFileSync13(planPath,"utf8"),plan=JSON.parse(raw);if(typeof plan.swarm!=="string"||typeof plan.title!=="string")return null;return{planId:derivePlanId(plan),planIdentityHash:derivePlanIdentityHash(plan)}}catch{return null}}function evidenceStampedForDifferentPlan(evidence,currentPlanIdentityHash){if(evidence==null||currentPlanIdentityHash==null)return!1;return typeof evidence.planIdentityHash==="string"&&evidence.planIdentityHash!==currentPlanIdentityHash}function planStampForPersist(nextEvidence,previous,planIdentity,campaignRestart){if(nextEvidence.planIdentityHash!==void 0)return{};if(Object.keys(nextEvidence.gates??{}).length>0&&previous!=null&&!campaignRestart)return previous.planIdentityHash!==void 0?{...previous.planId!==void 0?{planId:previous.planId}:{},planIdentityHash:previous.planIdentityHash}:{};return planIdentity?{planId:planIdentity.planId,planIdentityHash:planIdentity.planIdentityHash}:{}}function isValidTaskId(taskId){return isStrictTaskId(taskId)}function assertValidTaskId(taskId){assertStrictTaskId(taskId)}function createDefaultWorkflowMetadata(nowIso2){return{schema:TASK_WORKFLOW_SCHEMA_MARKER,generation:0,state:DEFAULT_WORKFLOW_STATE,retryCount:0,retryHistory:[],retryEpoch:0,lastOutcome:"none",lastTransitionId:null,updatedAt:nowIso2}}function getEventOutcome(event){switch(event.type){case"dispatch_attempted":return"dispatch_attempted";case"dispatch_no_mutation":return"dispatch_no_mutation";case"accepted_mutation":return event.context?.settlementFailed===!0?"accepted_mutation_failed":"accepted_mutation";case"stage_a_passed":return"stage_a_passed";case"stage_a_failed":return"stage_a_failed";case"stage_b_completed":return"stage_b_completed";case"stage_b_failed":return"stage_b_failed";case"gate_recorded":return"gate_recorded";case"task_completed":return"task_completed";case"task_blocked":return"task_blocked";case"task_closed":return"task_closed";case"repair_idle":return"repair_idle";case"external_evidence_attested":return"external_evidence_attested";case"external_evidence_revoked":return"external_evidence_revoked"}}function isAuthoritativeWorkflowMetadata(workflow){return workflow?.schema===TASK_WORKFLOW_SCHEMA_MARKER}function getTaskWorkflowSnapshot(evidence){if(isAuthoritativeWorkflowMetadata(evidence?.workflow))return{...evidence.workflow,authoritative:!0};return{...createDefaultWorkflowMetadata(""),authoritative:!1}}function maybeExpandRequiredGates(existing,event){if(event.type==="accepted_mutation"){let agentType=event.agentType;if(typeof agentType==="string"&&agentType.trim()!=="")return existing?expandRequiredGates(existing.required_gates.filter((gate)=>gate!==TASK_GATE_REQUIREMENTS_RECONSTRUCTION_SENTINEL),agentType,event.context??{}):deriveRequiredGates(agentType,event.context??{})}if(event.type==="stage_b_completed"&&event.ensureDefaultStageB===!0)return expandRequiredGates(existing?.required_gates??[],"coder",{testEngineerExempt:!1});if(event.type==="stage_b_completed"||event.type==="gate_recorded")return existing?expandRequiredGates(existing.required_gates,event.gate):deriveRequiredGates(event.gate);return existing?.required_gates??[]}function hasAllRequiredGatesPassed(requiredGates,gates){return requiredGates.length>0&&requiredGates.every((gate)=>gates[gate]!=null)}function shouldTreatGateAsStageB(gate){return gate==="reviewer"||gate==="test_engineer"}function clearWorkflowGateProof(gates){let retained={...gates};return delete retained.pre_check,delete retained.reviewer,delete retained.test_engineer,delete retained.council,delete retained.critic,delete retained.critic_sounding_board,retained}function assertExpectedGeneration(snapshot,event){if(typeof event.expectedGeneration==="number"&&event.expectedGeneration!==snapshot.generation)throw Error(`TASK_WORKFLOW_GENERATION_MISMATCH: expected ${event.expectedGeneration}, current ${snapshot.generation}`)}function isDuplicateTransition(snapshot,event){if(event.type==="dispatch_no_mutation"&&event.context?.declaredFiles?.length===0&&event.context.settlementTransitionId===event.transitionId&&!snapshot.noMutationSettlement)return!1;return snapshot.authoritative&&typeof event.transitionId==="string"&&event.transitionId.length>0&&snapshot.lastTransitionId===event.transitionId&&snapshot.lastOutcome===getEventOutcome(event)}function isNoMutationSettlementMetadata(workflow){let settlement=workflow.noMutationSettlement;if(!workflow.authoritative||workflow.generation!==0||settlement?.generation!==0||typeof settlement.transitionId!=="string"||settlement.transitionId.length===0||!Array.isArray(settlement.declaredFiles)||settlement.declaredFiles.length!==0)return!1;return workflow.state==="idle"||workflow.state==="complete"}function deriveApplicableGateSet(evidence,options){if(!evidence)return{requiredGates:["pre_check"],satisfiedGates:[],missingGates:["pre_check"],readOnlyNoMutation:!1};let workflow=getTaskWorkflowSnapshot(evidence),readOnlyNoMutation=isNoMutationSettlementMetadata(workflow)&&(options?.currentDeclaredFiles===void 0?!0:options.currentDeclaredFiles!==null&&options.currentDeclaredFiles.length===0),externalEvidenceMatched=workflow.lastOutcome==="external_evidence_attested"&&(workflow.externalEvidence?.anchors.length??0)>0&&workflow.externalEvidence.anchors.every((anchor)=>anchor.matched),requiredGates=[...new Set(evidence.required_gates??[])];if(!readOnlyNoMutation&&!externalEvidenceMatched&&!requiredGates.includes("pre_check"))requiredGates.unshift("pre_check");let satisfiedGates=requiredGates.filter((gate)=>evidence.gates?.[gate]!=null);return{requiredGates,satisfiedGates,missingGates:requiredGates.filter((gate)=>evidence.gates?.[gate]==null),readOnlyNoMutation}}function isReadOnlyNoMutationEligible(evidence,options){return deriveApplicableGateSet(evidence,options).readOnlyNoMutation}function computeExternalDeclarationDigest(input){let canonical={taskId:input.taskId,evidence_class:input.evidence_class,evidence_anchors:input.evidence_anchors.map((anchor)=>({command:anchor.command,expect:anchor.expect,expect_prefix:anchor.expect_prefix})),plan_title:input.plan_title,plan_swarm:input.plan_swarm,generation:input.generation};return createHash22("sha256").update(JSON.stringify(canonical)).digest("hex")}function externalProofCurrent(plan,planTask,evidence){if(planTask.evidence_class!=="external_git")return!1;let workflow=evidence?.workflow;if(!workflow)return!1;let bundle=workflow.externalEvidence;if(!bundle||bundle.anchors.length===0)return!1;if(!bundle.anchors.every((anchor)=>anchor.matched))return!1;return bundle.declarationDigest===computeExternalDeclarationDigest({taskId:planTask.id,evidence_class:"external_git",evidence_anchors:planTask.evidence_anchors??[],plan_title:plan.title,plan_swarm:plan.swarm,generation:workflow.generation})}function isExternalEvidenceInitialCompletionEligible(plan,planTask,evidence){if(!externalProofCurrent(plan,planTask,evidence))return!1;let snapshot=getTaskWorkflowSnapshot(evidence);return snapshot.authoritative&&snapshot.state==="idle"}function reduceTaskWorkflowSnapshot(current,event,context){if((current.state==="complete"||current.state==="blocked"||current.state==="closed")&&event.type!=="repair_idle"&&!(current.state==="complete"&&event.type==="task_completed"||current.state==="blocked"&&event.type==="task_blocked"||current.state==="blocked"&&event.type==="task_closed"||current.state==="blocked"&&event.type==="stage_a_passed"&&event.settlementRecovery===!0))throw Error(`TASK_WORKFLOW_TERMINAL: cannot apply ${event.type} from ${current.state}`);let outcome=getEventOutcome(event),base={schema:TASK_WORKFLOW_SCHEMA_MARKER,generation:current.generation,state:current.state,retryCount:current.retryCount,retryHistory:current.retryHistory,retryEpoch:current.retryEpoch,lastOutcome:outcome,lastTransitionId:event.transitionId??current.lastTransitionId,updatedAt:context.nowIso,...current.forcedCompletion===!0?{forcedCompletion:!0}:{},...current.supervisedRecovery===!0?{supervisedRecovery:!0}:{},...current.settlementRecovery===!0?{settlementRecovery:!0}:{},...current.noMutationSettlement?{noMutationSettlement:current.noMutationSettlement}:{},...current.externalEvidence?{externalEvidence:current.externalEvidence}:{}};switch(event.type){case"dispatch_attempted":{let{noMutationSettlement:_clearedSettlement,externalEvidence:_clearedExternalEvidence,...withoutSettlement}=base;return withoutSettlement}case"dispatch_no_mutation":{let{noMutationSettlement:_clearedSettlement,externalEvidence:_clearedExternalEvidence,...withoutSettlement}=base;return{...withoutSettlement,retryCount:Math.min(current.retryCount+1,3),retryHistory:[...current.retryHistory,outcome].slice(-3),retryEpoch:current.retryEpoch||current.generation+1,...current.generation===0&&event.transitionId&&Array.isArray(event.context?.declaredFiles)&&event.context.declaredFiles.length===0&&event.context.settlementTransitionId===event.transitionId?{noMutationSettlement:{generation:0,transitionId:event.transitionId,declaredFiles:[]}}:{}}}case"stage_b_failed":if(current.state!=="pre_check_passed"&¤t.state!=="reviewer_run"&¤t.state!=="tests_run"&¤t.state!=="rework_required")throw Error(`TASK_WORKFLOW_STAGE_A_REQUIRED: cannot reject ${event.gate} from ${current.state}`);return{...base,state:"rework_required",retryCount:Math.min(current.retryCount+1,3),retryHistory:[...current.retryHistory,outcome].slice(-3),retryEpoch:current.retryEpoch||current.generation+1};case"accepted_mutation":{let{noMutationSettlement:_clearedSettlement,externalEvidence:_clearedExternalEvidence,...withoutSettlement}=base;if(event.context?.settlementFailed===!0)return{...withoutSettlement,generation:current.generation+1,state:"rework_required",retryCount:Math.min(current.retryCount+1,3),retryHistory:[...current.retryHistory,outcome].slice(-3),retryEpoch:current.retryEpoch||current.generation+1,supervisedRecovery:void 0,settlementRecovery:void 0};return{...withoutSettlement,generation:current.generation+1,state:"coder_delegated",supervisedRecovery:void 0,settlementRecovery:void 0}}case"stage_a_passed":if(current.state!=="coder_delegated"&¤t.state!=="pre_check_passed"&&!(current.state==="rework_required"&&event.supervisedRecovery===!0)&&!(event.settlementRecovery===!0&&(current.state==="idle"||current.state==="blocked")))throw Error(`TASK_WORKFLOW_CODER_MUTATION_REQUIRED: cannot pass Stage A from ${current.state}`);return{...base,...event.supervisedRecovery===!0?{supervisedRecovery:!0}:{},...event.settlementRecovery===!0?{settlementRecovery:!0}:{},state:"pre_check_passed"};case"stage_a_failed":if(current.state!=="coder_delegated"&¤t.state!=="pre_check_passed"&¤t.state!=="rework_required")throw Error(`TASK_WORKFLOW_CODER_MUTATION_REQUIRED: cannot fail Stage A from ${current.state}`);return{...base,state:"rework_required",retryCount:Math.min(current.retryCount+1,3),retryHistory:[...current.retryHistory,outcome].slice(-3),retryEpoch:current.retryEpoch||current.generation+1};case"stage_b_completed":if(current.state!=="pre_check_passed"&¤t.state!=="reviewer_run"&¤t.state!=="tests_run")throw Error(`TASK_WORKFLOW_STAGE_A_REQUIRED: cannot record ${event.gate} from ${current.state}`);if(event.routeComplete===!1)return{...base,state:event.gate==="reviewer"||current.state==="reviewer_run"?"reviewer_run":current.state};if(event.routeComplete===!0)return{...base,state:"tests_run"};return{...base,state:hasAllRequiredGatesPassed(context.requiredGates,context.gates)?"tests_run":"reviewer_run"};case"gate_recorded":return{...base,state:current.state};case"external_evidence_attested":{if(current.state!=="idle")throw Error(`TASK_WORKFLOW_EXTERNAL_ATTEST_STATE: external evidence can only be attested from idle (task never entered the coder QA lifecycle), not ${current.state}`);if(current.externalEvidence?.transitionId===event.bundle.transitionId)return{...base};return{...base,externalEvidence:event.bundle}}case"external_evidence_revoked":{let{externalEvidence:_revokedExternalEvidence,...withoutExternalEvidence}=base;return withoutExternalEvidence}case"task_completed":{let readOnlyNoMutation=event.readOnlyNoMutation===!0&¤t.state==="idle"&¤t.generation===0&&isNoMutationSettlementMetadata(current)&&context.requiredGates.every((gate)=>context.gates[gate]!=null),externalAdmitted=event.externalEvidence===!0&¤t.externalEvidence!==void 0&¤t.externalEvidence.anchors.length>0&¤t.externalEvidence.anchors.every((anchor)=>anchor.matched)&&(current.state==="idle"||current.state==="complete");if(event.qaExempt!==!0&¤t.state!=="tests_run"&¤t.state!=="complete"&&!(current.state==="pre_check_passed"&&context.gates.council!=null)&&!readOnlyNoMutation&&!externalAdmitted)throw Error(`TASK_WORKFLOW_QA_REQUIRED: cannot complete from ${current.state}`);return{...base,state:"complete",...event.qaExempt===!0?{forcedCompletion:!0}:{}}}case"task_blocked":return{...base,state:"blocked"};case"task_closed":return{...base,state:"closed"};case"repair_idle":{let{forcedCompletion:_cleared,supervisedRecovery:_clearedMarker,settlementRecovery:_clearedSettlementMarker,noMutationSettlement:_clearedSettlement,externalEvidence:_clearedExternalEvidence,...withoutForced}=base;return{...withoutForced,generation:current.generation+1,state:"idle",retryCount:0,retryHistory:[],retryEpoch:0}}}}function getEvidenceDir(directory){let swarmDir=path40.resolve(directory,".swarm"),evidenceDir=path40.join(swarmDir,"evidence");mkdirSync15(evidenceDir,{recursive:!0});let resolvedSwarmDir,resolvedEvidenceDir;try{resolvedSwarmDir=path40.normalize(realpathSync10(swarmDir)),resolvedEvidenceDir=path40.normalize(realpathSync10(evidenceDir))}catch(error49){throw Error(`Unable to resolve evidence directory: ${error49.message}`)}let swarmPrefix=`${resolvedSwarmDir}${path40.sep}`;if(!(process.platform==="win32"?resolvedEvidenceDir.toLowerCase().startsWith(swarmPrefix.toLowerCase()):resolvedEvidenceDir.startsWith(swarmPrefix)))throw Error(`Evidence path escapes .swarm boundary: ${resolvedEvidenceDir}`);return resolvedEvidenceDir}function getEvidencePath(directory,taskId){return assertValidTaskId(taskId),taskEvidencePath(directory,taskId)}function bindTrustedNoMutationSettlement(directory,taskId,event){if(event.type!=="dispatch_no_mutation")return event;let context=event.context;if(!context||event.transitionId===void 0)return{...event,context:void 0};try{let wal=readWorkflowWalFileSync("coder-settlement",validateSwarmPath(directory,`coder-settlements/${taskId}.json`),taskId),declaredFiles=wal?.context?.declaredFiles,trusted=wal!==null&&(wal.state==="PREPARED"||wal.state==="COMMITTED")&&wal.accepted===!1&&wal.transitionId===event.transitionId&&Array.isArray(declaredFiles)&&declaredFiles.length===0&&Array.isArray(context.declaredFiles)&&context.declaredFiles.length===0;return{...event,context:trusted?{...context,declaredFiles,settlementTransitionId:wal.transitionId}:{...context,settlementTransitionId:void 0}}}catch{return{...event,context:{...context,settlementTransitionId:void 0}}}}function readExisting(evidencePath,taskId){try{let raw=readFileSync13(evidencePath,"utf-8");return parseTaskEvidence(raw,taskId)}catch(error49){if(error49.code==="ENOENT")return null;throw telemetry.gateParseError(taskId,error49),error49}}function deriveRequiredGates(agentType,context={}){switch(agentType){case"coder":return context.testEngineerExempt===!0?["reviewer"]:["reviewer","test_engineer"];case"docs":return["docs"];case"designer":return["designer","reviewer","test_engineer"];case"explorer":return["explorer"];case"sme":return["sme"];case"reviewer":return["reviewer"];case"test_engineer":return["test_engineer"];case"critic":return["critic"];case"critic_sounding_board":return["critic_sounding_board"];case"critic_drift_verifier":return["critic_drift_verifier"];case"critic_hallucination_verifier":return["critic_hallucination_verifier"];case"critic_architecture_supervisor":return["critic_architecture_supervisor"];default:return["reviewer","test_engineer"]}}function expandRequiredGates(existingGates,newAgentType,context={}){let newGates=deriveRequiredGates(newAgentType,context);return[...new Set([...existingGates??[],...newGates])].sort()}function updateEvidenceForTransition(existing,event){let nowIso2=new Date().toISOString(),requiredGates=maybeExpandRequiredGates(existing,event),gates={...existing?.gates??{}};if(event.type==="accepted_mutation"||event.type==="repair_idle")gates=clearWorkflowGateProof(gates);if(event.type==="stage_a_passed")gates={...gates,pre_check:{sessionId:"system",timestamp:nowIso2,agent:"pre_check"}};if(event.type==="stage_a_failed")delete gates.pre_check;if(event.type==="stage_b_failed")delete gates.reviewer,delete gates.test_engineer;if(event.type==="stage_b_completed"||event.type==="gate_recorded")gates={...gates,[event.gate]:{sessionId:event.sessionId,timestamp:nowIso2,agent:event.gate}};let snapshot=getTaskWorkflowSnapshot(existing);if(assertExpectedGeneration(snapshot,event),isDuplicateTransition(snapshot,event)&&existing)return existing;let workflow=reduceTaskWorkflowSnapshot(snapshot,event,{requiredGates,gates,nowIso:nowIso2});return{taskId:existing?.taskId??"",required_gates:requiredGates,gates,turbo:"turbo"in event&&event.turbo===!0?!0:("turbo"in event)&&event.turbo===!1?existing?.turbo:existing?.turbo,test_engineer_exempt:(event.type==="dispatch_attempted"||event.type==="dispatch_no_mutation"||event.type==="accepted_mutation")&&event.agentType==="coder"?event.context?.testEngineerExempt===!0&&!requiredGates.includes("test_engineer"):existing?.test_engineer_exempt,workflow,requirements_state:existing?.requirements_state,...existing?.repair_provenance?{repair_provenance:existing.repair_provenance}:{},...existing?.todo_scan?{todo_scan:existing.todo_scan}:{}}}async function transitionTaskWorkflowEvidence(directory,taskId,event){let{evidence}=await transitionTaskWorkflowEvidenceWithStatus(directory,taskId,event);return evidence}async function transitionTaskWorkflowEvidenceWithStatus(directory,taskId,event){assertValidTaskId(taskId);let updatedEvidence=null,duplicated=!1;return await withTaskEvidenceTransaction(directory,taskId,event.type,async(transaction)=>{if(transaction.transitionWithStatus){let result=await transaction.transitionWithStatus(event);updatedEvidence=result.evidence,duplicated=result.duplicated;return}updatedEvidence=await transaction.transition(event)}),{evidence:updatedEvidence??{taskId,required_gates:[],gates:{},workflow:createDefaultWorkflowMetadata(new Date().toISOString())},duplicated}}async function withTaskEvidenceTransaction(directory,taskId,agent,callback){return assertValidTaskId(taskId),withTaskEvidenceLock(directory,taskId,agent,async()=>{let resolvedEvidenceDir=getEvidenceDir(directory),evidencePath=path40.join(resolvedEvidenceDir,`${taskId}.json`),current=null;try{current=readExisting(evidencePath,taskId)}catch(error49){throw telemetry.gateParseError(taskId,error49),error49}let persist=async(nextEvidence,event)=>{let planIdentity=resolveCurrentPlanIdentitySync(directory),validated=TaskEvidenceSchema.parse({...nextEvidence,taskId,...planStampForPersist(nextEvidence,current,planIdentity,event?.type==="accepted_mutation"&&event.agentType==="coder"&&nextEvidence!==current)});if(await atomicWriteFile(evidencePath,JSON.stringify(validated,null,2)),event)await _internals38.appendTaskGateRequirementsReceiptIfNeeded(directory,taskId,current,validated,event);return current=validated,validated},transitionWithStatusImpl=async(event)=>{let boundEvent=bindTrustedNoMutationSettlement(directory,taskId,event);assertTaskEvidenceWriteAllowed(directory,taskId,boundEvent);let nextEvidence=updateEvidenceForTransition(current,boundEvent),duplicated=nextEvidence===current;return nextEvidence.taskId=taskId,{evidence:await persist(nextEvidence,boundEvent),duplicated}};return callback({taskId,read:()=>current,transition:async(event)=>{let{evidence}=await transitionWithStatusImpl(event);return evidence},transitionWithStatus:transitionWithStatusImpl,save:async(nextEvidence)=>{return assertTaskEvidenceWriteAllowed(directory,taskId,void 0),nextEvidence.taskId=taskId,persist(nextEvidence)}})})}async function ensureTaskGateRequirementsReceiptForSettledTransition(directory,taskId,evidence,event){assertValidTaskId(taskId);let validated=TaskEvidenceSchema.parse({...evidence,taskId});await _internals38.appendTaskGateRequirementsReceiptIfNeeded(directory,taskId,null,validated,event)}async function recordGateEvidence(directory,taskId,gate,sessionId,turbo,options={}){if(assertValidTaskId(taskId),shouldTreatGateAsStageB(gate)&&typeof options.expectedGeneration!=="number")throw Error(`TASK_WORKFLOW_GENERATION_REQUIRED: ${gate} for task ${taskId} must be bound at dispatch`);await transitionTaskWorkflowEvidence(directory,taskId,shouldTreatGateAsStageB(gate)?{type:"stage_b_completed",gate,sessionId,routeBinding:options.routeBinding,routeComplete:options.routeComplete,turbo,ensureDefaultStageB:options.ensureDefaultStageB,expectedGeneration:options.expectedGeneration,transitionId:options.transitionId}:{type:"gate_recorded",gate,sessionId,turbo,expectedGeneration:options.expectedGeneration,transitionId:options.transitionId}),telemetry.gatePassed(sessionId,gate,taskId)}async function recordTodoScanEvidence(directory,taskId,scan){assertValidTaskId(taskId),await withTaskEvidenceTransaction(directory,taskId,"todo_scan_recorded",async(transaction)=>{let base=transaction.read()??{taskId,required_gates:[],gates:{},workflow:createDefaultWorkflowMetadata(new Date().toISOString())};if(!transaction.save)throw Error(`TASK_EVIDENCE_SAVE_UNAVAILABLE: transaction for task ${taskId} does not support supplementary writes`);await transaction.save({...base,todo_scan:scan})})}async function recordAgentDispatch(directory,taskId,agentType,turbo,context={}){assertValidTaskId(taskId);let expectedGeneration=getTaskWorkflowSnapshot(await readTaskEvidence(directory,taskId)).generation;await transitionTaskWorkflowEvidence(directory,taskId,agentType==="coder"?{type:"accepted_mutation",agentType,turbo,context,expectedGeneration}:{type:"dispatch_attempted",agentType,turbo,context,expectedGeneration})}async function readTaskEvidence(directory,taskId){let state2=await readTaskEvidenceState(directory,taskId);return state2.kind==="ok"?state2.evidence:null}async function readTaskEvidenceState(directory,taskId){try{assertValidTaskId(taskId)}catch{return{kind:"missing"}}try{let evidencePath=getEvidencePath(directory,taskId),raw=readFileSync13(evidencePath,"utf-8");return{kind:"ok",evidence:parseTaskEvidence(raw,taskId)}}catch(error49){let evidencePath=getEvidencePathSafe(directory,taskId),code=error49.code;if(code==="ENOENT"||code==="ENAMETOOLONG")return{kind:"missing"};return telemetry.gateParseError(taskId,error49),{kind:"unparseable",evidencePath,error:error49}}}function getEvidencePathSafe(directory,taskId){try{return getEvidencePath(directory,taskId)}catch{return`${directory}/.swarm/evidence/${taskId}.json`}}function readTaskEvidenceRaw(directory,taskId){assertValidTaskId(taskId);let evidencePath=getEvidencePath(directory,taskId);try{let raw=readFileSync13(evidencePath,"utf-8");return parseTaskEvidence(raw,taskId)}catch(error49){let code=error49.code;if(code==="ENOENT"||code==="ENAMETOOLONG")return null;throw error49}}async function hasPassedAllGates(directory,taskId,currentDeclaredFiles){let evidence=await readTaskEvidence(directory,taskId);if(!evidence)return!1;if(!Array.isArray(evidence.required_gates))return!1;if(currentDeclaredFiles===void 0){if(deriveApplicableGateSet(evidence).readOnlyNoMutation)return!1;return hasAllRequiredGatesPassed(evidence.required_gates,evidence.gates)}return deriveApplicableGateSet(evidence,{currentDeclaredFiles}).missingGates.length===0}function compareTaskWorkflowStateRank(left,right){return WORKFLOW_STATE_RANK[left]-WORKFLOW_STATE_RANK[right]}var _internals38,TASK_WORKFLOW_SCHEMA_MARKER="exact-task-v1",TASK_WORKFLOW_STATES,TASK_WORKFLOW_OUTCOMES,MAX_PLAN_SCOPE_INSPECTION_BYTES=4194304,TASK_GATE_REQUIREMENTS_RECONSTRUCTION_SENTINEL="requirements_reconstruction",GateEvidenceSchema,ExternalEvidenceBundleSchema,TaskWorkflowMetadataSchema,TaskEvidenceSchema,DEFAULT_REQUIRED_GATES,DEFAULT_WORKFLOW_STATE="idle",WORKFLOW_STATE_RANK;var init_gate_evidence=__esm(()=>{init_zod();init_task_file();init_task_gate_requirements();init_utils2();init_utils3();init_telemetry();init_task_id();init_workflow_wal_file();_internals38={appendTaskGateRequirementsReceiptIfNeeded},TASK_WORKFLOW_STATES=["idle","coder_delegated","pre_check_passed","reviewer_run","tests_run","rework_required","complete","blocked","closed"],TASK_WORKFLOW_OUTCOMES=["none","dispatch_attempted","dispatch_no_mutation","accepted_mutation","accepted_mutation_failed","stage_a_passed","stage_a_failed","stage_b_completed","stage_b_failed","gate_recorded","task_completed","task_blocked","task_closed","repair_idle","external_evidence_attested","external_evidence_revoked"];GateEvidenceSchema=exports_external.object({sessionId:exports_external.string(),timestamp:exports_external.string(),agent:exports_external.string()}).passthrough(),ExternalEvidenceBundleSchema=exports_external.object({class:exports_external.literal("external_git"),transitionId:exports_external.string().min(1).max(512),declarationDigest:exports_external.string().regex(/^[a-f0-9]{64}$/),anchors:exports_external.array(exports_external.object({command:exports_external.string().min(1).max(400),expect:exports_external.string().max(4096).optional(),expect_prefix:exports_external.string().min(1).max(4096).optional(),matched:exports_external.boolean(),exit_code:exports_external.number().int(),stdout:exports_external.string().max(4096)})).min(1).max(16).superRefine((anchors,ctx)=>{anchors.forEach((anchor,index)=>{if(anchor.expect===void 0&&anchor.expect_prefix===void 0)ctx.addIssue({code:exports_external.ZodIssueCode.custom,message:`anchor ${index} must carry expect and/or a non-empty expect_prefix`,path:[index]})})}),attestedAt:exports_external.string().min(1)}),TaskWorkflowMetadataSchema=exports_external.object({schema:exports_external.literal(TASK_WORKFLOW_SCHEMA_MARKER),generation:exports_external.number().int().min(0),state:exports_external.enum(TASK_WORKFLOW_STATES),retryCount:exports_external.number().int().min(0).default(0),retryHistory:exports_external.array(exports_external.enum(TASK_WORKFLOW_OUTCOMES)).max(3).default([]),retryEpoch:exports_external.number().int().min(0).default(0),lastOutcome:exports_external.enum(TASK_WORKFLOW_OUTCOMES).default("none"),lastTransitionId:exports_external.string().min(1).nullable().optional().default(null),updatedAt:exports_external.string(),forcedCompletion:exports_external.boolean().optional(),supervisedRecovery:exports_external.boolean().optional(),settlementRecovery:exports_external.boolean().optional(),noMutationSettlement:exports_external.object({generation:exports_external.literal(0),transitionId:exports_external.string().min(1).max(512),declaredFiles:exports_external.array(exports_external.string()).length(0)}).optional(),externalEvidence:ExternalEvidenceBundleSchema.optional()}),TaskEvidenceSchema=exports_external.object({taskId:exports_external.string(),required_gates:exports_external.array(exports_external.string()).default([]),gates:exports_external.record(exports_external.string(),GateEvidenceSchema),turbo:exports_external.boolean().optional(),requirements_state:exports_external.enum(["known","unknown"]).optional(),test_engineer_exempt:exports_external.boolean().optional(),planId:exports_external.string().optional(),planIdentityHash:exports_external.string().regex(/^[a-f0-9]{64}$/).optional(),workflow:TaskWorkflowMetadataSchema.optional(),repair_provenance:exports_external.object({source_sha256:exports_external.string().regex(/^[a-f0-9]{64}$/).nullable(),source_generation:exports_external.number().int().min(0).nullable(),requirements_receipt_hash:exports_external.string().regex(/^[a-f0-9]{64}$/).nullable()}).optional(),todo_scan:exports_external.object({priority:exports_external.string(),count:exports_external.number().int().min(0),details:exports_external.array(exports_external.string()).max(200).optional(),recorded_at:exports_external.string().optional()}).optional()});DEFAULT_REQUIRED_GATES=["reviewer","test_engineer"],WORKFLOW_STATE_RANK={idle:0,coder_delegated:1,pre_check_passed:2,reviewer_run:3,tests_run:4,rework_required:5,blocked:6,closed:7,complete:8}});import*as path41 from"node:path";function normalizeCandidate(value){if(typeof value!=="string"||value.length===0)return null;if([...value].some((character)=>{let codePoint=character.codePointAt(0)??0;return codePoint<=31||codePoint===127}))return null;if(path41.win32.isAbsolute(value)||path41.posix.isAbsolute(value))return null;let normalized=value.replace(/\\/g,"/");if(normalized.split("/").some((segment)=>segment===""||segment==="."||segment===".."))return null;return normalized}function isExactMarkdownPath(value){let normalized=normalizeCandidate(value);return normalized!==null&&path41.posix.extname(normalized)===".md"}function isMarkdownOnlyDeclaredScope(value){return Array.isArray(value)&&value.length>0&&value.every(isExactMarkdownPath)}function isMarkdownOnlyTaskChange(declaredFiles,observedFiles){if(!Array.isArray(declaredFiles)||!Array.isArray(observedFiles))return!1;if(!isMarkdownOnlyDeclaredScope(declaredFiles)||observedFiles.length===0)return!1;if(!observedFiles.every(isExactMarkdownPath))return!1;let declared=new Set(declaredFiles.map(normalizeCandidate).filter((value)=>value!==null));return observedFiles.every((value)=>{let normalized=normalizeCandidate(value);return normalized!==null&&declared.has(normalized)})}var init_gate_evidence_classification=()=>{};import{createHash as createHash23}from"node:crypto";import*as fs24 from"node:fs";import*as path42 from"node:path";function ownerDirectory(directory){return path42.dirname(validateSwarmPath(directory,path42.join(PROVISIONING_OWNER_DIR,".containment-anchor")))}function ownerPath(directory,callID){let digest2=createHash23("sha256").update(callID).digest("hex");return validateSwarmPath(directory,path42.join(PROVISIONING_OWNER_DIR,`${digest2}.json`))}function journalPath(directory){return validateSwarmPath(directory,PROVISIONING_JOURNAL_PATH)}function isOwner(value){if(!value||typeof value!=="object"||Array.isArray(value))return!1;let candidate=value,schemaVersion=candidate.schemaVersion,validTaskIdentity=schemaVersion===1?candidate.taskId===void 0&&candidate.reservationId===void 0&&candidate.generation===void 0&&candidate.branchName===void 0:schemaVersion===2&&typeof candidate.taskId==="string"&&candidate.taskId.length>0&&candidate.taskId.length<=512&&candidate.reservationId===void 0&&candidate.generation===void 0&&candidate.branchName===void 0,validV3Identity=schemaVersion===3&&typeof candidate.taskId==="string"&&candidate.taskId.length>0&&candidate.taskId.length<=512&&typeof candidate.reservationId==="string"&&candidate.reservationId.length>0&&candidate.reservationId.length<=512&&typeof candidate.generation==="number"&&Number.isInteger(candidate.generation)&&candidate.generation>0&&typeof candidate.branchName==="string"&&candidate.branchName.length>0&&candidate.branchName.length<=1024;return(schemaVersion===1||schemaVersion===2||schemaVersion===3)&&(validTaskIdentity||validV3Identity)&&typeof candidate.callID==="string"&&candidate.callID.length>0&&candidate.callID.length<=512&&typeof candidate.parentSessionId==="string"&&candidate.parentSessionId.length>0&&candidate.parentSessionId.length<=512&&typeof candidate.worktreeSessionId==="string"&&candidate.worktreeSessionId.length>0&&candidate.worktreeSessionId.length<=512&&typeof candidate.createdAt==="number"&&Number.isFinite(candidate.createdAt)&&candidate.createdAt>=0}function isLifecycleEntry(value){if(!value||typeof value!=="object"||Array.isArray(value))return!1;let candidate=value,validState=WORKTREE_PROVISIONING_LIFECYCLE_STATES.includes(candidate.state);return candidate.schemaVersion===1&&validState&&typeof candidate.callID==="string"&&candidate.callID.length>0&&candidate.callID.length<=512&&typeof candidate.parentSessionId==="string"&&candidate.parentSessionId.length>0&&candidate.parentSessionId.length<=512&&typeof candidate.worktreeSessionId==="string"&&candidate.worktreeSessionId.length>0&&candidate.worktreeSessionId.length<=512&&(candidate.taskId===void 0||typeof candidate.taskId==="string"&&candidate.taskId.length>0&&candidate.taskId.length<=512)&&(candidate.reservationId===void 0||typeof candidate.reservationId==="string"&&candidate.reservationId.length>0&&candidate.reservationId.length<=512)&&(candidate.generation===void 0||typeof candidate.generation==="number"&&Number.isInteger(candidate.generation)&&candidate.generation>0)&&(candidate.branchName===void 0||typeof candidate.branchName==="string"&&candidate.branchName.length>0&&candidate.branchName.length<=1024)&&typeof candidate.recordedAt==="number"&&Number.isFinite(candidate.recordedAt)&&candidate.recordedAt>=0}function readBoundedJsonFile(filePath,maxBytes){try{if(fs24.statSync(filePath).size>maxBytes)return{ok:!1,reason:`${path42.basename(filePath)} exceeds the ${maxBytes}-byte safety bound`};let raw=fs24.readFileSync(filePath,"utf8");if(Buffer.byteLength(raw,"utf8")>maxBytes)return{ok:!1,reason:`${path42.basename(filePath)} changed beyond the ${maxBytes}-byte safety bound`};return{ok:!0,value:JSON.parse(raw)}}catch(error49){if(error49.code==="ENOENT")return{ok:!0,value:void 0};return{ok:!1,reason:`${path42.basename(filePath)} is unreadable or malformed: ${error49 instanceof Error?error49.message:String(error49)}`}}}function readOwner(directory,callID){let absolutePath=ownerPath(directory,callID),loaded=readBoundedJsonFile(absolutePath,MAX_PROVISIONING_OWNER_BYTES);if(!loaded.ok||loaded.value===void 0)return null;return isOwner(loaded.value)?loaded.value:null}function loadLifecycleJournal(directory){let loaded=readBoundedJsonFile(journalPath(directory),MAX_PROVISIONING_JOURNAL_BYTES);if(!loaded.ok)return{status:"uncertain",reason:loaded.reason};if(loaded.value===void 0)return{status:"ok",entries:[]};let parsed=loaded.value;if(parsed.schemaVersion!==1||!Array.isArray(parsed.entries))return{status:"uncertain",reason:"worktree provisioning lifecycle journal is malformed"};if(parsed.entries.length>MAX_PROVISIONING_JOURNAL_ENTRIES)return{status:"uncertain",reason:`worktree provisioning lifecycle journal exceeds the ${MAX_PROVISIONING_JOURNAL_ENTRIES}-entry safety bound`};let entries=[];for(let entry of parsed.entries){if(!isLifecycleEntry(entry))return{status:"uncertain",reason:"worktree provisioning lifecycle journal contains an invalid entry"};entries.push(entry)}return{status:"ok",entries}}function appendLifecycleEntry(directory,owner,state2){let loaded=loadLifecycleJournal(directory);if(loaded.status==="uncertain")throw Error(loaded.reason);let journal={schemaVersion:1,entries:[...loaded.entries,{schemaVersion:1,state:state2,callID:owner.callID,parentSessionId:owner.parentSessionId,worktreeSessionId:owner.worktreeSessionId,...owner.taskId?{taskId:owner.taskId}:{},...owner.reservationId?{reservationId:owner.reservationId}:{},...owner.generation!==void 0?{generation:owner.generation}:{},...owner.branchName?{branchName:owner.branchName}:{},recordedAt:Date.now()}].slice(-MAX_PROVISIONING_JOURNAL_ENTRIES)};atomicWriteSwarmFileSync(journalPath(directory),JSON.stringify(journal,null,2))}function recordWorktreeProvisioningOwner(directory,input){let wantsV3=input.reservationId!==void 0||input.generation!==void 0||input.branchName!==void 0;if(wantsV3&&(!input.taskId||!input.reservationId||input.generation===void 0||!input.branchName))throw Error("worktree provisioning owner v3 requires taskId, reservationId, generation, and branchName");let owner={schemaVersion:wantsV3?3:input.taskId?2:1,callID:input.callID,parentSessionId:input.parentSessionId,worktreeSessionId:input.worktreeSessionId,...input.taskId?{taskId:input.taskId}:{},...input.reservationId?{reservationId:input.reservationId}:{},...input.generation!==void 0?{generation:input.generation}:{},...input.branchName?{branchName:input.branchName}:{},createdAt:Date.now()};if(!isOwner(owner))throw Error("invalid worktree provisioning owner");let absolutePath=ownerPath(directory,input.callID);return fs24.mkdirSync(path42.dirname(absolutePath),{recursive:!0}),atomicWriteSwarmFileSync(absolutePath,`${JSON.stringify(owner)}
|
|
614
614
|
`),appendLifecycleEntry(directory,owner,"OWNER_PUBLISHED"),owner}function removeWorktreeProvisioningOwner(directory,callID,expected){try{let owner=readOwner(directory,callID);if(owner?.schemaVersion===3&&(!expected||expected.reservationId!==owner.reservationId||expected.generation!==owner.generation||expected.branchName!==owner.branchName))return!1;if(fs24.unlinkSync(ownerPath(directory,callID)),owner)appendLifecycleEntry(directory,owner,"OWNER_REMOVED");return!0}catch(error49){return error49.code==="ENOENT"}}function scanWorktreeProvisioningOwnersForRecovery(directory){let directoryPath,entries;try{directoryPath=ownerDirectory(directory),entries=fs24.readdirSync(directoryPath,{withFileTypes:!0}).filter((entry)=>entry.isFile()&&entry.name.endsWith(".json"))}catch(error49){if(error49.code==="ENOENT")return{status:"ok",owners:[]};return{status:"uncertain",reason:`worktree provisioning-owner directory is unreadable: ${error49 instanceof Error?error49.message:String(error49)}`}}if(entries.length>MAX_PROVISIONING_OWNERS)return{status:"uncertain",reason:`worktree provisioning-owner count exceeds the ${MAX_PROVISIONING_OWNERS}-marker safety bound`};let owners=[];for(let entry of entries){let absolutePath=path42.join(directoryPath,entry.name);try{if(fs24.statSync(absolutePath).size>MAX_PROVISIONING_OWNER_BYTES)return{status:"uncertain",reason:`worktree provisioning owner "${entry.name}" exceeds the recovery size bound`};let raw=fs24.readFileSync(absolutePath,"utf8");if(Buffer.byteLength(raw,"utf8")>MAX_PROVISIONING_OWNER_BYTES)return{status:"uncertain",reason:`worktree provisioning owner "${entry.name}" changed beyond the recovery size bound`};let parsed=JSON.parse(raw);if(!isOwner(parsed))return{status:"uncertain",reason:`worktree provisioning owner "${entry.name}" is invalid`};owners.push(parsed)}catch(error49){return{status:"uncertain",reason:`worktree provisioning owner "${entry.name}" is unreadable or malformed: ${error49 instanceof Error?error49.message:String(error49)}`}}}return{status:"ok",owners}}function scanWorktreeProvisioningLifecycleJournalForRecovery(directory){return loadLifecycleJournal(directory)}var PROVISIONING_OWNER_DIR="worktree-provisioning-owners",MAX_PROVISIONING_OWNERS=512,MAX_PROVISIONING_OWNER_BYTES=16384,PROVISIONING_JOURNAL_PATH,MAX_PROVISIONING_JOURNAL_BYTES=262144,MAX_PROVISIONING_JOURNAL_ENTRIES=512,WORKTREE_PROVISIONING_OWNER_LEASE_MS=300000,WORKTREE_LIFECYCLE_LOCK_FILE=".swarm/locks/init-orphan-recovery.lock",WORKTREE_PROVISIONING_LIFECYCLE_STATES;var init_worktree_provisioning_owner=__esm(()=>{init_atomic_write();init_utils2();PROVISIONING_JOURNAL_PATH=path42.join(".swarm","worktree-provisioning-lifecycle.json"),WORKTREE_PROVISIONING_LIFECYCLE_STATES=["OWNER_PUBLISHED","OWNER_REMOVED"]});import{spawnSync as spawnSync3}from"node:child_process";import{existsSync as existsSync21}from"node:fs";import{tmpdir as tmpdir4}from"node:os";function resolveBwrapBinary(){try{if(existsSync21(BWRAP_ABSOLUTE))return BWRAP_ABSOLUTE}catch{}return"bwrap"}function shellQuote(s){return`'${shellEscape(s)}'`}function buildBwrapArgs(input){let{quote}=input,roBindArgs=input.readonlyRoots.flatMap((p)=>["--ro-bind",quote(p),quote(p)]),bindArgs=input.scopes.flatMap((p)=>["--bind",quote(p),quote(p)]),args2=["--unshare-user","--unshare-ipc","--die-with-parent","--new-session","--cap-drop","ALL",...roBindArgs,...bindArgs,"--dev","/dev","--size",String(TMPFS_SIZE_BYTES),"--tmpfs",quote(input.temp),"--ro-bind","/etc","/etc","--ro-bind","/usr","/usr","--ro-bind","/lib","/lib","--ro-bind","/lib64","/lib64","--proc","/proc","--unshare-pid",...input.envArgs,"--","bash","-c",quote(input.command)];if((input.networkMode??"off")==="off")args2.splice(1,0,"--unshare-net");return args2}function probeBwrapNamespace(binary){try{let result=spawnSync3(binary,[...BWRAP_NAMESPACE_SMOKE_ARGS],{cwd:tmpdir4(),windowsHide:!0,encoding:"utf-8",timeout:5000,stdio:["ignore","ignore","pipe"]});if(!result.error&&result.status===0)return{ok:!0};return{ok:!1,reason:result.error?.message??(result.stderr?.trim().split(`
|
|
615
615
|
`)[0]||`exit ${result.status}`)}}catch(err){return{ok:!1,reason:err instanceof Error?err.message:String(err)}}}function probeBwrap(){try{let binary=_internals39.resolveBwrapBinary(),result=spawnSync3(binary,["--version"],{cwd:tmpdir4(),windowsHide:!0,encoding:"utf-8",timeout:5000,stdio:["ignore","pipe","ignore"]});if(result.error){let code=result.error.code;if(code&&BWRAP_UNAVAILABLE_CODES.has(code))return warn(`Sandbox disabled: bwrap error (${code}). Falling through to tool-layer enforcement.`),!1;return warn(`Sandbox disabled: bwrap spawn error (${result.error.message}). Falling through to tool-layer enforcement.`),!1}if(result.status!==BWRAP_VERSION_EXIT||result.stdout.trim().length===0)return!1;let smoke=_internals39.probeBwrapNamespace(binary);if(!smoke.ok)return warn(`Sandbox disabled: bwrap cannot create a sandbox on this host (${smoke.reason}). Unprivileged user namespaces may be restricted (Ubuntu 24.04+: kernel.apparmor_restrict_unprivileged_userns=1). Falling through to tool-layer enforcement.`),!1;return!0}catch(err){let message=err instanceof Error?err.message:String(err);return warn(`Sandbox disabled: probe threw (${message}). Falling through to tool-layer enforcement.`),!1}}function shellEscape(s){return s.replace(/'/g,"'\\''")}class BubblewrapSandboxExecutor{mechanism="Bubblewrap";_scopePaths;_tempDir;_available;_disabledReason;constructor(scopePaths=[],tempDir){this._scopePaths=scopePaths,this._tempDir=tempDir,this._available=!1,this._disabledReason=null;try{if(!_internals39.probeBwrap())this._disabledReason="bwrap not available or not functional",warn(`Sandbox disabled: ${this._disabledReason}. Falling through to tool-layer enforcement.`);else this._available=!0}catch(err){let message=err instanceof Error?err.message:String(err);this._disabledReason=`constructor threw: ${message}`,this._available=!1,warn(`Sandbox disabled: ${this._disabledReason}. Falling through to tool-layer enforcement.`)}}isAvailable(){return this._available}disable(reason){this._available=!1,this._disabledReason=reason,warn(`Sandbox disabled: ${reason}. Falling through to tool-layer enforcement.`)}wrapCommand(command,scopePaths,tempDir,envOverrides,policy){if(!this._available)throw new SandboxError("Sandbox not available","SANDBOX_UNAVAILABLE");let temp=tempDir??this._tempDir??"/tmp",allScopes=[...this._scopePaths,...scopePaths],readonlyRoots=[...new Set((policy?.readonly_roots??[]).filter((p)=>typeof p==="string"&&p.startsWith("/")&&p!=="/"))],envArgs=[];if(envOverrides)for(let[key,value]of Object.entries(envOverrides)){if(!isValidEnvKey(key))continue;if(value===null)envArgs.push("--unsetenv",key);else envArgs.push("--setenv",key,shellQuote(value))}let args2=buildBwrapArgs({quote:shellQuote,temp,readonlyRoots,scopes:allScopes,envArgs,networkMode:policy?.network_mode,command});return`${_internals39.resolveBwrapBinary()} ${args2.join(" ")}`}getEnvOverrides(){return{}}}var BWRAP_VERSION_EXIT=0,BWRAP_UNAVAILABLE_CODES,BWRAP_ABSOLUTE="/usr/bin/bwrap",TMPFS_SIZE_BYTES=524288000,BWRAP_NAMESPACE_SMOKE_ARGS,_internals39;var init_bubblewrap_executor=__esm(()=>{init_logger();init_executor();BWRAP_UNAVAILABLE_CODES=new Set(["ENOENT","EACCES","ENOSPC"]);BWRAP_NAMESPACE_SMOKE_ARGS=buildBwrapArgs({quote:(value)=>value,temp:"/tmp",readonlyRoots:[],scopes:[],envArgs:[],networkMode:"off",command:"true"});_internals39={probeBwrap,probeBwrapNamespace,resolveBwrapBinary}});import{spawnSync as spawnSync4}from"node:child_process";import{existsSync as existsSync22,mkdtempSync,writeFileSync as writeFileSync9}from"node:fs";import*as os9 from"node:os";import*as path43 from"node:path";function resolveBinary(absolutePath,bareName){try{if(_internals40.exists(absolutePath))return absolutePath}catch{}return bareName}function resolveSandboxExecBinary(){return resolveBinary(SANDBOX_EXEC_ABSOLUTE,"sandbox-exec")}function resolveProbeTargetBinary(){return resolveBinary(TRUE_ABSOLUTE,"true")}function buildProbeProfile(tempDir){return`(version 1)
|
|
616
616
|
(allow default)
|
|
@@ -703,7 +703,7 @@ ${formatSwarmPlanTrailer(planKey)}`}function cacheRootTimestamp(key,value){if(ro
|
|
|
703
703
|
`)}function summarizeClosedWave(wave,outcomes){let resolutions={};for(let outcome of outcomes)resolutions[outcome.taskId]=outcome.resolution;return{seq:wave.seq,phase:wave.phase,taskIds:[...wave.taskIds],resolutions,closeHead:wave.closeHead??null,divergence:outcomes.filter((o)=>o.undeclared.length>0).map((o)=>({taskId:o.taskId,undeclared:o.undeclared})),waveUndeclared:wave.undeclared??[]}}function predecessorMessage(problems,planKey){let lines=problems.slice(0,10).map((p)=>`${p.taskId} depends on ${p.dependency}, which ${PREDECESSOR_WHY[p.why]}`),more=problems.length>10?` (+${problems.length-10} more)`:"",committedHint=problems.some((p)=>p.why==="not-committed")?` For a task whose work IS on the epic branch, ask the user to run \`/swarm epic status --repair-refs\` (it re-adopts the task's commit: its \`swarm(task <id>): …\` commit with the trailer \`Swarm-Plan: ${planKey}\`, else the newest commit touching its declared files); if its work is missing, re-run the task.`:"";return`These tasks can never run as planned: ${lines.join("; ")}${more}. Tell the user and fix the plan — drop or correct the dependency (save_plan), or close the dependent task (update_task_status closed).${committedHint} Then call epic_next_wave.`}function syncPhaseRecords(phases,currentPhase,currentStatus){let key=String(currentPhase),prior=phases[key];if(prior?.status===currentStatus||prior?.status==="complete")return phases;return{...phases,[key]:{status:currentStatus,reviewRuns:prior?.reviewRuns??0,verdicts:prior?.verdicts??[]}}}var PREDECESSOR_WHY;var init_next_wave_format=__esm(()=>{PREDECESSOR_WHY={removed:"is no longer in the plan",closed:"was closed (its work will never exist)","later-phase":"belongs to a later phase","not-committed":"is completed but its commit is not on the epic branch (no epic task ref, or the ref is no longer reachable from HEAD — e.g. it was completed outside a wave, or a rebase/amend rewrote its commit)",cycle:"forms a dependency cycle"}});import*as path54 from"node:path";function toCoChangeEntry(pair){return{fileA:pair.fileA,fileB:pair.fileB,npmi:pair.npmi,coChangeCount:pair.coChangeCount,lift:0,hasStaticEdge:!1,totalCommits:0,commitsA:0,commitsB:0}}function epicWaveVerdictOptions(plan,wave){return{plan,scopes:wave.files,useCochange:!!wave.cochange,...wave.cochange?{cochangePairs:wave.cochange.pairs.map(toCoChangeEntry),cochangeThreshold:wave.cochange.threshold}:{}}}function computeEpicWaveVerdict(directory,plan,wave,taskIds){return _internals53.computeParallelVerdict(directory,taskIds,epicWaveVerdictOptions(plan,wave))}function reject(code,message){return{kind:"reject",code,message}}function errorText2(error49){return error49 instanceof Error?error49.message:String(error49)}function findPlanTask(plan,taskId){for(let phase of plan.phases){let task=(phase.tasks??[]).find((t)=>t.id===taskId);if(task)return task}return null}function isResolved(status){return status==="completed"||status==="closed"}function list(items,max=8){let shown=items.slice(0,max).join(", ");return items.length>max?`${shown}, …`:shown}function resolveEpicDispatchPolicy(directory,plan,incomingTaskId,liveBindingFiles){if(!_internals53.epicSentinelExists(directory))return null;if(!_internals53.isEpicModeConfigEnabledForDirectory(directory))return null;let epic;try{epic=_internals53.getOpenEpic(directory,plan)}catch(error49){return reject("EPIC_STATE_UNREADABLE",`Epic Mode is enabled and an epic sentinel exists, but the epic's lifecycle state is unreadable (${errorText2(error49)}). Coder dispatch is refused (fail closed) until it is repaired, because it cannot be told whether the coder belongs to an epic wave. Remedy: ask the user to run \`/swarm epic status\` (diagnose) and \`/swarm epic close --abandon\` (repair).`)}if(!epic){let closingKey=null;try{let record2=_internals53.inspectEpic(directory,null).record;if(record2?.status==="closing")closingKey=record2.epicKey}catch(error49){return reject("EPIC_STATE_UNREADABLE",`Epic Mode is enabled and an epic sentinel exists, but the epic's lifecycle state could not be read to determine whether a close is in progress (${errorText2(error49)}). Coder dispatch is refused (fail closed). Remedy: ask the user to run \`/swarm epic status\` (diagnose) and \`/swarm epic close --abandon\` (repair).`)}if(closingKey!==null)return reject("EPIC_CLOSING",`Epic \`${closingKey}\` is closing (an interrupted \`/swarm epic close\`), so a coder dispatched now would settle with no Epic context and merge back onto the branch the close is stepping off. Remedy: ask the user to rerun \`/swarm epic close\`.`);return null}let branch=_internals53.checkEpicBranch(directory,epic);if(!branch.ok)return reject("EPIC_BRANCH_MISMATCH",branch.message.replace(/^EPIC_BRANCH_MISMATCH:\s*/,""));let taskId=typeof incomingTaskId==="string"?incomingTaskId.trim():"";if(taskId.length===0||!findPlanTask(plan,taskId))return reject("EPIC_TASK_UNKNOWN",`${taskId?`task ${taskId} is`:"the coder dispatch names no task that is"} not a task of the plan epic \`${epic.epicKey}\` runs, so it cannot be dispatched while the epic is open. Remedy: call epic_next_wave and dispatch only the task ids of the wave it returns.`);let wave=epic.activeWaveSeq===null?void 0:epic.waves.find((w)=>w.seq===epic.activeWaveSeq&&w.status==="issued");if(!wave){let inReview=Object.entries(epic.phases).filter(([,record2])=>record2.status==="review").map(([phase])=>Number(phase)).filter((phase)=>Number.isFinite(phase)),reviewNote=inReview.length>0?` Phase ${inReview[0]} is in review: to fix review findings, ${epicPhaseFixSteps(inReview[0])}`:"";return reject("EPIC_NO_ACTIVE_WAVE",`no wave of epic \`${epic.epicKey}\` is active, so the coder for task ${taskId} is refused. Remedy: call epic_next_wave — it closes the finished wave and issues the next one — and dispatch only the tasks it returns.${reviewNote}`)}if(!wave.taskIds.includes(taskId))return reject("EPIC_TASK_NOT_IN_ACTIVE_WAVE",`task ${taskId} is not in the active wave ${wave.seq} (tasks: ${list(wave.taskIds)}). While an epic is open, coders run only for the active wave's tasks. Remedy: dispatch the wave's tasks, finish each (Stage A → Stage B → update_task_status(completed)), then call epic_next_wave for the next wave.`);let frozen=wave.files[taskId]??[],extra=(liveBindingFiles??[]).filter((file2)=>!scopeContains(frozen,file2));if(extra.length>0)return reject("EPIC_WAVE_SCOPE_DRIFT",`task ${taskId}'s declared scope has path(s) outside the scope frozen when wave ${wave.seq} was issued (outside: ${list(extra)}; frozen: ${list(frozen)}). The wave's parallel safety was proven on the frozen scope, and a frozen scope never grows. Remedy, one of: (1) re-declare the task within the frozen scope (declare_scope replace_existing: true, no FILE: line outside it) and dispatch again; (2) if the task genuinely needs the extra paths, finish it within the frozen scope or close it (update_task_status closed), and add the extra work as a NEW pending task of the current phase (save_plan) — epic_next_wave plans it into a later wave with its own scope; (3) ask the user to end the epic (\`/swarm epic close --abandon\`).`);let isolate=epic.git.isRepo&&epic.config.isolation==="worktree",unresolved=wave.taskIds.filter((id)=>{let task=findPlanTask(plan,id);return task!==null&&!isResolved(task.status)}),parallel=!1;if(isolate&&unresolved.includes(taskId)&&unresolved.length>=2)try{parallel=computeEpicWaveVerdict(directory,plan,wave,unresolved).verdict==="all_disjoint"}catch{parallel=!1}return{kind:"allow",parallel,isolate,maxConcurrent:Math.max(1,epic.config.maxParallel)}}function resolveEpicGateTaskAttribution(directory,files){if(!_internals53.epicSentinelExists(directory))return{kind:"none"};let epic;try{epic=_internals53.getOpenEpic(directory)}catch(error49){return{kind:"unattributable",message:`EPIC STAGE A ATTRIBUTION: the epic's lifecycle state is unreadable (${errorText2(error49)}), so this gate run cannot be credited to a wave task. Ask the user to run \`/swarm epic status\` (diagnose) or \`/swarm epic close --abandon\` (repair).`}}if(!epic||epic.activeWaveSeq===null)return{kind:"none"};let wave=epic.waves.find((w)=>w.seq===epic.activeWaveSeq&&w.status==="issued");if(!wave||wave.taskIds.length<2)return{kind:"none"};let scopes=wave.taskIds.map((id)=>`${id}: ${list(wave.files[id]??[])}`).join("; "),checked=(files??[]).filter((file2)=>file2.trim()!=="");if(checked.length===0)return{kind:"unattributable",message:`EPIC STAGE A ATTRIBUTION: wave ${wave.seq} runs ${wave.taskIds.length} tasks at once, and this gate run names no files, so it cannot be credited to one task. Re-run it with \`files\` set to ONE task's changed files (frozen scopes — ${scopes}).`};let relative12=checked.map((file2)=>path54.isAbsolute(file2)?path54.relative(directory,file2):file2),owners=wave.taskIds.filter((id)=>relative12.every((file2)=>scopeContains(wave.files[id]??[],file2)));if(owners.length===1)return{kind:"task",taskId:owners[0]};return{kind:"unattributable",message:owners.length===0?`EPIC STAGE A ATTRIBUTION: no task of wave ${wave.seq} owns every checked file (${list(relative12)}), so this gate run is credited to no task. Run the gate once per task, with \`files\` limited to that task's frozen scope (${scopes}).`:`EPIC STAGE A ATTRIBUTION: the checked files (${list(relative12)}) fall inside the frozen scope of several wave-${wave.seq} tasks (${list(owners)}), so this gate run is credited to no task. Run it with files only one task owns (${scopes}).`}}function resolveEpicPrFeedbackConflict(directory,declaredFiles){if(!_internals53.epicSentinelExists(directory))return null;let epic;try{epic=_internals53.getOpenEpic(directory)}catch(error49){return{code:"EPIC_STATE_UNREADABLE",message:`the open epic's lifecycle state is unreadable (${errorText2(error49)}), so this PR-feedback coder cannot be checked against the running wave (fail closed). Ask the user to run \`/swarm epic status\`.`}}if(!epic||epic.activeWaveSeq===null)return null;let wave=epic.waves.find((w)=>w.seq===epic.activeWaveSeq&&w.status==="issued");if(!wave)return null;let declared=(declaredFiles??[]).filter((file2)=>file2.trim()!=="").map((file2)=>path54.isAbsolute(file2)?path54.relative(directory,file2):file2),owners=[];for(let taskId of wave.taskIds){let frozen=wave.files[taskId]??[];if(declared.some((file2)=>scopeContains(frozen,file2)||frozen.some((entry)=>scopeContains([file2],entry))))owners.push(taskId)}if(owners.length===0)return null;return{code:"EPIC_PR_FEEDBACK_SCOPE_OVERLAP",message:`this PR-feedback coder's declared files (${list(declared)}) overlap the frozen scope of wave-${wave.seq} task(s) ${list(owners)}, which may be writing them right now. Let the wave finish (epic_next_wave closes it), then dispatch the PR-feedback coder.`}}var _internals53;var init_gate_policy=__esm(()=>{init_parallel_verdict();init_scope_binding();init_config_gate();init_epic_branch();init_lifecycle();init_next_wave_format();_internals53={epicSentinelExists,isEpicModeConfigEnabledForDirectory,getOpenEpic,inspectEpic,checkEpicBranch,computeParallelVerdict}});function canonicalProjectKey(directory){return canonicalRootKeyFresh(directory)}var defaultCanonicalRootRealpath,defaultCanonicalRootNativeRealpath;var init_canonical_project=__esm(()=>{init_canonical_root();defaultCanonicalRootRealpath=_internals8.realpathSync,defaultCanonicalRootNativeRealpath=_internals8.realpathSyncNative});function evictOldest(map2,cap){while(map2.size>=cap){let oldest=map2.keys().next().value;if(oldest===void 0)break;map2.delete(oldest)}}function hydrationProjectKey(directory){let memoKey=canonicalRootKeyLexical(directory),memoized=directoryKeyMemo.get(memoKey);if(memoized!==void 0)return memoized;let key=canonicalProjectKey(directory);if(!directoryKeyMemo.has(memoKey))evictOldest(directoryKeyMemo,MAX_DIRECTORY_KEY_MEMO);return directoryKeyMemo.set(memoKey,key),key}function beginHydrationScope(directory){let projectKey=hydrationProjectKey(directory),current=projectHydrationAuthorities.get(projectKey),generation=(current?.generation??0)+1;if(!current)evictOldest(projectHydrationAuthorities,MAX_TRACKED_PROJECTS);let authorityEpoch=current?.authorityEpoch??nextHydrationAuthorityEpoch();return projectHydrationAuthorities.set(projectKey,{generation,authorityEpoch}),{projectKey,generation,authorityEpoch}}function currentHydrationGeneration(projectKey){return projectHydrationAuthorities.get(projectKey)?.generation??0}function captureCurrentHydrationAuthority(projectKey){let current=projectHydrationAuthorities.get(projectKey);if(current)return{projectKey,...current};let authorityEpoch=nextHydrationAuthorityEpoch();evictOldest(projectHydrationAuthorities,MAX_TRACKED_PROJECTS);let record2={generation:0,authorityEpoch};return projectHydrationAuthorities.set(projectKey,record2),{projectKey,...record2}}function nextHydrationAuthorityEpoch(){if(hydrationAuthorityEpoch>=Number.MAX_SAFE_INTEGER)throw Error("hydration authority epoch exhausted");return hydrationAuthorityEpoch+=1,hydrationAuthorityEpoch}function isHydrationAuthorityCurrent(authority){let current=projectHydrationAuthorities.get(authority.projectKey);return current?.generation===authority.generation&¤t.authorityEpoch===authority.authorityEpoch}function isHydrationScopeCurrent(scope){return isHydrationAuthorityCurrent(scope)}function nextSessionHydrationStamp(projectKey){return currentHydrationGeneration(projectKey)+1}function getRehydrationCache(projectKey){let entry=rehydrationCaches.get(projectKey),authority=projectHydrationAuthorities.get(projectKey);if(!entry||!authority||entry.authorityEpoch!==authority.authorityEpoch)return;return entry.cache}function setRehydrationCache(projectKey,cache2,authority){let cacheAuthority=authority??captureCurrentHydrationAuthority(projectKey);if(cacheAuthority.projectKey!==projectKey||!isHydrationAuthorityCurrent(cacheAuthority))return!1;if(!rehydrationCaches.has(projectKey))evictOldest(rehydrationCaches,MAX_TRACKED_PROJECTS);return rehydrationCaches.set(projectKey,{cache:cache2,authorityEpoch:cacheAuthority.authorityEpoch}),!0}function recordHydratedAggregateKeys(projectKey,keys,authority){let aggregateAuthority=authority??captureCurrentHydrationAuthority(projectKey);if(aggregateAuthority.projectKey!==projectKey||!isHydrationAuthorityCurrent(aggregateAuthority))return!1;if(!hydratedAggregateKeys.has(projectKey))evictOldest(hydratedAggregateKeys,MAX_TRACKED_PROJECTS);return hydratedAggregateKeys.set(projectKey,{keys:new Set(keys),authorityEpoch:aggregateAuthority.authorityEpoch}),!0}function hydratedAggregateKeysFor(projectKey,authority){let entry=hydratedAggregateKeys.get(projectKey),current=authority??projectHydrationAuthorities.get(projectKey);if(!entry||!current||entry.authorityEpoch!==current.authorityEpoch)return new Set;return entry.keys}function clearHydrationOwnershipState(){projectHydrationAuthorities.clear(),rehydrationCaches.clear(),hydratedAggregateKeys.clear(),directoryKeyMemo.clear()}var MAX_TRACKED_PROJECTS=32,MAX_DIRECTORY_KEY_MEMO=64,projectHydrationAuthorities,hydrationAuthorityEpoch=0,rehydrationCaches,hydratedAggregateKeys,directoryKeyMemo;var init_hydration_ownership=__esm(()=>{init_canonical_project();init_canonical_root();projectHydrationAuthorities=new Map,rehydrationCaches=new Map,hydratedAggregateKeys=new Map,directoryKeyMemo=new Map});function resolveEpicLearningSettings(config2){let learning=resolveEpicConfig(config2)?.learning,d=DEFAULT_EPIC_LEARNING_SETTINGS;return{enabled:learning?.enabled??d.enabled,decayPerEpic:learning?.decay_per_epic??d.decayPerEpic,halfLifeDays:learning?.half_life_days??d.halfLifeDays,hotExcess:learning?.hot_excess??d.hotExcess}}function emptyEpicLearning(){return{files:new Map,edges:new Map}}function isEpicLearningEmpty(stats2){return stats2.files.size===0&&stats2.edges.size===0}function cloneEpicLearning(stats2){let edges=new Map;for(let[from,targets]of stats2.edges)edges.set(from,new Map(targets));let files=new Map;for(let[file2,s]of stats2.files)files.set(file2,{...s});return{files,edges}}function isLearnablePath(file2){return file2.length>0&&file2!=="."&&file2!==".swarm"&&!file2.startsWith(".swarm/")&&!file2.startsWith("../")&&file2!==".."&&!file2.startsWith("/")}function learnablePaths(files){let out=new Set;for(let file2 of files){let normalized=normalizePath(file2);if(isLearnablePath(normalized))out.add(normalized)}return[...out]}function addFile(stats2,file2,alpha,beta){if(alpha===0&&beta===0)return;let current=stats2.files.get(file2)??{alpha:0,beta:0};current.alpha+=alpha,current.beta+=beta,stats2.files.set(file2,current)}function addEdge(stats2,from,to,weight){if(from===to||weight===0)return;let targets=stats2.edges.get(from)??new Map;targets.set(to,(targets.get(to)??0)+weight),stats2.edges.set(from,targets)}function undeclaredFiles(declaredScope,actualFiles){let declared=[...new Set(declaredScope.map(normalizePath))],actual=[...new Set(actualFiles.map(normalizePath))].sort(),covers=(d,f)=>d.length<=f.length&&pathsConflict(d,f);return actual.filter((f)=>!declared.some((d)=>covers(d,f)))}function reworkCharge(generation){let w=EPIC_LEARNING_INCIDENT_WEIGHTS,g=Number.isFinite(generation)?generation:0;return w.reworkPerGeneration*Math.min(Math.max(g-1,0),w.reworkMaxGenerations)}function count(value){return Number.isFinite(value)?Math.max(0,value):0}function epicLearningFromOutcomes(outcomes,options={}){let w=EPIC_LEARNING_INCIDENT_WEIGHTS,stats2=emptyEpicLearning();for(let outcome of outcomes){if(outcome.resolution==="removed")continue;let declared=learnablePaths(outcome.declared),undeclared=learnablePaths(outcome.undeclared).filter((file2)=>!declared.includes(file2)),all=[...declared,...undeclared],fileEntries=declared.filter((entry)=>!all.some((other)=>other!==entry&&other.length>entry.length&&pathsConflict(entry,other))&&!(options.isDirectory?.(entry)??!1));for(let file2 of fileEntries)addFile(stats2,file2,0,1);for(let file2 of undeclared){addFile(stats2,file2,w.undeclared,0);for(let from of declared)addEdge(stats2,from,file2,1)}let previous=outcome.previous&&options.learnedThroughWaveSeq!==void 0&&outcome.previous.waveSeq<=options.learnedThroughWaveSeq?outcome.previous:null,perDeclared=outcome.mergeFailure?w.mergeFailurePerDeclared:0;if(perDeclared+=w.stageBFailure*Math.max(0,count(outcome.stageBFailures)-count(previous?.stageBFailures)),perDeclared+=Math.max(0,reworkCharge(outcome.generation)-(previous?reworkCharge(previous.generation):0)),perDeclared+=w.reopen*Math.max(0,count(outcome.reopened)-count(previous?.reopened)),perDeclared>0)for(let file2 of fileEntries)addFile(stats2,file2,perDeclared,0)}return stats2}function mergeEpicLearning(a,b){let out=cloneEpicLearning(a);for(let[file2,s]of b.files)addFile(out,file2,s.alpha,s.beta);for(let[from,targets]of b.edges)for(let[to,weight]of targets)addEdge(out,from,to,weight);return out}function scaleEpicLearning(stats2,factor){let f=Number.isFinite(factor)?Math.min(Math.max(factor,0),1):1,out=emptyEpicLearning();for(let[file2,s]of stats2.files)out.files.set(file2,{alpha:s.alpha*f,beta:s.beta*f});for(let[from,targets]of stats2.edges){let scaled=new Map;for(let[to,weight]of targets)scaled.set(to,weight*f);out.edges.set(from,scaled)}return out}function epicTimeDecayFactor(updatedAtIso,nowMs,halfLifeDays){let updated=updatedAtIso?Date.parse(updatedAtIso):Number.NaN;if(!Number.isFinite(updated)||!Number.isFinite(nowMs))return 1;if(!(halfLifeDays>0))return 1;let days=Math.max(0,nowMs-updated)/DAY_MS;return 0.5**Math.floor(days/halfLifeDays)}function boundEpicLearning(stats2){let maxFiles=resolveRetentionCap("MAX_EPIC_LEARNING_FILES",MAX_EPIC_LEARNING_FILES),maxEdges=resolveRetentionCap("MAX_EPIC_LEARNING_EDGES",MAX_EPIC_LEARNING_EDGES),files=[...stats2.files].filter(([file2,s])=>isLearnablePath(file2)&&Number.isFinite(s.alpha)&&Number.isFinite(s.beta)&&s.alpha>=0&&s.beta>=0&&s.alpha+s.beta>=EPIC_LEARNING_DROP_BELOW).sort(([fa,a],[fb,b])=>b.alpha+b.beta-(a.alpha+a.beta)||fa.localeCompare(fb)).slice(0,maxFiles),edges=[];for(let[from,targets]of stats2.edges)for(let[to,weight]of targets)if(isLearnablePath(from)&&isLearnablePath(to)&&from!==to&&Number.isFinite(weight)&&weight>=EPIC_LEARNING_DROP_BELOW)edges.push([from,to,weight]);edges.sort((a,b)=>b[2]-a[2]||a[0].localeCompare(b[0])||a[1].localeCompare(b[1]));let out=emptyEpicLearning();for(let[file2,s]of files)out.files.set(file2,{...s});for(let[from,to,weight]of edges.slice(0,maxEdges))addEdge(out,from,to,weight);return out}function epicIncidentRate(stats2){return(PRIOR_A0+stats2.alpha)/(PRIOR_A0+PRIOR_B0+stats2.alpha+stats2.beta)}function isEpicHotFile(stats2,hotExcess){return stats2.alpha>=EPIC_HOT_MIN_ALPHA&&epicIncidentRate(stats2)-EPIC_LEARNING_PRIOR_MEAN>hotExcess}function strongestCoWriteInto(stats2){let strongest=new Map;for(let targets of stats2.edges.values())for(let[to,weight]of targets)if(weight>(strongest.get(to)??0))strongest.set(to,weight);return strongest}function epicHotIncidentMass(stats2,strongestCoWriter){return strongestCoWriter>=EPIC_EXPANSION_MIN_WEIGHT?Math.max(0,stats2.alpha-strongestCoWriter):stats2.alpha}function epicHotEvidence(stats2,file2){let s=stats2.files.get(file2)??{alpha:0,beta:0},countedAlpha=epicHotIncidentMass(s,strongestCoWriteInto(stats2).get(file2)??0);return{alpha:s.alpha,countedAlpha,beta:s.beta,rate:epicIncidentRate({alpha:countedAlpha,beta:s.beta})}}function epicHotFiles(stats2,hotExcess){let strongest=strongestCoWriteInto(stats2);return[...stats2.files].map(([file2,s])=>[file2,{alpha:epicHotIncidentMass(s,strongest.get(file2)??0),beta:s.beta}]).filter(([,s])=>isEpicHotFile(s,hotExcess)).sort(([fa,a],[fb,b])=>epicIncidentRate(b)-epicIncidentRate(a)||fa.localeCompare(fb)).map(([file2])=>file2)}function expandEpicScope(scope,coWrites){let declared=[...new Set(scope.map(normalizePath))];if(!coWrites||coWrites.size===0)return declared;let sums=new Map;for(let from of declared)for(let[to,weight]of coWrites.get(from)??[])sums.set(to,(sums.get(to)??0)+weight);let learned=[...sums].filter(([file2,weight])=>weight>=EPIC_EXPANSION_MIN_WEIGHT&&!declared.includes(file2)).map(([file2])=>file2).sort((a,b)=>a.localeCompare(b));return[...declared,...learned]}function summarizeEpicLearning(stats2,hotExcess,limit=10){let edges=[];for(let[from,targets]of stats2.edges)for(let[to,weight]of targets)edges.push({from,to,weight});return edges.sort((a,b)=>b.weight-a.weight||a.from.localeCompare(b.from)||a.to.localeCompare(b.to)),{files:stats2.files.size,edges:edges.length,hotFiles:epicHotFiles(stats2,hotExcess),topCoWrites:edges.slice(0,limit)}}var MAX_EPIC_LEARNING_FILES=2000,MAX_EPIC_LEARNING_EDGES=2000,EPIC_LEARNING_DROP_BELOW=0.05,EPIC_LEARNING_PRIOR_MEAN=0.1,EPIC_LEARNING_PRIOR_STRENGTH=2,EPIC_HOT_MIN_ALPHA=1,EPIC_EXPANSION_MIN_WEIGHT=1,PRIOR_A0,PRIOR_B0,DAY_MS=86400000,EPIC_LEARNING_INCIDENT_WEIGHTS,DEFAULT_EPIC_LEARNING_SETTINGS;var init_learning=__esm(()=>{init_caps();init_conflicts();init_config();PRIOR_A0=EPIC_LEARNING_PRIOR_MEAN*EPIC_LEARNING_PRIOR_STRENGTH,PRIOR_B0=(1-EPIC_LEARNING_PRIOR_MEAN)*EPIC_LEARNING_PRIOR_STRENGTH,EPIC_LEARNING_INCIDENT_WEIGHTS=Object.freeze({undeclared:1,mergeFailurePerDeclared:0.5,stageBFailure:0.25,reworkPerGeneration:0.25,reworkMaxGenerations:4,reopen:0.5}),DEFAULT_EPIC_LEARNING_SETTINGS=Object.freeze({enabled:!0,decayPerEpic:0.7,halfLifeDays:60,hotExcess:0.25})});import{createHash as createHash29}from"node:crypto";import*as fs31 from"node:fs";import*as path55 from"node:path";function errorText3(error49){return error49 instanceof Error?error49.message:String(error49)}function priorPath(directory){return path55.join(directory,EPIC_PRIOR_LEARNING_RELATIVE_PATH)}function posteriorPath(directory){return path55.join(directory,EPIC_POSTERIOR_RELATIVE_PATH)}function encodeStats(stats2){let files=[...stats2.files].map(([file2,s])=>({path:file2,alpha:s.alpha,beta:s.beta})).sort((a,b)=>a.path.localeCompare(b.path)),edges=[];for(let[from,targets]of stats2.edges)for(let[to,weight]of targets)edges.push({from,to,weight});return edges.sort((a,b)=>a.from.localeCompare(b.from)||a.to.localeCompare(b.to)),{files,edges}}function decodeStats(raw){let stats2=emptyEpicLearning();for(let entry of raw.files){let current=stats2.files.get(entry.path)??{alpha:0,beta:0};stats2.files.set(entry.path,{alpha:current.alpha+entry.alpha,beta:current.beta+entry.beta})}for(let edge of raw.edges){let targets=stats2.edges.get(edge.from)??new Map;targets.set(edge.to,(targets.get(edge.to)??0)+edge.weight),stats2.edges.set(edge.from,targets)}return boundEpicLearning(stats2)}function readBounded(filePath){let size;try{size=fs31.statSync(filePath).size}catch(error49){if(error49?.code==="ENOENT")return null;throw error49}if(size>MAX_LEARNING_FILE_BYTES)throw Error(`${filePath} exceeds ${MAX_LEARNING_FILE_BYTES} bytes`);return fs31.readFileSync(filePath,"utf-8")}function sha2563(text){return createHash29("sha256").update(text).digest("hex")}function directoryProbe(directory){return(entry)=>{try{return fs31.statSync(path55.join(directory,entry)).isDirectory()}catch{return!1}}}function readEpicPrior(directory){let raw;try{raw=readBounded(priorPath(directory))}catch(error49){return{status:"unreadable",reason:errorText3(error49),digest:null}}if(raw===null)return{status:"absent",digest:null};try{let parsed=priorSchema.safeParse(JSON.parse(raw));if(!parsed.success)return{status:"unreadable",reason:`invalid ${EPIC_PRIOR_LEARNING_RELATIVE_PATH}: ${parsed.error.issues[0]?.message??"schema mismatch"}`,digest:null};return{status:"ok",digest:sha2563(raw),prior:{updatedAt:parsed.data.updatedAt,importedFrom:parsed.data.importedFrom,mergedEpics:parsed.data.mergedEpics.slice(-EPIC_PRIOR_MERGED_EPICS_KEEP),stats:decodeStats(parsed.data)}}}catch(error49){return{status:"unreadable",reason:errorText3(error49),digest:null}}}function writeEpicPrior(directory,prior){let target=priorPath(directory);fs31.mkdirSync(path55.dirname(target),{recursive:!0});let payload={schema:"epic-learning-v1",updatedAt:prior.updatedAt,importedFrom:prior.importedFrom,mergedEpics:prior.mergedEpics.slice(-EPIC_PRIOR_MERGED_EPICS_KEEP),...encodeStats(boundEpicLearning(prior.stats))};atomicWriteSwarmFileSync(target,`${JSON.stringify(payload,null,2)}
|
|
704
704
|
`)}function readEpicPosterior(directory){try{let raw=readBounded(posteriorPath(directory));if(raw===null)return null;let parsed=posteriorSchema.safeParse(JSON.parse(raw));if(!parsed.success)return null;return{epicKey:parsed.data.epicKey,token:parsed.data.token,priorDigest:parsed.data.priorDigest,createdAt:parsed.data.createdAt,lastAppliedWaveSeq:parsed.data.lastAppliedWaveSeq,base:{updatedAt:parsed.data.base.updatedAt,stats:decodeStats(parsed.data.base)},increments:decodeStats(parsed.data.increments)}}catch{return null}}function writeEpicPosterior(directory,posterior){let target=posteriorPath(directory);fs31.mkdirSync(path55.dirname(target),{recursive:!0});let payload={schema:"epic-posterior-v1",epicKey:posterior.epicKey,token:posterior.token,priorDigest:posterior.priorDigest,createdAt:posterior.createdAt,lastAppliedWaveSeq:posterior.lastAppliedWaveSeq,base:{updatedAt:posterior.base.updatedAt,...encodeStats(boundEpicLearning(posterior.base.stats))},increments:encodeStats(boundEpicLearning(posterior.increments))};atomicWriteSwarmFileSync(target,`${JSON.stringify(payload,null,2)}
|
|
705
705
|
`)}function warnOnce(key,message){if(warnedKeys.has(key))return;if(warnedKeys.size>=MAX_WARNED_KEYS){let oldest=warnedKeys.values().next().value;if(oldest!==void 0)warnedKeys.delete(oldest)}warnedKeys.add(key),criticalWarn(message)}function decayedPriorStats(prior,settings,nowMs){return scaleEpicLearning(prior.stats,epicTimeDecayFactor(prior.updatedAt,nowMs,settings.halfLifeDays))}function loadEpicLearningView(directory,epic,settings,nowMs){if(!settings.enabled)return{source:"none",stats:emptyEpicLearning()};if(epic!==null){let posterior=readEpicPosterior(directory);if(posterior&&posterior.epicKey===epic.epicKey&&posterior.token===epic.token){let base=scaleEpicLearning(posterior.base.stats,epicTimeDecayFactor(posterior.base.updatedAt,nowMs,settings.halfLifeDays));return{source:"posterior",stats:boundEpicLearning(mergeEpicLearning(base,posterior.increments))}}}let read=readEpicPrior(directory);if(read.status==="unreadable")return warnOnce(`prior\x00${directory}`,`[epic/learning] the project prior is unreadable (${read.reason}); epics plan without learned signals until \`/swarm epic prior reset\` clears it.`),{source:"prior-unreadable",stats:emptyEpicLearning()};if(read.status==="absent")return{source:"none",stats:emptyEpicLearning()};return{source:"prior",stats:decayedPriorStats(read.prior,settings,nowMs)}}function initEpicPosterior(directory,record2,snapshot){writeEpicPosterior(directory,{epicKey:record2.epicKey,token:record2.token,priorDigest:record2.priorDigest,createdAt:record2.startedAt,lastAppliedWaveSeq:0,base:snapshot.status==="ok"?{updatedAt:snapshot.prior.updatedAt,stats:snapshot.prior.stats}:{updatedAt:record2.startedAt,stats:emptyEpicLearning()},increments:emptyEpicLearning()})}function posteriorFor(directory,record2){let existing=readEpicPosterior(directory);if(existing&&existing.epicKey===record2.epicKey&&existing.token===record2.token)return existing;let prior=readEpicPrior(directory);return{epicKey:record2.epicKey,token:record2.token,priorDigest:prior.digest,createdAt:record2.startedAt,lastAppliedWaveSeq:0,base:prior.status==="ok"?{updatedAt:prior.prior.updatedAt,stats:prior.prior.stats}:{updatedAt:record2.startedAt,stats:emptyEpicLearning()},increments:emptyEpicLearning()}}function applyClosedWavesToPosterior(directory,record2,settings){if(!settings.enabled)return{appliedWaves:[]};let posterior=posteriorFor(directory,record2),pending=record2.waves.filter((wave)=>wave.status==="closed"&&wave.seq>posterior.lastAppliedWaveSeq).map((wave)=>wave.seq).sort((a,b)=>a-b);if(pending.length===0)return{appliedWaves:[]};let applied=new Set(pending),outcomes=Object.values(record2.tasks??{}).filter((outcome)=>applied.has(outcome.waveSeq));return writeEpicPosterior(directory,{...posterior,lastAppliedWaveSeq:pending[pending.length-1],increments:boundEpicLearning(mergeEpicLearning(posterior.increments,epicLearningFromOutcomes(outcomes,{isDirectory:directoryProbe(directory),learnedThroughWaveSeq:posterior.lastAppliedWaveSeq})))}),{appliedWaves:pending}}function mergeEpicPosteriorIntoPrior(directory,record2,reportKey,settings,nowMs){let none={learnedFiles:0,learnedEdges:0,hotFiles:[]};if(!settings.enabled)return{status:"disabled",...none,detail:"learning is disabled (epic.learning.enabled: false)"};try{try{applyClosedWavesToPosterior(directory,record2,settings)}catch(error49){warn(`[epic/learning] posterior catch-up failed; merging from the epic record: ${errorText3(error49)}`)}let posterior=readEpicPosterior(directory),increments=posterior&&posterior.epicKey===record2.epicKey&&posterior.token===record2.token?posterior.increments:boundEpicLearning(epicLearningFromOutcomes(Object.values(record2.tasks??{}),{isDirectory:directoryProbe(directory)})),learnedEdges=0;for(let targets of increments.edges.values())learnedEdges+=targets.size;let learned={learnedFiles:increments.files.size,learnedEdges},read=readEpicPrior(directory);if(read.status==="unreadable")return{status:"prior-unreadable",...learned,hotFiles:[],detail:`the project prior is unreadable (${read.reason}); this epic's observations were not merged — clear it with \`/swarm epic prior reset\``};let prior=read.status==="ok"?read.prior:null;if(prior?.mergedEpics.includes(reportKey))return removePosterior(directory,record2),{status:"already-merged",...learned,hotFiles:epicHotFiles(prior.stats,settings.hotExcess).slice(0,10),detail:"already merged into the project prior"};if(isEpicLearningEmpty(increments)){if(prior)writeEpicPrior(directory,{...prior,mergedEpics:[...prior.mergedEpics,reportKey]});return removePosterior(directory,record2),{status:"nothing-to-learn",...learned,hotFiles:prior?epicHotFiles(prior.stats,settings.hotExcess).slice(0,10):[],detail:"no outcomes to learn from"}}let decayed=prior?scaleEpicLearning(decayedPriorStats(prior,settings,nowMs),settings.decayPerEpic):emptyEpicLearning(),stats2=boundEpicLearning(mergeEpicLearning(decayed,increments));return writeEpicPrior(directory,{updatedAt:new Date(nowMs).toISOString(),importedFrom:prior?.importedFrom??null,mergedEpics:[...prior?.mergedEpics??[],reportKey],stats:stats2}),removePosterior(directory,record2),{status:"merged",...learned,hotFiles:epicHotFiles(stats2,settings.hotExcess).slice(0,10),detail:"merged into the project prior"}}catch(error49){return{status:"failed",...none,detail:`merging into the project prior failed: ${errorText3(error49)}`}}}function removePosterior(directory,record2){let existing=readEpicPosterior(directory);if(existing&&existing.epicKey!==record2.epicKey)return;try{fs31.rmSync(posteriorPath(directory),{force:!0})}catch{}}function resetEpicPrior(directory,nowMs){let read=readEpicPrior(directory),nowIso2=new Date(nowMs).toISOString();try{return writeEpicPrior(directory,{updatedAt:nowIso2,importedFrom:read.status==="ok"&&read.prior.importedFrom?read.prior.importedFrom:{source:"reset",at:nowIso2,calibrationHotModules:0,divergenceRecords:0},mergedEpics:read.status==="ok"?read.prior.mergedEpics:[],stats:emptyEpicLearning()}),{status:"reset",hadPrior:read.status!=="absent"}}catch(error49){return{status:"failed",detail:errorText3(error49)}}}function readLegacyHotModules(directory){let raw=readBounded(path55.join(directory,LEGACY_CALIBRATION_RELATIVE_PATH));if(raw===null)return null;let parsed=JSON.parse(raw);if(!Array.isArray(parsed?.hotModuleAdditions))return[];return parsed.hotModuleAdditions.filter((entry)=>typeof entry==="string").slice(0,MAX_LEGACY_HOT_MODULES)}function readLegacyDivergence(directory){let filePath=path55.join(directory,LEGACY_DIVERGENCE_RELATIVE_PATH),size;try{size=fs31.statSync(filePath).size}catch(error49){if(error49?.code==="ENOENT")return null;throw error49}let text,truncated=!1;if(size>MAX_LEGACY_DIVERGENCE_BYTES){let fd=fs31.openSync(filePath,"r");try{let buffer=Buffer.alloc(MAX_LEGACY_DIVERGENCE_BYTES);fs31.readSync(fd,buffer,0,MAX_LEGACY_DIVERGENCE_BYTES,size-MAX_LEGACY_DIVERGENCE_BYTES),text=buffer.toString("utf-8"),truncated=!0}finally{fs31.closeSync(fd)}}else text=fs31.readFileSync(filePath,"utf-8");let tail=text.split(`
|
|
706
|
-
`).filter((line)=>line.trim().length>0).slice(truncated?1:0).slice(-MAX_LEGACY_DIVERGENCE_RECORDS),records=[];for(let line of tail)try{let parsed=JSON.parse(line);if(parsed&&typeof parsed==="object")records.push(parsed)}catch{}let last=new Map;records.forEach((record2,index)=>{if(typeof record2.planId==="string"&&typeof record2.taskId==="string")last.set(`${record2.planId}\x00${record2.taskId}`,index)});let strings=(value)=>Array.isArray(value)?value.filter((entry)=>typeof entry==="string"):[];return records.filter((record2,index)=>typeof record2.planId!=="string"||typeof record2.taskId!=="string"||last.get(`${record2.planId}\x00${record2.taskId}`)===index).map((record2)=>({declared:strings(record2.declaredScope),undeclared:strings(record2.undeclared)}))}function importLegacyEpicCalibrationOnce(directory,nowMs){try{let read=readEpicPrior(directory);if(read.status==="unreadable")return{status:"prior-unreadable"};if(read.status==="ok"&&read.prior.importedFrom!==null)return{status:"already-imported"};let hotModules=null;try{hotModules=readLegacyHotModules(directory)}catch(error49){warn(`[epic/learning] Epic v1 calibration.json unreadable; not imported: ${errorText3(error49)}`)}let divergence=null;try{divergence=readLegacyDivergence(directory)}catch(error49){warn(`[epic/learning] Epic v1 divergence.jsonl unreadable; not imported: ${errorText3(error49)}`)}if(hotModules===null&&divergence===null)return{status:"nothing-to-import"};let increments=epicLearningFromOutcomes((divergence??[]).map((record2,index)=>({taskId:`legacy-${index}`,phase:0,waveSeq:0,resolution:"completed",resolvedAt:"",generation:0,stageAFailures:0,stageBFailures:0,mergeFailure:null,declared:record2.declared,undeclared:record2.undeclared,attribution:"session",reopened:0,marker:null})),{isDirectory:directoryProbe(directory)}),base=read.status==="ok"?read.prior.stats:emptyEpicLearning(),stats2=mergeEpicLearning(base,increments);for(let file2 of learnablePaths(hotModules??[])){let current=stats2.files.get(file2)??{alpha:0,beta:0};stats2.files.set(file2,{alpha:Math.max(current.alpha,EPIC_LEGACY_HOT_MODULE_ALPHA),beta:current.beta})}let nowIso2=new Date(nowMs).toISOString(),importedFrom={source:"epic-v1-import",at:nowIso2,calibrationHotModules:hotModules?.length??0,divergenceRecords:divergence?.length??0};return writeEpicPrior(directory,{updatedAt:nowIso2,importedFrom,mergedEpics:read.status==="ok"?read.prior.mergedEpics:[],stats:boundEpicLearning(stats2)}),{status:"imported",calibrationHotModules:importedFrom.calibrationHotModules,divergenceRecords:importedFrom.divergenceRecords}}catch(error49){return{status:"failed",detail:errorText3(error49)}}}function describeEpicPriorMerge(result){switch(result.status){case"merged":return`Learning: merged ${result.learnedFiles} file statistic(s) and ${result.learnedEdges} learned co-write(s) into the project prior (\`${EPIC_PRIOR_LEARNING_DISPLAY_PATH}\`)${result.hotFiles.length>0?`; hot files: ${result.hotFiles.slice(0,5).join(", ")}${result.hotFiles.length>5?", …":""}`:"; no hot files"}. Project prior kept (it survives /swarm close; \`/swarm epic prior reset\` clears it).`;case"already-merged":return"Learning: already merged into the project prior. Project prior kept.";case"nothing-to-learn":return"Learning: this epic recorded no outcomes to learn from. Project prior kept.";case"disabled":return"Learning: disabled (`epic.learning.enabled: false`). Project prior kept unchanged.";default:return`Learning: ⚠️ ${result.detail}. Project prior kept unchanged.`}}var EPIC_PRIOR_LEARNING_RELATIVE_PATH,EPIC_PRIOR_LEARNING_DISPLAY_PATH=".swarm/epic-prior/learning.json",EPIC_POSTERIOR_RELATIVE_PATH,LEGACY_CALIBRATION_RELATIVE_PATH,LEGACY_DIVERGENCE_RELATIVE_PATH,EPIC_PRIOR_MERGED_EPICS_KEEP=50,MAX_LEARNING_FILE_BYTES=4194304,MAX_LEGACY_DIVERGENCE_BYTES=16777216,MAX_LEGACY_DIVERGENCE_RECORDS=1e4,MAX_LEGACY_HOT_MODULES=2000,EPIC_LEGACY_HOT_MODULE_ALPHA=2,MAX_WARNED_KEYS=64,fileEntrySchema,edgeEntrySchema,statsSchema,importedFromSchema,priorSchema,posteriorSchema,warnedKeys;var init_learning_store=__esm(()=>{init_zod();init_atomic_write();init_logger();init_learning();EPIC_PRIOR_LEARNING_RELATIVE_PATH=path55.join(".swarm","epic-prior","learning.json"),EPIC_POSTERIOR_RELATIVE_PATH=path55.join(".swarm","epic","posterior.json"),LEGACY_CALIBRATION_RELATIVE_PATH=path55.join(".swarm","epic","calibration.json"),LEGACY_DIVERGENCE_RELATIVE_PATH=path55.join(".swarm","epic","divergence.jsonl"),fileEntrySchema=exports_external.object({path:exports_external.string().min(1),alpha:exports_external.number().finite().min(0),beta:exports_external.number().finite().min(0)}).strict(),edgeEntrySchema=exports_external.object({from:exports_external.string().min(1),to:exports_external.string().min(1),weight:exports_external.number().finite().min(0)}).strict(),statsSchema=exports_external.object({files:exports_external.array(fileEntrySchema),edges:exports_external.array(edgeEntrySchema)}).strict(),importedFromSchema=exports_external.object({at:exports_external.string(),source:exports_external.enum(["epic-v1-import","reset"]),calibrationHotModules:exports_external.number().int().min(0),divergenceRecords:exports_external.number().int().min(0)}).strict(),priorSchema=statsSchema.extend({schema:exports_external.literal("epic-learning-v1"),updatedAt:exports_external.string(),importedFrom:importedFromSchema.nullable(),mergedEpics:exports_external.array(exports_external.string())}).strict(),posteriorSchema=exports_external.object({schema:exports_external.literal("epic-posterior-v1"),epicKey:exports_external.string().min(1),token:exports_external.string().min(1),priorDigest:exports_external.string().nullable(),createdAt:exports_external.string(),lastAppliedWaveSeq:exports_external.number().int().min(0),base:statsSchema.extend({updatedAt:exports_external.string()}).strict(),increments:statsSchema}).strict();warnedKeys=new Set});function isFullSha(value){return typeof value==="string"&&SHA_RE2.test(value)}function taskRefComponent(taskId){if(SAFE_COMPONENT_RE.test(taskId)&&!taskId.endsWith(".lock"))return taskId;return`_x${Buffer.from(taskId,"utf8").toString("hex")}`}function epicRefPrefix(epicKey){return assertSafeGitRefArg(`${EPIC_REFS_ROOT}/${epicKey}`,"epic ref prefix")}function epicBaseRef(epicKey){return`${epicRefPrefix(epicKey)}/base`}function epicWaveRef(epicKey,seq){return`${epicRefPrefix(epicKey)}/waves/${Math.trunc(seq)}`}function epicTaskRef(epicKey,taskId){return assertSafeGitRefArg(`${epicRefPrefix(epicKey)}/tasks/${taskRefComponent(taskId)}`,"epic task ref")}function readEpicRefs(directory,epicKey){let output=_internals54.gitExec(["for-each-ref",`--count=${MAX_EPIC_REFS}`,"--format=%(objectname) %(refname)",epicRefPrefix(epicKey)],directory),refs=new Map;for(let line of output.split(/\r?\n/)){let space=line.indexOf(" ");if(space<=0)continue;let sha=line.slice(0,space),name=line.slice(space+1).trim();if(isFullSha(sha)&&name.length>0)refs.set(name,sha)}return refs}function readOneRef(directory,ref){let sha=_internals54.gitExec(["for-each-ref","--count=1","--format=%(objectname)",ref],directory).trim().split(/\r?\n/)[0]??"";return isFullSha(sha)?sha:null}function writeEpicRef(directory,ref,sha,existing){if(!isFullSha(sha))throw Error(`not a full commit id: ${sha}`);if(assertSafeGitRefArg(ref,"epic ref write"),existing===sha)return"unchanged";try{return _internals54.gitExecOnce(["update-ref",ref,sha,existing??""],directory),existing===null?"created":"updated"}catch(error49){if(readOneRef(directory,ref)===sha)return existing===null?"created":"updated";throw error49}}function desiredEpicRefs(record2){let desired=new Map;if(!record2.git.isRepo)return desired;if(isFullSha(record2.git.baseCommit))desired.set(epicBaseRef(record2.epicKey),record2.git.baseCommit);for(let wave of record2.waves)if(wave.status==="closed"&&isFullSha(wave.closeHead))desired.set(epicWaveRef(record2.epicKey,wave.seq),wave.closeHead);for(let outcome of Object.values(record2.tasks)){let sha=outcome.marker?.sha;if(outcome.resolution==="completed"&&isFullSha(sha))desired.set(epicTaskRef(record2.epicKey,outcome.taskId),sha)}return desired}function syncEpicRefs(directory,record2){let existing=readEpicRefs(directory,record2.epicKey);for(let[ref,sha]of desiredEpicRefs(record2))writeEpicRef(directory,ref,sha,existing.get(ref)??null),existing.set(ref,sha);return existing}function isCommitAncestorOfHead(directory,sha){if(!isFullSha(sha))return!1;return _internals54.gitProbeExitCode(["merge-base","--is-ancestor",sha,"HEAD"],directory)===0}function deleteEpicRefs(directory,epicKey){let deleted=[],failed=[],refs;try{refs=readEpicRefs(directory,epicKey)}catch(error49){return{deleted,failed:[`${epicRefPrefix(epicKey)}/* (${error49 instanceof Error?error49.message:String(error49)})`]}}for(let[ref,sha]of refs)try{_internals54.gitExecOnce(["update-ref","-d",ref,sha],directory),deleted.push(ref)}catch{failed.push(ref)}return{deleted,failed}}function findTaskCommits(directory,range,planKey,taskIds){let wanted=new Map;for(let id of taskIds)wanted.set(scrubTaskIdForGitSubject(id),id);let found=new Map;if(wanted.size===0)return found;let output=_internals54.gitExec(["log","-z","--extended-regexp","--grep=^swarm\\(task [^)]+\\):",`--max-count=${MARKER_LOOKUP_MAX_COMMITS}`,MARKER_LOG_FORMAT,range,"--"],directory);for(let marker of parseTaskMarkerLog(output)){if(marker.planKey!==planKey)continue;let taskId=wanted.get(marker.taskId);if(taskId!==void 0&&!found.has(taskId))found.set(taskId,marker.sha)}return found}function epicCommitRange(record2){return isFullSha(record2.git.baseCommit)?`${record2.git.baseCommit}..HEAD`:"HEAD"}function planEpicTaskRefRepair(directory,record2,unrecorded){let repairs=[],recorded=new Map,adoptedUnrecorded=new Map,refs=readEpicRefs(directory,record2.epicKey),broken=[],reachable=(sha)=>isFullSha(sha)&&isCommitAncestorOfHead(directory,sha);for(let outcome of Object.values(record2.tasks)){if(outcome.resolution!=="completed")continue;let sha=outcome.marker?.sha??null;if(reachable(sha))repairs.push({taskId:outcome.taskId,status:"ok",sha,detail:"reachable from HEAD"});else broken.push(outcome.taskId)}let brokenUnrecorded=[];for(let taskId of unrecorded){if(record2.tasks[taskId])continue;let sha=refs.get(epicTaskRef(record2.epicKey,taskId));if(reachable(sha))repairs.push({taskId,status:"ok",sha,detail:"reachable from HEAD"});else brokenUnrecorded.push(taskId)}if(broken.length===0&&brokenUnrecorded.length===0)return{repairs,recorded,unrecorded:adoptedUnrecorded};let range=epicCommitRange(record2),markers=findTaskCommits(directory,range,record2.planKey,[...broken,...brokenUnrecorded]),needsAttention=(taskId)=>{repairs.push({taskId,status:"needs-attention",sha:null,detail:"no commit reachable from HEAD carries its work — commit it on the epic branch with the subject `swarm(task <id>): …` and the plan trailer, then rerun --repair-refs"})};for(let taskId of broken){let sha=markers.get(taskId)??null,how="its `swarm(task …)` commit for this plan",declared=(record2.tasks[taskId]?.declared??[]).filter((file2)=>file2.length>0&&!file2.startsWith(":"));if(!sha&&declared.length>0){let out=_internals54.gitExec(["log","--max-count=1","--format=%H",range,"--",...declared.slice(0,200).map((file2)=>`:(literal)${file2}`)],directory).trim();if(isFullSha(out))sha=out,how="the newest commit touching its declared files"}if(!sha){needsAttention(taskId);continue}recorded.set(taskId,sha),repairs.push({taskId,status:"repaired",sha,detail:`re-pointed to ${sha.slice(0,12)} (${how})`})}for(let taskId of brokenUnrecorded){let sha=markers.get(taskId);if(!sha){needsAttention(taskId);continue}adoptedUnrecorded.set(taskId,sha),repairs.push({taskId,status:"repaired",sha,detail:`adopted ${sha.slice(0,12)} (its \`swarm(task …)\` commit for this plan; completed outside a wave)`})}return{repairs,recorded,unrecorded:adoptedUnrecorded}}var EPIC_REFS_ROOT="refs/swarm/epics",MARKER_LOOKUP_MAX_COMMITS=2000,MAX_EPIC_REFS=20000,SHA_RE2,SAFE_COMPONENT_RE,_internals54;var init_markers=__esm(()=>{init_branch();init_safe_ref();init_git_once();init_plan_key();SHA_RE2=/^[0-9a-f]{40,64}$/,SAFE_COMPONENT_RE=/^[A-Za-z0-9][A-Za-z0-9_-]*(\.[A-Za-z0-9_-]+)*$/,_internals54={gitExec:(args2,cwd)=>_internals45.gitExec(args2,cwd),gitExecOnce,gitProbeExitCode}});function errorText4(error49){return error49 instanceof Error?error49.message:String(error49)}function readHead(directory){try{let head=_internals55.gitExec(["rev-parse","HEAD"],directory).trim();return SHA_RE3.test(head)?head:null}catch{return null}}function isSwarmPath(file2){return file2===".swarm"||file2.startsWith(".swarm/")}function changedFilesSinceBase(directory,baseHead){if(!baseHead||!SHA_RE3.test(baseHead))return null;try{let files=new Set,committed=_internals55.gitExec(["diff","--name-only","-z",baseHead,"HEAD"],directory);for(let file2 of committed.split("\x00"))if(file2.length>0)files.add(file2.replace(/\\/g,"/"));let records=_internals55.gitExec(["status","--porcelain=v1","-z","--untracked-files=all"],directory).split("\x00");for(let i=0;i<records.length;i+=1){let record2=records[i];if(record2.length<4)continue;let code=record2.slice(0,2);if(files.add(record2.slice(3).replace(/\\/g,"/")),code.includes("R")||code.includes("C"))i+=1}return[...files].filter((file2)=>!isSwarmPath(file2)).sort().slice(0,MAX_FALLBACK_FILES)}catch(error49){return warn(`[epic/wave-close] git fallback for divergence unavailable: ${errorText4(error49)}`),null}}function collectTaskAttribution(directory,callerSessionID,taskId){let collected=[],add=(session)=>{if(!session)return;try{collected.push(..._internals55.getModifiedFilesForTask(session,taskId))}catch{}},caller=callerSessionID?_internals55.getAgentSession(callerSessionID):void 0;add(caller);let projectKey=null;try{projectKey=_internals55.hydrationProjectKey(directory)}catch{projectKey=null}if(projectKey!==null)try{for(let[,session]of _internals55.listAgentSessions()){if(session===caller)continue;if(!session||!(session.modifiedFilesByTask instanceof Map))continue;if(session.owningProjectKey!==projectKey)continue;add(session)}}catch{}let canonical=new Set;for(let file2 of collected){let normalized=canonicalAttributionPath(file2,directory);if(normalized!==null)canonical.add(normalized)}return[...canonical].sort()}function lastTransitionAt(events,taskId,resolution){let at=null;for(let event of events){if(event.task_id!==taskId)continue;if(resolution==="removed"&&event.event_type==="task_removed"||event.event_type==="task_status_changed"&&event.to_status===resolution)at=event.timestamp}return at}function countReopens(events,taskId,sinceIso){let since=Date.parse(sinceIso);return events.filter((event)=>event.task_id===taskId&&event.event_type==="task_status_changed"&&event.from_status==="completed"&&event.to_status!=="completed"&&(!Number.isFinite(since)||Date.parse(event.timestamp)>=since)).length}async function readWorkflowCounts(directory,taskId){try{let workflow=(await _internals55.readTaskEvidence(directory,taskId))?.workflow;if(!workflow)return{generation:0,stageA:0,stageB:0};let history=Array.isArray(workflow.retryHistory)?workflow.retryHistory:[];return{generation:Number.isFinite(workflow.generation)?workflow.generation:0,stageA:history.filter((o)=>o==="stage_a_failed").length,stageB:history.filter((o)=>o==="stage_b_failed").length}}catch{return{generation:0,stageA:0,stageB:0}}}function resolutionOf(plan,taskId){for(let phase of plan.phases){let task=(phase.tasks??[]).find((t)=>t.id===taskId);if(!task)continue;if(task.status==="completed")return"completed";if(task.status==="closed")return"closed";return null}return"removed"}function markerFor(epic,taskId,resolution,closeHead,taskCommits){if(resolution!=="completed")return null;if(!epic.git.isRepo)return{ref:null,sha:null,provenance:"no-git"};let landed=taskCommits.get(taskId),sha=landed??closeHead;return{ref:isFullSha(sha)?epicTaskRef(epic.epicKey,taskId):null,sha,provenance:landed?"landing-commit":"wave-close-head"}}async function computeWaveClose(args2){let{directory,epic,wave,plan,sessionID,nowIso:nowIso2}=args2,isRepo=epic.git.isRepo,closeHead=isRepo?readHead(directory):null,events=[];try{events=await _internals55.readLedgerEvents(directory)}catch(error49){warn(`[epic/wave-close] plan ledger unreadable; outcome times fall back to now: ${errorText4(error49)}`)}let changed=isRepo?changedFilesSinceBase(directory,wave.baseHead):null,completedIds=wave.taskIds.filter((taskId)=>resolutionOf(plan,taskId)==="completed"),taskCommits=new Map;if(isRepo&&closeHead&&completedIds.length>0)try{taskCommits=_internals55.findTaskCommits(directory,isFullSha(wave.baseHead)?`${wave.baseHead}..HEAD`:epicCommitRange(epic),epic.planKey,completedIds)}catch(error49){warn(`[epic/wave-close] task commit lookup failed; markers fall back to the close HEAD: ${errorText4(error49)}`)}let outcomes=[],attributedAll=new Set;for(let taskId of wave.taskIds){let resolution=resolutionOf(plan,taskId)??"removed",declared=[...wave.files[taskId]??[]],counts=resolution==="removed"?{generation:0,stageA:0,stageB:0}:await readWorkflowCounts(directory,taskId),undeclared=[],attribution=isRepo?"unavailable":"no-git";if(resolution==="completed"){let attributed=collectTaskAttribution(directory,sessionID,taskId);for(let file2 of attributed)attributedAll.add(file2);let actual=null;if(attributed.length>0)actual=attributed,attribution="session";else if(changed!==null&&wave.taskIds.length===1)actual=changed,attribution="git-single-task";if(actual!==null)undeclared=undeclaredFiles(declared,actual)}let snapshot=wave.mergeFailures?.[taskId];outcomes.push({taskId,phase:wave.phase,waveSeq:wave.seq,resolution,resolvedAt:lastTransitionAt(events,taskId,resolution)??nowIso2,generation:counts.generation,stageAFailures:counts.stageA,stageBFailures:counts.stageB,mergeFailure:snapshot?{outcome:snapshot.outcome,stage:snapshot.stage}:null,declared,undeclared,attribution,reopened:countReopens(events,taskId,epic.startedAt),marker:markerFor(epic,taskId,resolution,closeHead,taskCommits)})}let waveUndeclared=[];if(changed!==null){let declaredAll=Object.values(wave.files).flat();waveUndeclared=undeclaredFiles(declaredAll,changed).filter((file2)=>!attributedAll.has(file2))}return{closeHead,outcomes,waveUndeclared}}function applyWaveClose(record2,seq,computation,nowIso2){let wave=record2.waves.find((w)=>w.seq===seq);if(!wave||wave.status!=="issued"||record2.activeWaveSeq!==seq)return record2;let tasks={...record2.tasks};for(let outcome of computation.outcomes){let before=Object.hasOwn(record2.tasks,outcome.taskId)?record2.tasks[outcome.taskId]:void 0;tasks[outcome.taskId]=before&&before.waveSeq!==outcome.waveSeq?{...outcome,previous:{waveSeq:before.waveSeq,generation:before.generation,stageBFailures:before.stageBFailures,reopened:before.reopened}}:outcome}return{...record2,activeWaveSeq:null,tasks,waves:record2.waves.map((w)=>w.seq===seq?{...w,status:"closed",closedAt:nowIso2,closeHead:computation.closeHead,undeclared:computation.waveUndeclared}:w)}}function recordEpicWaveLearning(args2){let settings=resolveEpicLearningSettings(args2.config);if(!settings.enabled)return[];try{return _internals55.applyClosedWavesToPosterior(args2.directory,args2.record,settings).appliedWaves}catch(error49){return criticalWarn(`[epic/wave-close] learning update failed (the wave flow continues; the next wave close catches it up): ${errorText4(error49)}`),[]}}function releaseWaveAttribution(directory,sessionID,taskIds){let sessions=new Set,caller=sessionID?_internals55.getAgentSession(sessionID):void 0;if(caller)sessions.add(caller);try{let projectKey=_internals55.hydrationProjectKey(directory);for(let[,session]of _internals55.listAgentSessions())if(session&&session.owningProjectKey===projectKey)sessions.add(session)}catch{}for(let session of sessions)for(let taskId of taskIds)try{_internals55.resetModifiedFilesForTask(session,taskId,{remove:!0})}catch{}}var MAX_FALLBACK_FILES=2000,SHA_RE3,_internals55;var init_wave_close=__esm(()=>{init_gate_evidence();init_branch();init_ledger();init_hydration_ownership();init_state();init_logger();init_path();init_learning();init_learning_store();init_markers();SHA_RE3=/^[0-9a-f]{7,64}$/,_internals55={gitExec:(args2,cwd)=>_internals45.gitExec(args2,cwd),readTaskEvidence,readLedgerEvents,listAgentSessions:()=>swarmState.agentSessions.entries(),getAgentSession,getModifiedFilesForTask,resetModifiedFilesForTask,hydrationProjectKey,applyClosedWavesToPosterior,findTaskCommits}});import*as fs32 from"node:fs";import*as path56 from"node:path";function errorText5(error49){return error49 instanceof Error?error49.message:String(error49)}function isSwarmStatePath(file2){let normalized=file2.replace(/\\/g,"/");return normalized===".swarm"||normalized.startsWith(".swarm/")||normalized.includes("/.swarm/")||normalized.endsWith("/.swarm")}function caseKey(file2){return process.platform==="win32"?file2.toLowerCase():file2}function listDirtyEntries(directory){let output=_internals56.gitExec(["status","--porcelain=v1","-z","--untracked-files=all"],directory),entries=[],records=output.split("\x00");for(let i=0;i<records.length;i+=1){let record2=records[i];if(record2.length<4)continue;let code=record2.slice(0,2),file2=record2.slice(3).replace(/\\/g,"/"),origin;if(code.includes("R")||code.includes("C"))i+=1,origin=records[i]?.replace(/\\/g,"/");if(isSwarmStatePath(file2))continue;if(entries.push({path:file2,untracked:code==="??",needsAdd:code[1]!==" ",...origin?{origin}:{}}),entries.length>=MAX_DIRTY_ENTRIES)break}return entries}function coveredBy(file2,declared){let key=caseKey(file2);return declared.some((entry)=>{let d=caseKey(entry.replace(/\\/g,"/").replace(/\/+$/,""));return d.length>0&&(key===d||key.startsWith(`${d}/`))})}function literal2(file2){return`:(literal)${file2}`}function readIndexEntries(directory,files){let entries=new Map;for(let i=0;i<files.length;i+=PATHSPEC_CHUNK){let out=_internals56.gitExec(["ls-files","-s","-z","--",...files.slice(i,i+PATHSPEC_CHUNK).map(literal2)],directory);for(let record2 of out.split("\x00")){let tab=record2.indexOf("\t");if(tab<0)continue;let[mode,sha,stage]=record2.slice(0,tab).split(" ");if(stage!=="0")continue;entries.set(record2.slice(tab+1),`${mode} ${sha}`)}}return entries}function restoreIndexEntries(directory,files,before){for(let i=0;i<files.length;i+=PATHSPEC_CHUNK)_internals56.gitExecOnce(["reset","-q","--",...files.slice(i,i+PATHSPEC_CHUNK).map(literal2)],directory);let after=readIndexEntries(directory,files);for(let file2 of files){let wanted=before.get(file2),actual=after.get(file2);if(wanted===actual)continue;if(wanted){let[mode,sha]=wanted.split(" ");_internals56.gitExecOnce(["update-index","--cacheinfo",`${mode},${sha},${file2}`],directory)}else _internals56.gitExecOnce(["update-index","--force-remove","--",file2],directory)}}function commitPaths(directory,message,files,toAdd){let base=["-c","commit.gpgsign=false","commit","--only","--no-verify","-m",message],pathspecs=files.map(literal2),inlineBytes=pathspecs.reduce((sum,p)=>sum+Buffer.byteLength(p,"utf-8")+1,0),before=readIndexEntries(directory,files);try{for(let i=0;i<toAdd.length;i+=PATHSPEC_CHUNK)_internals56.gitExecOnce(["add","-A","--",...toAdd.slice(i,i+PATHSPEC_CHUNK).map(literal2)],directory);if(inlineBytes<=COMMIT_ARGV_PATHSPEC_BUDGET_BYTES)_internals56.gitExecOnce([...base,"--",...pathspecs],directory);else{let gitPath=_internals56.gitExec(["rev-parse","--git-path",`swarm-epic-residue-${process.pid}-${_internals56.now()}`],directory).trim(),specFile=path56.resolve(directory,gitPath);try{fs32.writeFileSync(specFile,`${pathspecs.join("\x00")}\x00`,"utf-8"),_internals56.gitExecOnce([...base,`--pathspec-from-file=${specFile}`,"--pathspec-file-nul"],directory)}finally{try{fs32.rmSync(specFile,{force:!0})}catch{}}}}catch(error49){try{restoreIndexEntries(directory,files,before)}catch(restoreError){criticalWarn(`[epic] could not restore the index after a failed residue commit (${errorText5(restoreError)}); check \`git status\` for: ${files.slice(0,10).join(", ")}`)}throw error49}try{let head=_internals56.gitExec(["rev-parse","HEAD"],directory).trim();return/^[0-9a-f]{40,64}$/.test(head)?head:null}catch{return null}}function commitTaskResidue(args2){let wanted=new Set;for(let candidate of args2.candidates)if(typeof candidate==="string"&&candidate.length>0&&!candidate.startsWith(":")&&!isSwarmStatePath(candidate))wanted.add(caseKey(candidate.replace(/\\/g,"/")));let files=new Set,toAdd=new Set,scopes=(args2.scopes??[]).filter((entry)=>entry.length>0&&!entry.startsWith(":")),globLike=scopes.filter((entry)=>/[*?]/.test(entry));if(globLike.length>0)warn(`[epic] task ${args2.taskId}: declared scope entries are literal files or directories, never globs; ${globLike.slice(0,5).join(", ")} only match a path spelled exactly like that.`);for(let entry of args2.dirty){if(!wanted.has(caseKey(entry.path))&&!(scopes.length>0&&coveredBy(entry.path,scopes)))continue;if(files.add(entry.path),entry.needsAdd!==!1)toAdd.add(entry.path);if(entry.origin&&!isSwarmStatePath(entry.origin))files.add(entry.origin)}if(files.size===0)return{status:"nothing"};let list2=[...files].sort();try{return{status:"committed",sha:commitPaths(args2.directory,formatEpicTaskCommitMessage(args2.taskId,args2.epic.planKey,args2.label),list2,[...toAdd].sort()),files:list2}}catch(error49){return{status:"failed",error:errorText5(error49),files:list2}}}function inFlightWriterFiles(directory,exclude){let files=new Set;for(let[id,session]of _internals56.listAgentSessions()){if(exclude.has(id)||!session?.delegationActive)continue;if(!(session.modifiedFilesByTask instanceof Map))continue;for(let entries of session.modifiedFilesByTask.values())for(let file2 of entries){let canonical=canonicalAttributionPath(file2,directory);if(canonical!==null)files.add(caseKey(canonical))}}return files}function childSessionFiles(directory,ids){let files=[];for(let id of new Set(ids)){if(typeof id!=="string"||id.length===0)continue;let session=_internals56.getAgentSession(id);if(!session||!(session.modifiedFilesByTask instanceof Map))continue;for(let entries of session.modifiedFilesByTask.values())for(let file2 of entries){let canonical=canonicalAttributionPath(file2,directory);if(canonical!==null)files.push(canonical)}}return files}function declaredScopeOf(epic,taskId){return[...epic.waves.find((w)=>w.seq===epic.activeWaveSeq&&w.status==="issued")?.files[taskId]??[]]}async function commitEpicResidueAfterDelegation(request){try{if(!_internals56.epicSentinelExists(request.directory))return;let agent=stripKnownSwarmPrefix(request.agent);if(agent==="coder"||agent==="architect")return;let epic=_internals56.getOpenEpic(request.directory);if(!epic||!epic.git.isRepo)return;let taskIds=(await request.resolveTaskIds()).filter((id)=>_internals56.readPlanTaskRef(request.directory,id)!==null);if(taskIds.length===0)return;let branch=_internals56.checkEpicBranch(request.directory,epic);if(!branch.ok){criticalWarn(`[epic] ${agent} residue for task ${taskIds.join(", ")} NOT committed: ${branch.message}`);return}let childIds=await request.childSessionIds(),childFiles=childSessionFiles(request.directory,childIds),exclude=new Set([...childIds,request.sessionID].filter((id)=>typeof id==="string"&&id.length>0)),inFlight=inFlightWriterFiles(request.directory,exclude);await _internals56.serializeWithMergeBacks(()=>commitResidueForTasks(request,epic,agent,taskIds,childFiles,inFlight))}catch(error49){criticalWarn(`[epic] residue commit after a ${request.agent} delegation failed (non-fatal; epic_next_wave retries): ${errorText5(error49)}`)}}function commitResidueForTasks(request,epic,agent,taskIds,childFiles,inFlight=new Set){try{let dirty=listDirtyEntries(request.directory).filter((entry)=>!inFlight.has(caseKey(entry.path)));if(dirty.length===0)return;let remaining=dirty,commitStep=(taskId,label,candidates,scopes)=>{let result=commitTaskResidue({directory:request.directory,epic,taskId,label,candidates,scopes,dirty:remaining});if(result.status==="failed")return criticalWarn(`[epic] ${label} for task ${taskId} could not be committed (${result.error}); epic_next_wave retries before the next wave. Files: ${result.files.slice(0,10).join(", ")}`),!1;if(result.status==="committed"){let done=new Set(result.files.map(caseKey));remaining=remaining.filter((entry)=>!done.has(caseKey(entry.path)))}return!0};for(let[index,taskId]of taskIds.entries()){if(index===0&&childFiles.length>0&&!commitStep(taskId,`${agent} residue`,childFiles,[]))return;if(!commitStep(taskId,"residue",_internals56.collectTaskAttribution(request.directory,request.sessionID,taskId),declaredScopeOf(epic,taskId)))return}}catch(error49){criticalWarn(`[epic] residue commit after a ${request.agent} delegation failed (non-fatal; epic_next_wave retries): ${errorText5(error49)}`)}}function classifyDirtyBaseline(dirty){let unattributedTracked=[],unattributedUntracked=[];for(let entry of dirty)(entry.untracked?unattributedUntracked:unattributedTracked).push(entry.path);return{unattributedTracked,unattributedUntracked}}var COMMIT_ARGV_PATHSPEC_BUDGET_BYTES=24576,PATHSPEC_CHUNK=200,MAX_DIRTY_ENTRIES=5000,_internals56;var init_residue_commit=__esm(()=>{init_schema();init_branch();init_worktree_isolation();init_state();init_logger();init_path();init_epic_branch();init_git_once();init_lifecycle();init_plan_key();init_wave_close();_internals56={epicSentinelExists,getOpenEpic,readPlanTaskRef,checkEpicBranch,collectTaskAttribution,getAgentSession,listAgentSessions:()=>swarmState.agentSessions.entries(),gitExec:(args2,cwd)=>_internals45.gitExec(args2,cwd),gitExecOnce,serializeWithMergeBacks:(task)=>runSerializedWithMergeBacks(task),now:()=>Date.now()}});function normalizeToolName(toolName){if(!toolName)return;return toolName.replace(NAMESPACE_PREFIX_PATTERN,"")}function normalizeToolNameLowerCase(toolName){return toolName.replace(NAMESPACE_PREFIX_PATTERN,"").toLowerCase()}function isTaskToolId(toolName){if(!toolName)return!1;if(toolName.includes("."))return/^tool\.[^.:]+\.task$/i.test(toolName);return normalizeToolNameLowerCase(toolName)==="task"}var NAMESPACE_PREFIX_PATTERN;var init_normalize_tool_name=__esm(()=>{NAMESPACE_PREFIX_PATTERN=/^[^:]+[:.]/});function declaresWindowsWrapper(command){return CMD_WRAPPER_DECLARATION.test(command)||PS_WRAPPER_DECLARATION.test(command)}function declaresWindowsWrapperLoose(command){return declaresWindowsWrapper(command)||PS_WRAPPER_LOOSE.test(command)}var CMD_SWITCH,CMD_WRAPPER_DECLARATION,PS_WRAPPER_DECLARATION,PS_WRAPPER_LOOSE,CMD_BUILTIN_PREFIX,CMD_STRIP_PREFIX,PS_STRIP_PREFIX;var init_shell_executor_context=__esm(()=>{CMD_SWITCH=String.raw`\/[a-z](?::(?:on|off))?`,CMD_WRAPPER_DECLARATION=new RegExp(String.raw`(?:^|[;|&\n])\s*cmd(?:\.exe)?\s+(?:${CMD_SWITCH}\s+)*\/c(?:\s|$)`,"i"),PS_WRAPPER_DECLARATION=/(?:^|[;|&\n])\s*(?:powershell|pwsh)(?:\.exe)?\s+(?:-[A-Za-z]+\s+)*-command(?:\s|$)/i,PS_WRAPPER_LOOSE=/(?:^|\|)\s*(?:powershell|pwsh)(?:\.exe)?\s+-/i;CMD_BUILTIN_PREFIX=new RegExp(String.raw`(?:(?:^|\s)(?:if\s+(?:not\s+)?exist\s+(?:"[^"]*"|\S+)\s+)|(?:^|[;|&\n])\s*cmd(?:\.exe)?\s+(?:${CMD_SWITCH}\s+)*\/c\s+|(?:^|\s)(?:call|start)\s+)*`,"i"),CMD_STRIP_PREFIX=new RegExp(String.raw`^cmd(?:\.exe)?\s+(?:${CMD_SWITCH}\s+)*\/[ck]\s+`,"i"),PS_STRIP_PREFIX=/^(?:powershell|pwsh)(?:\.exe)?\s+(?:-[A-Za-z]+\s+)*-(?:command|c)\s+/i});import*as fsSync6 from"node:fs";import*as path57 from"node:path";function dcNormalizeCommand(cmd){let s=cmd.normalize("NFKC");return s=s.replace(/`(.)/g,"$1"),s=s.replace(/\^([a-zA-Z0-9 ])/g,"$1"),s=s.replace(/""/g,""),s=s.replace(/''/g,""),s}function dcStripOneWrapper(cmd){let t=cmd.trim(),cmdExeMatch=new RegExp(`${CMD_STRIP_PREFIX.source}"?(.*?)"?\\s*$`,"is").exec(t);if(cmdExeMatch)return cmdExeMatch[1].trim();let psCommandMatch=new RegExp(`${PS_STRIP_PREFIX.source}(.+)$`,"is").exec(t);if(psCommandMatch)return psCommandMatch[1].replace(/^["']|["']$/g,"").trim();let psEncMatch=/^(?:powershell|pwsh)(?:\.exe)?\s+(?:-(?:EncodedCommand|encodedcommand|enc|e)\s+)([A-Za-z0-9+/=]+)\s*$/.exec(t);if(psEncMatch)try{return Buffer.from(psEncMatch[1],"base64").toString("utf16le").trim()}catch{return t}let shellMatch=/^(?:bash|sh|zsh|dash|fish)(?:\.exe)?\s+-c\s+"?(.*?)"?\s*$/is.exec(t);if(shellMatch)return shellMatch[1].trim();let evalMatch=/^eval\s+(.+)$/is.exec(t);if(evalMatch)return evalMatch[1].replace(/^["']|["']$/g,"").trim();let prefixMatch=/^(?:sudo|time|nohup)\s+(.+)$/is.exec(t)??/^env(?:\s+[A-Za-z_][A-Za-z0-9_]*=[^\s]*)*\s+(.+)$/is.exec(t)??/^nice\s+(?:-n\s+\d+\s+)?(.+)$/is.exec(t);if(prefixMatch)return prefixMatch[1].trim();let wslMatch=/^wsl(?:\.exe)?\s+(?:-e|--)\s+(.+)$/is.exec(t);if(wslMatch)return wslMatch[1].trim();let scriptBlockMatch=/^&\s*\{(.+)\}$/s.exec(t);if(scriptBlockMatch)return scriptBlockMatch[1].trim();let iexMatch=/^(?:Invoke-Expression|iex)\s+(.+)$/is.exec(t);if(iexMatch)return iexMatch[1].replace(/^["'`]|["'`]$/g,"").trim();let invokeCommandMatch=/^Invoke-Command\s+.*-ScriptBlock\s*\{(.+)\}$/is.exec(t);if(invokeCommandMatch)return invokeCommandMatch[1].trim();let callMatch=/^call\s+(.+)$/is.exec(t);if(callMatch)return callMatch[1].trim();return null}function dcUnwrapWrappers(cmd){let current=cmd.trim();for(let depth=0;depth<DC_MAX_UNWRAP_DEPTH;depth++){let inner=dcStripOneWrapper(current);if(inner===null||inner===current)break;current=inner.trim()}return current}function dcSplitSegments(cmd){let segments=[],current="",inDoubleQuote=!1,inSingleQuote=!1;for(let i=0;i<cmd.length;i++){let ch=cmd[i],next=cmd[i+1];if(ch==='"'&&!inSingleQuote){inDoubleQuote=!inDoubleQuote,current+=ch;continue}if(ch==="'"&&!inDoubleQuote){inSingleQuote=!inSingleQuote,current+=ch;continue}if(!inDoubleQuote&&!inSingleQuote){if(ch==="&"&&next==="&"||ch==="|"&&next==="|"){segments.push(current.trim()),current="",i++;continue}if(ch==="|"||ch===";"||ch===`
|
|
706
|
+
`).filter((line)=>line.trim().length>0).slice(truncated?1:0).slice(-MAX_LEGACY_DIVERGENCE_RECORDS),records=[];for(let line of tail)try{let parsed=JSON.parse(line);if(parsed&&typeof parsed==="object")records.push(parsed)}catch{}let last=new Map;records.forEach((record2,index)=>{if(typeof record2.planId==="string"&&typeof record2.taskId==="string")last.set(`${record2.planId}\x00${record2.taskId}`,index)});let strings=(value)=>Array.isArray(value)?value.filter((entry)=>typeof entry==="string"):[];return records.filter((record2,index)=>typeof record2.planId!=="string"||typeof record2.taskId!=="string"||last.get(`${record2.planId}\x00${record2.taskId}`)===index).map((record2)=>({declared:strings(record2.declaredScope),undeclared:strings(record2.undeclared)}))}function importLegacyEpicCalibrationOnce(directory,nowMs){try{let read=readEpicPrior(directory);if(read.status==="unreadable")return{status:"prior-unreadable"};if(read.status==="ok"&&read.prior.importedFrom!==null)return{status:"already-imported"};let hotModules=null;try{hotModules=readLegacyHotModules(directory)}catch(error49){warn(`[epic/learning] Epic v1 calibration.json unreadable; not imported: ${errorText3(error49)}`)}let divergence=null;try{divergence=readLegacyDivergence(directory)}catch(error49){warn(`[epic/learning] Epic v1 divergence.jsonl unreadable; not imported: ${errorText3(error49)}`)}if(hotModules===null&&divergence===null)return{status:"nothing-to-import"};let increments=epicLearningFromOutcomes((divergence??[]).map((record2,index)=>({taskId:`legacy-${index}`,phase:0,waveSeq:0,resolution:"completed",resolvedAt:"",generation:0,stageAFailures:0,stageBFailures:0,mergeFailure:null,declared:record2.declared,undeclared:record2.undeclared,attribution:"session",reopened:0,marker:null})),{isDirectory:directoryProbe(directory)}),base=read.status==="ok"?read.prior.stats:emptyEpicLearning(),stats2=mergeEpicLearning(base,increments);for(let file2 of learnablePaths(hotModules??[])){let current=stats2.files.get(file2)??{alpha:0,beta:0};stats2.files.set(file2,{alpha:Math.max(current.alpha,EPIC_LEGACY_HOT_MODULE_ALPHA),beta:current.beta})}let nowIso2=new Date(nowMs).toISOString(),importedFrom={source:"epic-v1-import",at:nowIso2,calibrationHotModules:hotModules?.length??0,divergenceRecords:divergence?.length??0};return writeEpicPrior(directory,{updatedAt:nowIso2,importedFrom,mergedEpics:read.status==="ok"?read.prior.mergedEpics:[],stats:boundEpicLearning(stats2)}),{status:"imported",calibrationHotModules:importedFrom.calibrationHotModules,divergenceRecords:importedFrom.divergenceRecords}}catch(error49){return{status:"failed",detail:errorText3(error49)}}}function describeEpicPriorMerge(result){switch(result.status){case"merged":return`Learning: merged ${result.learnedFiles} file statistic(s) and ${result.learnedEdges} learned co-write(s) into the project prior (\`${EPIC_PRIOR_LEARNING_DISPLAY_PATH}\`)${result.hotFiles.length>0?`; hot files: ${result.hotFiles.slice(0,5).join(", ")}${result.hotFiles.length>5?", …":""}`:"; no hot files"}. Project prior kept (it survives /swarm close; \`/swarm epic prior reset\` clears it).`;case"already-merged":return"Learning: already merged into the project prior. Project prior kept.";case"nothing-to-learn":return"Learning: this epic recorded no outcomes to learn from. Project prior kept.";case"disabled":return"Learning: disabled (`epic.learning.enabled: false`). Project prior kept unchanged.";default:return`Learning: ⚠️ ${result.detail}. Project prior kept unchanged.`}}var EPIC_PRIOR_LEARNING_RELATIVE_PATH,EPIC_PRIOR_LEARNING_DISPLAY_PATH=".swarm/epic-prior/learning.json",EPIC_POSTERIOR_RELATIVE_PATH,LEGACY_CALIBRATION_RELATIVE_PATH,LEGACY_DIVERGENCE_RELATIVE_PATH,EPIC_PRIOR_MERGED_EPICS_KEEP=50,MAX_LEARNING_FILE_BYTES=4194304,MAX_LEGACY_DIVERGENCE_BYTES=16777216,MAX_LEGACY_DIVERGENCE_RECORDS=1e4,MAX_LEGACY_HOT_MODULES=2000,EPIC_LEGACY_HOT_MODULE_ALPHA=2,MAX_WARNED_KEYS=64,fileEntrySchema,edgeEntrySchema,statsSchema,importedFromSchema,priorSchema,posteriorSchema,warnedKeys;var init_learning_store=__esm(()=>{init_zod();init_atomic_write();init_logger();init_learning();EPIC_PRIOR_LEARNING_RELATIVE_PATH=path55.join(".swarm","epic-prior","learning.json"),EPIC_POSTERIOR_RELATIVE_PATH=path55.join(".swarm","epic","posterior.json"),LEGACY_CALIBRATION_RELATIVE_PATH=path55.join(".swarm","epic","calibration.json"),LEGACY_DIVERGENCE_RELATIVE_PATH=path55.join(".swarm","epic","divergence.jsonl"),fileEntrySchema=exports_external.object({path:exports_external.string().min(1),alpha:exports_external.number().finite().min(0),beta:exports_external.number().finite().min(0)}).strict(),edgeEntrySchema=exports_external.object({from:exports_external.string().min(1),to:exports_external.string().min(1),weight:exports_external.number().finite().min(0)}).strict(),statsSchema=exports_external.object({files:exports_external.array(fileEntrySchema),edges:exports_external.array(edgeEntrySchema)}).strict(),importedFromSchema=exports_external.object({at:exports_external.string(),source:exports_external.enum(["epic-v1-import","reset"]),calibrationHotModules:exports_external.number().int().min(0),divergenceRecords:exports_external.number().int().min(0)}).strict(),priorSchema=statsSchema.extend({schema:exports_external.literal("epic-learning-v1"),updatedAt:exports_external.string(),importedFrom:importedFromSchema.nullable(),mergedEpics:exports_external.array(exports_external.string())}).strict(),posteriorSchema=exports_external.object({schema:exports_external.literal("epic-posterior-v1"),epicKey:exports_external.string().min(1),token:exports_external.string().min(1),priorDigest:exports_external.string().nullable(),createdAt:exports_external.string(),lastAppliedWaveSeq:exports_external.number().int().min(0),base:statsSchema.extend({updatedAt:exports_external.string()}).strict(),increments:statsSchema}).strict();warnedKeys=new Set});function isFullSha(value){return typeof value==="string"&&SHA_RE2.test(value)}function taskRefComponent(taskId){if(SAFE_COMPONENT_RE.test(taskId)&&!taskId.endsWith(".lock"))return taskId;return`_x${Buffer.from(taskId,"utf8").toString("hex")}`}function epicRefPrefix(epicKey){return assertSafeGitRefArg(`${EPIC_REFS_ROOT}/${epicKey}`,"epic ref prefix")}function epicBaseRef(epicKey){return`${epicRefPrefix(epicKey)}/base`}function epicWaveRef(epicKey,seq){return`${epicRefPrefix(epicKey)}/waves/${Math.trunc(seq)}`}function epicTaskRef(epicKey,taskId){return assertSafeGitRefArg(`${epicRefPrefix(epicKey)}/tasks/${taskRefComponent(taskId)}`,"epic task ref")}function readEpicRefs(directory,epicKey){let output=_internals54.gitExec(["for-each-ref",`--count=${MAX_EPIC_REFS}`,"--format=%(objectname) %(refname)",epicRefPrefix(epicKey)],directory),refs=new Map;for(let line of output.split(/\r?\n/)){let space=line.indexOf(" ");if(space<=0)continue;let sha=line.slice(0,space),name=line.slice(space+1).trim();if(isFullSha(sha)&&name.length>0)refs.set(name,sha)}return refs}function readOneRef(directory,ref){let sha=_internals54.gitExec(["for-each-ref","--count=1","--format=%(objectname)",ref],directory).trim().split(/\r?\n/)[0]??"";return isFullSha(sha)?sha:null}function writeEpicRef(directory,ref,sha,existing){if(!isFullSha(sha))throw Error(`not a full commit id: ${sha}`);if(assertSafeGitRefArg(ref,"epic ref write"),existing===sha)return"unchanged";try{return _internals54.gitExecOnce(["update-ref",ref,sha,existing??""],directory),existing===null?"created":"updated"}catch(error49){if(readOneRef(directory,ref)===sha)return existing===null?"created":"updated";throw error49}}function desiredEpicRefs(record2){let desired=new Map;if(!record2.git.isRepo)return desired;if(isFullSha(record2.git.baseCommit))desired.set(epicBaseRef(record2.epicKey),record2.git.baseCommit);for(let wave of record2.waves)if(wave.status==="closed"&&isFullSha(wave.closeHead))desired.set(epicWaveRef(record2.epicKey,wave.seq),wave.closeHead);for(let outcome of Object.values(record2.tasks)){let sha=outcome.marker?.sha;if(outcome.resolution==="completed"&&isFullSha(sha))desired.set(epicTaskRef(record2.epicKey,outcome.taskId),sha)}return desired}function syncEpicRefs(directory,record2){let existing=readEpicRefs(directory,record2.epicKey);for(let[ref,sha]of desiredEpicRefs(record2))writeEpicRef(directory,ref,sha,existing.get(ref)??null),existing.set(ref,sha);return existing}function isCommitAncestorOfHead(directory,sha){if(!isFullSha(sha))return!1;return _internals54.gitProbeExitCode(["merge-base","--is-ancestor",sha,"HEAD"],directory)===0}function deleteEpicRefs(directory,epicKey){let deleted=[],failed=[],refs;try{refs=readEpicRefs(directory,epicKey)}catch(error49){return{deleted,failed:[`${epicRefPrefix(epicKey)}/* (${error49 instanceof Error?error49.message:String(error49)})`]}}for(let[ref,sha]of refs)try{_internals54.gitExecOnce(["update-ref","-d",ref,sha],directory),deleted.push(ref)}catch{failed.push(ref)}return{deleted,failed}}function findTaskCommits(directory,range,planKey,taskIds){let wanted=new Map;for(let id of taskIds)wanted.set(scrubTaskIdForGitSubject(id),id);let found=new Map;if(wanted.size===0)return found;let output=_internals54.gitExec(["log","-z","--extended-regexp","--grep=^swarm\\(task [^)]+\\):",`--max-count=${MARKER_LOOKUP_MAX_COMMITS}`,MARKER_LOG_FORMAT,range,"--"],directory);for(let marker of parseTaskMarkerLog(output)){if(marker.planKey!==planKey)continue;let taskId=wanted.get(marker.taskId);if(taskId!==void 0&&!found.has(taskId))found.set(taskId,marker.sha)}return found}function epicCommitRange(record2){return isFullSha(record2.git.baseCommit)?`${record2.git.baseCommit}..HEAD`:"HEAD"}function planEpicTaskRefRepair(directory,record2,unrecorded){let repairs=[],recorded=new Map,adoptedUnrecorded=new Map,refs=readEpicRefs(directory,record2.epicKey),broken=[],reachable=(sha)=>isFullSha(sha)&&isCommitAncestorOfHead(directory,sha);for(let outcome of Object.values(record2.tasks)){if(outcome.resolution!=="completed")continue;let sha=outcome.marker?.sha??null;if(reachable(sha))repairs.push({taskId:outcome.taskId,status:"ok",sha,detail:"reachable from HEAD"});else broken.push(outcome.taskId)}let brokenUnrecorded=[];for(let taskId of unrecorded){if(record2.tasks[taskId])continue;let sha=refs.get(epicTaskRef(record2.epicKey,taskId));if(reachable(sha))repairs.push({taskId,status:"ok",sha,detail:"reachable from HEAD"});else brokenUnrecorded.push(taskId)}if(broken.length===0&&brokenUnrecorded.length===0)return{repairs,recorded,unrecorded:adoptedUnrecorded};let range=epicCommitRange(record2),markers=findTaskCommits(directory,range,record2.planKey,[...broken,...brokenUnrecorded]),needsAttention=(taskId)=>{repairs.push({taskId,status:"needs-attention",sha:null,detail:"no commit reachable from HEAD carries its work — commit it on the epic branch with the subject `swarm(task <id>): …` and the plan trailer, then rerun --repair-refs"})};for(let taskId of broken){let sha=markers.get(taskId)??null,how="its `swarm(task …)` commit for this plan",declared=(record2.tasks[taskId]?.declared??[]).filter((file2)=>file2.length>0&&!file2.startsWith(":"));if(!sha&&declared.length>0){let out=_internals54.gitExec(["log","--max-count=1","--format=%H",range,"--",...declared.slice(0,200).map((file2)=>`:(literal)${file2}`)],directory).trim();if(isFullSha(out))sha=out,how="the newest commit touching its declared files"}if(!sha){needsAttention(taskId);continue}recorded.set(taskId,sha),repairs.push({taskId,status:"repaired",sha,detail:`re-pointed to ${sha.slice(0,12)} (${how})`})}for(let taskId of brokenUnrecorded){let sha=markers.get(taskId);if(!sha){needsAttention(taskId);continue}adoptedUnrecorded.set(taskId,sha),repairs.push({taskId,status:"repaired",sha,detail:`adopted ${sha.slice(0,12)} (its \`swarm(task …)\` commit for this plan; completed outside a wave)`})}return{repairs,recorded,unrecorded:adoptedUnrecorded}}var EPIC_REFS_ROOT="refs/swarm/epics",MARKER_LOOKUP_MAX_COMMITS=2000,MAX_EPIC_REFS=20000,SHA_RE2,SAFE_COMPONENT_RE,_internals54;var init_markers=__esm(()=>{init_branch();init_safe_ref();init_git_once();init_plan_key();SHA_RE2=/^[0-9a-f]{40,64}$/,SAFE_COMPONENT_RE=/^[A-Za-z0-9][A-Za-z0-9_-]*(\.[A-Za-z0-9_-]+)*$/,_internals54={gitExec:(args2,cwd)=>_internals45.gitExec(args2,cwd),gitExecOnce,gitProbeExitCode}});function errorText4(error49){return error49 instanceof Error?error49.message:String(error49)}function readHead(directory){try{let head=_internals55.gitExec(["rev-parse","HEAD"],directory).trim();return SHA_RE3.test(head)?head:null}catch{return null}}function isSwarmPath(file2){return file2===".swarm"||file2.startsWith(".swarm/")}function changedFilesSinceBase(directory,baseHead){if(!baseHead||!SHA_RE3.test(baseHead))return null;try{let files=new Set,committed=_internals55.gitExec(["diff","--name-only","-z",baseHead,"HEAD"],directory);for(let file2 of committed.split("\x00"))if(file2.length>0)files.add(file2.replace(/\\/g,"/"));let records=_internals55.gitExec(["status","--porcelain=v1","-z","--untracked-files=all"],directory).split("\x00");for(let i=0;i<records.length;i+=1){let record2=records[i];if(record2.length<4)continue;let code=record2.slice(0,2);if(files.add(record2.slice(3).replace(/\\/g,"/")),code.includes("R")||code.includes("C"))i+=1}return[...files].filter((file2)=>!isSwarmPath(file2)).sort().slice(0,MAX_FALLBACK_FILES)}catch(error49){return warn(`[epic/wave-close] git fallback for divergence unavailable: ${errorText4(error49)}`),null}}function collectTaskAttribution(directory,callerSessionID,taskId){let collected=[],add=(session)=>{if(!session)return;try{collected.push(..._internals55.getModifiedFilesForTask(session,taskId))}catch{}},caller=callerSessionID?_internals55.getAgentSession(callerSessionID):void 0;add(caller);let projectKey=null;try{projectKey=_internals55.hydrationProjectKey(directory)}catch{projectKey=null}if(projectKey!==null)try{for(let[,session]of _internals55.listAgentSessions()){if(session===caller)continue;if(!session||!(session.modifiedFilesByTask instanceof Map))continue;if(session.owningProjectKey!==projectKey)continue;add(session)}}catch{}let canonical=new Set;for(let file2 of collected){let normalized=canonicalAttributionPath(file2,directory);if(normalized!==null)canonical.add(normalized)}return[...canonical].sort()}function lastTransitionAt(events,taskId,resolution){let at=null;for(let event of events){if(event.task_id!==taskId)continue;if(resolution==="removed"&&event.event_type==="task_removed"||event.event_type==="task_status_changed"&&event.to_status===resolution)at=event.timestamp}return at}function countReopens(events,taskId,sinceIso){let since=Date.parse(sinceIso);return events.filter((event)=>event.task_id===taskId&&event.event_type==="task_status_changed"&&event.from_status==="completed"&&event.to_status!=="completed"&&(!Number.isFinite(since)||Date.parse(event.timestamp)>=since)).length}async function readWorkflowCounts(directory,taskId){try{let workflow=(await _internals55.readTaskEvidence(directory,taskId))?.workflow;if(!workflow)return{generation:0,stageA:0,stageB:0};let history=Array.isArray(workflow.retryHistory)?workflow.retryHistory:[];return{generation:Number.isFinite(workflow.generation)?workflow.generation:0,stageA:history.filter((o)=>o==="stage_a_failed").length,stageB:history.filter((o)=>o==="stage_b_failed").length}}catch{return{generation:0,stageA:0,stageB:0}}}function resolutionOf(plan,taskId){for(let phase of plan.phases){let task=(phase.tasks??[]).find((t)=>t.id===taskId);if(!task)continue;if(task.status==="completed")return"completed";if(task.status==="closed")return"closed";return null}return"removed"}function markerFor(epic,taskId,resolution,closeHead,taskCommits){if(resolution!=="completed")return null;if(!epic.git.isRepo)return{ref:null,sha:null,provenance:"no-git"};let landed=taskCommits.get(taskId),sha=landed??closeHead;return{ref:isFullSha(sha)?epicTaskRef(epic.epicKey,taskId):null,sha,provenance:landed?"landing-commit":"wave-close-head"}}async function computeWaveClose(args2){let{directory,epic,wave,plan,sessionID,nowIso:nowIso2}=args2,isRepo=epic.git.isRepo,closeHead=isRepo?readHead(directory):null,events=[];try{events=await _internals55.readLedgerEvents(directory)}catch(error49){warn(`[epic/wave-close] plan ledger unreadable; outcome times fall back to now: ${errorText4(error49)}`)}let changed=isRepo?changedFilesSinceBase(directory,wave.baseHead):null,completedIds=wave.taskIds.filter((taskId)=>resolutionOf(plan,taskId)==="completed"),taskCommits=new Map;if(isRepo&&closeHead&&completedIds.length>0)try{taskCommits=_internals55.findTaskCommits(directory,isFullSha(wave.baseHead)?`${wave.baseHead}..HEAD`:epicCommitRange(epic),epic.planKey,completedIds)}catch(error49){warn(`[epic/wave-close] task commit lookup failed; markers fall back to the close HEAD: ${errorText4(error49)}`)}let outcomes=[],attributedAll=new Set;for(let taskId of wave.taskIds){let resolution=resolutionOf(plan,taskId)??"removed",declared=[...wave.files[taskId]??[]],counts=resolution==="removed"?{generation:0,stageA:0,stageB:0}:await readWorkflowCounts(directory,taskId),undeclared=[],attribution=isRepo?"unavailable":"no-git";if(resolution==="completed"){let attributed=collectTaskAttribution(directory,sessionID,taskId);for(let file2 of attributed)attributedAll.add(file2);let actual=null;if(attributed.length>0)actual=attributed,attribution="session";else if(changed!==null&&wave.taskIds.length===1)actual=changed,attribution="git-single-task";if(actual!==null)undeclared=undeclaredFiles(declared,actual)}let snapshot=wave.mergeFailures?.[taskId];outcomes.push({taskId,phase:wave.phase,waveSeq:wave.seq,resolution,resolvedAt:lastTransitionAt(events,taskId,resolution)??nowIso2,generation:counts.generation,stageAFailures:counts.stageA,stageBFailures:counts.stageB,mergeFailure:snapshot?{outcome:snapshot.outcome,stage:snapshot.stage}:null,declared,undeclared,attribution,reopened:countReopens(events,taskId,epic.startedAt),marker:markerFor(epic,taskId,resolution,closeHead,taskCommits)})}let waveUndeclared=[];if(changed!==null){let declaredAll=Object.values(wave.files).flat();waveUndeclared=undeclaredFiles(declaredAll,changed).filter((file2)=>!attributedAll.has(file2))}return{closeHead,outcomes,waveUndeclared}}function applyWaveClose(record2,seq,computation,nowIso2){let wave=record2.waves.find((w)=>w.seq===seq);if(!wave||wave.status!=="issued"||record2.activeWaveSeq!==seq)return record2;let tasks={...record2.tasks};for(let outcome of computation.outcomes){let before=Object.hasOwn(record2.tasks,outcome.taskId)?record2.tasks[outcome.taskId]:void 0;tasks[outcome.taskId]=before&&before.waveSeq!==outcome.waveSeq?{...outcome,previous:{waveSeq:before.waveSeq,generation:before.generation,stageBFailures:before.stageBFailures,reopened:before.reopened}}:outcome}return{...record2,activeWaveSeq:null,tasks,waves:record2.waves.map((w)=>w.seq===seq?{...w,status:"closed",closedAt:nowIso2,closeHead:computation.closeHead,undeclared:computation.waveUndeclared}:w)}}function recordEpicWaveLearning(args2){let settings=resolveEpicLearningSettings(args2.config);if(!settings.enabled)return[];try{return _internals55.applyClosedWavesToPosterior(args2.directory,args2.record,settings).appliedWaves}catch(error49){return criticalWarn(`[epic/wave-close] learning update failed (the wave flow continues; the next wave close catches it up): ${errorText4(error49)}`),[]}}function releaseWaveAttribution(directory,sessionID,taskIds){let sessions=new Set,caller=sessionID?_internals55.getAgentSession(sessionID):void 0;if(caller)sessions.add(caller);try{let projectKey=_internals55.hydrationProjectKey(directory);for(let[,session]of _internals55.listAgentSessions())if(session&&session.owningProjectKey===projectKey)sessions.add(session)}catch{}for(let session of sessions)for(let taskId of taskIds)try{_internals55.resetModifiedFilesForTask(session,taskId,{remove:!0})}catch{}}var MAX_FALLBACK_FILES=2000,SHA_RE3,_internals55;var init_wave_close=__esm(()=>{init_gate_evidence();init_branch();init_ledger();init_hydration_ownership();init_state();init_logger();init_path();init_learning();init_learning_store();init_markers();SHA_RE3=/^[0-9a-f]{7,64}$/,_internals55={gitExec:(args2,cwd)=>_internals45.gitExec(args2,cwd),readTaskEvidence,readLedgerEvents,listAgentSessions:()=>swarmState.agentSessions.entries(),getAgentSession,getModifiedFilesForTask,resetModifiedFilesForTask,hydrationProjectKey,applyClosedWavesToPosterior,findTaskCommits}});import*as fs32 from"node:fs";import*as path56 from"node:path";function errorText5(error49){return error49 instanceof Error?error49.message:String(error49)}function isSwarmStatePath(file2){let normalized=file2.replace(/\\/g,"/");return normalized===".swarm"||normalized.startsWith(".swarm/")||normalized.includes("/.swarm/")||normalized.endsWith("/.swarm")}function caseKey(file2){return process.platform==="win32"?file2.toLowerCase():file2}function listDirtyEntries(directory){let output=_internals56.gitExec(["status","--porcelain=v1","-z","--untracked-files=all"],directory),entries=[],records=output.split("\x00");for(let i=0;i<records.length;i+=1){let record2=records[i];if(record2.length<4)continue;let code=record2.slice(0,2),file2=record2.slice(3).replace(/\\/g,"/"),origin;if(code.includes("R")||code.includes("C"))i+=1,origin=records[i]?.replace(/\\/g,"/");if(isSwarmStatePath(file2))continue;if(entries.push({path:file2,untracked:code==="??",needsAdd:code[1]!==" ",...origin?{origin}:{}}),entries.length>=MAX_DIRTY_ENTRIES)break}return entries}function coveredBy(file2,declared){let key=caseKey(file2);return declared.some((entry)=>{let d=caseKey(entry.replace(/\\/g,"/").replace(/\/+$/,""));return d.length>0&&(key===d||key.startsWith(`${d}/`))})}function literal2(file2){return`:(literal)${file2}`}function readIndexEntries(directory,files){let entries=new Map;for(let i=0;i<files.length;i+=PATHSPEC_CHUNK){let out=_internals56.gitExec(["ls-files","-s","-z","--",...files.slice(i,i+PATHSPEC_CHUNK).map(literal2)],directory);for(let record2 of out.split("\x00")){let tab=record2.indexOf("\t");if(tab<0)continue;let[mode,sha,stage]=record2.slice(0,tab).split(" ");if(stage!=="0")continue;entries.set(record2.slice(tab+1),`${mode} ${sha}`)}}return entries}function restoreIndexEntries(directory,files,before){for(let i=0;i<files.length;i+=PATHSPEC_CHUNK)_internals56.gitExecOnce(["reset","-q","--",...files.slice(i,i+PATHSPEC_CHUNK).map(literal2)],directory);let after=readIndexEntries(directory,files);for(let file2 of files){let wanted=before.get(file2),actual=after.get(file2);if(wanted===actual)continue;if(wanted){let[mode,sha]=wanted.split(" ");_internals56.gitExecOnce(["update-index","--cacheinfo",`${mode},${sha},${file2}`],directory)}else _internals56.gitExecOnce(["update-index","--force-remove","--",file2],directory)}}function commitPaths(directory,message,files,toAdd){let base=["-c","commit.gpgsign=false","commit","--only","--no-verify","-m",message],pathspecs=files.map(literal2),inlineBytes=pathspecs.reduce((sum,p)=>sum+Buffer.byteLength(p,"utf-8")+1,0),before=readIndexEntries(directory,files);try{for(let i=0;i<toAdd.length;i+=PATHSPEC_CHUNK)_internals56.gitExecOnce(["add","-A","--",...toAdd.slice(i,i+PATHSPEC_CHUNK).map(literal2)],directory);if(inlineBytes<=COMMIT_ARGV_PATHSPEC_BUDGET_BYTES)_internals56.gitExecOnce([...base,"--",...pathspecs],directory);else{let gitPath=_internals56.gitExec(["rev-parse","--git-path",`swarm-epic-residue-${process.pid}-${_internals56.now()}`],directory).trim(),specFile=path56.resolve(directory,gitPath);try{fs32.writeFileSync(specFile,`${pathspecs.join("\x00")}\x00`,"utf-8"),_internals56.gitExecOnce([...base,`--pathspec-from-file=${specFile}`,"--pathspec-file-nul"],directory)}finally{try{fs32.rmSync(specFile,{force:!0})}catch{}}}}catch(error49){try{restoreIndexEntries(directory,files,before)}catch(restoreError){criticalWarn(`[epic] could not restore the index after a failed residue commit (${errorText5(restoreError)}); check \`git status\` for: ${files.slice(0,10).join(", ")}`)}throw error49}try{let head=_internals56.gitExec(["rev-parse","HEAD"],directory).trim();return/^[0-9a-f]{40,64}$/.test(head)?head:null}catch{return null}}function commitTaskResidue(args2){let wanted=new Set;for(let candidate of args2.candidates)if(typeof candidate==="string"&&candidate.length>0&&!candidate.startsWith(":")&&!isSwarmStatePath(candidate))wanted.add(caseKey(candidate.replace(/\\/g,"/")));let files=new Set,toAdd=new Set,scopes=(args2.scopes??[]).filter((entry)=>entry.length>0&&!entry.startsWith(":")),globLike=scopes.filter((entry)=>/[*?]/.test(entry));if(globLike.length>0)warn(`[epic] task ${args2.taskId}: declared scope entries are literal files or directories, never globs; ${globLike.slice(0,5).join(", ")} only match a path spelled exactly like that.`);for(let entry of args2.dirty){if(!wanted.has(caseKey(entry.path))&&!(scopes.length>0&&coveredBy(entry.path,scopes)))continue;if(files.add(entry.path),entry.needsAdd!==!1)toAdd.add(entry.path);if(entry.origin&&!isSwarmStatePath(entry.origin))files.add(entry.origin)}if(files.size===0)return{status:"nothing"};let list2=[...files].sort();try{return{status:"committed",sha:commitPaths(args2.directory,formatEpicTaskCommitMessage(args2.taskId,args2.epic.planKey,args2.label),list2,[...toAdd].sort()),files:list2}}catch(error49){return{status:"failed",error:errorText5(error49),files:list2}}}function inFlightWriterFiles(directory,exclude){let files=new Set;for(let[id,session]of _internals56.listAgentSessions()){if(exclude.has(id)||!session?.delegationActive)continue;if(!(session.modifiedFilesByTask instanceof Map))continue;for(let entries of session.modifiedFilesByTask.values())for(let file2 of entries){let canonical=canonicalAttributionPath(file2,directory);if(canonical!==null)files.add(caseKey(canonical))}}return files}function childSessionFiles(directory,ids){let files=[];for(let id of new Set(ids)){if(typeof id!=="string"||id.length===0)continue;let session=_internals56.getAgentSession(id);if(!session||!(session.modifiedFilesByTask instanceof Map))continue;for(let entries of session.modifiedFilesByTask.values())for(let file2 of entries){let canonical=canonicalAttributionPath(file2,directory);if(canonical!==null)files.push(canonical)}}return files}function declaredScopeOf(epic,taskId){return[...epic.waves.find((w)=>w.seq===epic.activeWaveSeq&&w.status==="issued")?.files[taskId]??[]]}async function commitEpicResidueAfterDelegation(request){try{if(!_internals56.epicSentinelExists(request.directory))return;let agent=stripKnownSwarmPrefix(request.agent);if(agent==="coder"||agent==="architect")return;let epic=_internals56.getOpenEpic(request.directory);if(!epic||!epic.git.isRepo)return;let taskIds=(await request.resolveTaskIds()).filter((id)=>_internals56.readPlanTaskRef(request.directory,id)!==null);if(taskIds.length===0)return;let branch=_internals56.checkEpicBranch(request.directory,epic);if(!branch.ok){criticalWarn(`[epic] ${agent} residue for task ${taskIds.join(", ")} NOT committed: ${branch.message}`);return}let childIds=await request.childSessionIds(),childFiles=childSessionFiles(request.directory,childIds),exclude=new Set([...childIds,request.sessionID].filter((id)=>typeof id==="string"&&id.length>0)),inFlight=inFlightWriterFiles(request.directory,exclude);await _internals56.serializeWithMergeBacks(()=>commitResidueForTasks(request,epic,agent,taskIds,childFiles,inFlight))}catch(error49){criticalWarn(`[epic] residue commit after a ${request.agent} delegation failed (non-fatal; epic_next_wave retries): ${errorText5(error49)}`)}}function commitResidueForTasks(request,epic,agent,taskIds,childFiles,inFlight=new Set){try{let dirty=listDirtyEntries(request.directory).filter((entry)=>!inFlight.has(caseKey(entry.path)));if(dirty.length===0)return;let remaining=dirty,commitStep=(taskId,label,candidates,scopes)=>{let result=commitTaskResidue({directory:request.directory,epic,taskId,label,candidates,scopes,dirty:remaining});if(result.status==="failed")return criticalWarn(`[epic] ${label} for task ${taskId} could not be committed (${result.error}); epic_next_wave retries before the next wave. Files: ${result.files.slice(0,10).join(", ")}`),!1;if(result.status==="committed"){let done=new Set(result.files.map(caseKey));remaining=remaining.filter((entry)=>!done.has(caseKey(entry.path)))}return!0};for(let[index,taskId]of taskIds.entries()){if(index===0&&childFiles.length>0&&!commitStep(taskId,`${agent} residue`,childFiles,[]))return;if(!commitStep(taskId,"residue",_internals56.collectTaskAttribution(request.directory,request.sessionID,taskId),declaredScopeOf(epic,taskId)))return}}catch(error49){criticalWarn(`[epic] residue commit after a ${request.agent} delegation failed (non-fatal; epic_next_wave retries): ${errorText5(error49)}`)}}function classifyDirtyBaseline(dirty){let unattributedTracked=[],unattributedUntracked=[];for(let entry of dirty)(entry.untracked?unattributedUntracked:unattributedTracked).push(entry.path);return{unattributedTracked,unattributedUntracked}}var COMMIT_ARGV_PATHSPEC_BUDGET_BYTES=24576,PATHSPEC_CHUNK=200,MAX_DIRTY_ENTRIES=5000,_internals56;var init_residue_commit=__esm(()=>{init_schema();init_branch();init_worktree_isolation();init_state();init_logger();init_path();init_epic_branch();init_git_once();init_lifecycle();init_plan_key();init_wave_close();_internals56={epicSentinelExists,getOpenEpic,readPlanTaskRef,checkEpicBranch,collectTaskAttribution,getAgentSession,listAgentSessions:()=>swarmState.agentSessions.entries(),gitExec:(args2,cwd)=>_internals45.gitExec(args2,cwd),gitExecOnce,serializeWithMergeBacks:(task)=>runSerializedWithMergeBacks(task),now:()=>Date.now()}});function normalizeToolName(toolName){if(!toolName)return;return toolName.replace(NAMESPACE_PREFIX_PATTERN,"")}function normalizeToolNameLowerCase(toolName){return toolName.replace(NAMESPACE_PREFIX_PATTERN,"").toLowerCase()}function isTaskToolId(toolName){if(!toolName)return!1;if(toolName.includes("."))return/^tool\.[^.:]+\.task$/i.test(toolName);return normalizeToolNameLowerCase(toolName)==="task"}var NAMESPACE_PREFIX_PATTERN;var init_normalize_tool_name=__esm(()=>{NAMESPACE_PREFIX_PATTERN=/^[^:]+[:.]/});function declaresWindowsWrapper(command){return CMD_WRAPPER_DECLARATION.test(command)||PS_WRAPPER_DECLARATION.test(command)}function declaresWindowsWrapperLoose(command){return declaresWindowsWrapper(command)||PS_WRAPPER_LOOSE.test(command)}function recordObservedHostShell(shell){if(typeof shell!=="string"||shell.trim()==="")return;observedHostShell=shell}function getObservedHostShell(){return observedHostShell}function hostShellGrammarFamily(hostShell){let name=(hostShell.split(/[\\/]/).filter(Boolean).pop()??hostShell).replace(/\.exe$/i,"").toLowerCase();return name==="powershell"||name==="pwsh"||name==="cmd"?"windows":"posix"}var CMD_SWITCH,CMD_WRAPPER_DECLARATION,PS_WRAPPER_DECLARATION,PS_WRAPPER_LOOSE,CMD_BUILTIN_PREFIX,CMD_STRIP_PREFIX,PS_STRIP_PREFIX,observedHostShell;var init_shell_executor_context=__esm(()=>{CMD_SWITCH=String.raw`\/[a-z](?::(?:on|off))?`,CMD_WRAPPER_DECLARATION=new RegExp(String.raw`(?:^|[;|&\n])\s*cmd(?:\.exe)?\s+(?:${CMD_SWITCH}\s+)*\/c(?:\s|$)`,"i"),PS_WRAPPER_DECLARATION=/(?:^|[;|&\n])\s*(?:powershell|pwsh)(?:\.exe)?\s+(?:-[A-Za-z]+\s+)*-command(?:\s|$)/i,PS_WRAPPER_LOOSE=/(?:^|\|)\s*(?:powershell|pwsh)(?:\.exe)?\s+-/i;CMD_BUILTIN_PREFIX=new RegExp(String.raw`(?:(?:^|\s)(?:if\s+(?:not\s+)?exist\s+(?:"[^"]*"|\S+)\s+)|(?:^|[;|&\n])\s*cmd(?:\.exe)?\s+(?:${CMD_SWITCH}\s+)*\/c\s+|(?:^|\s)(?:call|start)\s+)*`,"i"),CMD_STRIP_PREFIX=new RegExp(String.raw`^cmd(?:\.exe)?\s+(?:${CMD_SWITCH}\s+)*\/[ck]\s+`,"i"),PS_STRIP_PREFIX=/^(?:powershell|pwsh)(?:\.exe)?\s+(?:-[A-Za-z]+\s+)*-(?:command|c)\s+/i});import*as fsSync6 from"node:fs";import*as path57 from"node:path";function dcNormalizeCommand(cmd){let s=cmd.normalize("NFKC");return s=s.replace(/`(.)/g,"$1"),s=s.replace(/\^([a-zA-Z0-9 ])/g,"$1"),s=s.replace(/""/g,""),s=s.replace(/''/g,""),s}function dcStripOneWrapper(cmd){let t=cmd.trim(),cmdExeMatch=new RegExp(`${CMD_STRIP_PREFIX.source}"?(.*?)"?\\s*$`,"is").exec(t);if(cmdExeMatch)return cmdExeMatch[1].trim();let psCommandMatch=new RegExp(`${PS_STRIP_PREFIX.source}(.+)$`,"is").exec(t);if(psCommandMatch)return psCommandMatch[1].replace(/^["']|["']$/g,"").trim();let psEncMatch=/^(?:powershell|pwsh)(?:\.exe)?\s+(?:-(?:EncodedCommand|encodedcommand|enc|e)\s+)([A-Za-z0-9+/=]+)\s*$/.exec(t);if(psEncMatch)try{return Buffer.from(psEncMatch[1],"base64").toString("utf16le").trim()}catch{return t}let shellMatch=/^(?:bash|sh|zsh|dash|fish)(?:\.exe)?\s+-c\s+"?(.*?)"?\s*$/is.exec(t);if(shellMatch)return shellMatch[1].trim();let evalMatch=/^eval\s+(.+)$/is.exec(t);if(evalMatch)return evalMatch[1].replace(/^["']|["']$/g,"").trim();let envPrefix=/^env(?:\s+(?:[A-Za-z_][A-Za-z0-9_]*=\S+|(?:-[i0vVh]*[uUCSaP]|--u(?:n(?:s(?:e(?:t)?)?)?)?|--c(?:h(?:d(?:i(?:r)?)?)?)?|--a(?:r(?:g(?:v(?:0)?)?)?)?|--s(?:p(?:l(?:i(?:t(?:-(?:s(?:t(?:r(?:i(?:n(?:g)?)?)?)?)?)?)?)?)?)?)?|--e(?:n(?:v(?:0(?:-(?:f(?:r(?:o(?:m)?)?)?)?)?)?)?)?)\s+\S+|-\S+|--[A-Za-z][A-Za-z0-9-]*))*\s+(.+)$/is,prefixMatch=/^(?:sudo|time|nohup)\s+(.+)$/is.exec(t)??envPrefix.exec(t)??/^nice\s+(?:-n\s+\d+\s+)?(.+)$/is.exec(t);if(prefixMatch)return prefixMatch[1].trim();let wslMatch=/^wsl(?:\.exe)?\s+(?:-e|--)\s+(.+)$/is.exec(t);if(wslMatch)return wslMatch[1].trim();let scriptBlockMatch=/^&\s*\{(.+)\}$/s.exec(t);if(scriptBlockMatch)return scriptBlockMatch[1].trim();let iexMatch=/^(?:Invoke-Expression|iex)\s+(.+)$/is.exec(t);if(iexMatch)return iexMatch[1].replace(/^["'`]|["'`]$/g,"").trim();let invokeCommandMatch=/^Invoke-Command\s+.*-ScriptBlock\s*\{(.+)\}$/is.exec(t);if(invokeCommandMatch)return invokeCommandMatch[1].trim();let callMatch=/^call\s+(.+)$/is.exec(t);if(callMatch)return callMatch[1].trim();return null}function dcUnwrapWrappers(cmd){let current=cmd.trim();for(let depth=0;depth<DC_MAX_UNWRAP_DEPTH;depth++){let inner=dcStripOneWrapper(current);if(inner===null||inner===current)break;current=inner.trim()}return current}function dcSplitSegments(cmd){let segments=[],current="",inDoubleQuote=!1,inSingleQuote=!1;for(let i=0;i<cmd.length;i++){let ch=cmd[i],next=cmd[i+1];if(ch==='"'&&!inSingleQuote){inDoubleQuote=!inDoubleQuote,current+=ch;continue}if(ch==="'"&&!inDoubleQuote){inSingleQuote=!inSingleQuote,current+=ch;continue}if(!inDoubleQuote&&!inSingleQuote){if(ch==="&"&&next==="&"||ch==="|"&&next==="|"){segments.push(current.trim()),current="",i++;continue}if(ch==="|"||ch===";"||ch===`
|
|
707
707
|
`||ch==="\r"){segments.push(current.trim()),current="";continue}if(ch==="&"&&next!=="&"){if(!(cmd[i-1]===">"||next===">")){segments.push(current.trim()),current="";continue}}}current+=ch}if(current.trim())segments.push(current.trim());return segments.filter((s)=>s.length>0)}function dcExtractRecursiveRmTargets(segment){let tokens=segment.match(/"(?:[^"\\]|\\.)*"|'[^']*'|\S+/g)??[];if(tokens.length<2||tokens[0]!=="rm")return null;let destructive=!1,index=1;for(;index<tokens.length;index++){let token=tokens[index];if(token==="--"){index++;break}if(!token.startsWith("-")||token==="-")break;if(token==="--recursive"||token==="--force")destructive=!0;if(!token.startsWith("--")&&/[rRfF]/.test(token.slice(1)))destructive=!0}if(!destructive)return null;return tokens.slice(index).map((target)=>target.replace(/^(["'])|(["'])$/g,""))}function dcHasUnresolvableVars(p){return/(%[A-Za-z_][A-Za-z0-9_]*%|\$\{?[A-Za-z_]|\$env:)/i.test(p)}function dcIsRemotePath(p){return DC_REMOTE_PREFIXES.some((pfx)=>p.startsWith(pfx))}function dcLstatAncestorWalk(targetPath,cwd){let normalizedTarget=path57.resolve(cwd,targetPath),normalizedCwd=path57.resolve(cwd),ancestors=[],current=normalizedTarget;while(!0){let rel=path57.relative(normalizedCwd,current);if(rel===".."||rel.startsWith(`..${path57.sep}`)||path57.isAbsolute(rel))break;if(ancestors.push(current),rel==="")break;let parent=path57.dirname(current);if(parent===current)break;current=parent}for(let ancestor of ancestors){let stat8=null;try{stat8=fsSync6.lstatSync(ancestor)}catch(err){if(err.code==="ENOENT")continue;return`lstat failed on "${ancestor}": ${String(err)} — refusing to allow destructive operation on unverifiable path`}if(stat8.isSymbolicLink())return`BLOCKED: "${ancestor}" is a symlink/junction — deleting recursively through it would destroy the link target. Use platform-specific junction deletion (fsutil reparsepoint delete, Remove-Item without -Recurse) instead.`}return null}function dcValidateTargets(targets,cwd){for(let raw of targets){let t=raw.trim().replace(/^["']|["']$/g,"");if(!t||t===".")continue;if(dcHasUnresolvableVars(t))return`BLOCKED: Destructive command targets path with unexpanded variable "${t}" — cannot verify safety. Resolve variables before using destructive operations.`;if(dcIsRemotePath(t))return`BLOCKED: Destructive command targets remote/network filesystem path "${t}" — refusing to execute remote destructive operations.`;if(/^\\\\/.test(t))return`BLOCKED: Destructive command targets UNC path "${t}" — UNC paths in destructive operations are not allowed.`;let filesystemTarget=t.replace(/[\\/]+/g,path57.sep),lstatBlock=dcLstatAncestorWalk(filesystemTarget,cwd);if(lstatBlock)return lstatBlock;let basename11=path57.basename(filesystemTarget);if(dcPathComponents(t).length===1&&DC_SAFE_TARGETS.has(basename11))continue;if(DC_FS_ROOTS.has(t)||DC_FS_ROOTS.has(t.replace(/\//g,"\\")))return`BLOCKED: Destructive command targets filesystem root "${t}"`;if(path57.isAbsolute(t)||/^[A-Za-z]:/.test(t)){for(let blocked of DC_BLOCKED_ABSOLUTE_PREFIXES)if(t.startsWith(blocked))return`BLOCKED: Destructive command targets system path "${t}" which is under protected prefix "${blocked}"`}}return null}function dcIsUntrustedCodePoint(codePoint){return codePoint<=31||codePoint>=127&&codePoint<=159||codePoint>=8234&&codePoint<=8238||codePoint>=8294&&codePoint<=8297}function dcHasUntrustedText(value){return Array.from(value).some((character)=>dcIsUntrustedCodePoint(character.codePointAt(0)??0))}function dcSafeDiagnosticValue(value){return value.split("").map((character)=>dcIsUntrustedCodePoint(character.codePointAt(0)??0)?"?":character).join("").slice(0,512)}function dcPathComponents(value){return value.replace(/\\/g,"/").split("/").filter(Boolean)}function dcComponentEquals(left,right){return process.platform==="win32"?left.toLowerCase()===right.toLowerCase():left===right}function dcScopeContains(scopeEntry,target){let normalize8=(value)=>{let normalized=path57.posix.normalize(value.replace(/\\/g,"/")).replace(/^\.\//,"").replace(/\/$/,"");return process.platform==="win32"?normalized.toLowerCase():normalized},scope=normalize8(scopeEntry),candidate=normalize8(target);return candidate===scope||candidate.startsWith(`${scope}/`)}function dcEvaluateRecursiveDeleteTargets(input){if(input.targets.length===0)return{allowed:!1,code:"DESTRUCTIVE_TARGET_INVALID",reason:"BLOCKED: Recursive delete has no statically verifiable target."};let commonBlock=dcValidateTargets(input.targets,input.cwd);if(commonBlock)return{allowed:!1,code:"DESTRUCTIVE_TARGET_INVALID",reason:commonBlock};let normalizedTargets=[],hasNested=!1;for(let raw of input.targets){let target=raw.trim().replace(/^['"]|['"]$/g,""),safeTarget=dcSafeDiagnosticValue(target);if(!target||target==="."||dcHasUntrustedText(target)||dcPathComponents(target).includes(".."))return{allowed:!1,code:"DESTRUCTIVE_TARGET_INVALID",reason:`BLOCKED: Recursive delete target "${safeTarget}" is empty, the workspace root, contains traversal, or contains control characters.`};let components=dcPathComponents(target);if(components.some((component)=>dcComponentEquals(component,".git")||dcComponentEquals(component,".swarm")))return{allowed:!1,code:"DESTRUCTIVE_TARGET_PROTECTED",reason:`BLOCKED: Recursive delete target "${safeTarget}" contains protected .git or .swarm state.`};let filesystemTarget=target.replace(/[\\/]+/g,path57.sep),resolved=path57.resolve(input.cwd,filesystemTarget),relative13=path57.relative(path57.resolve(input.cwd),resolved);if(relative13===""||relative13===".."||relative13.startsWith(`..${path57.sep}`)||path57.isAbsolute(relative13))return{allowed:!1,code:"DESTRUCTIVE_TARGET_OUTSIDE_WORKSPACE",reason:`BLOCKED: Recursive delete target "${safeTarget}" is not strictly contained by the workspace.`};let basename11=path57.basename(resolved);if(!DC_SAFE_TARGETS.has(basename11))return{allowed:!1,code:"DESTRUCTIVE_TARGET_NOT_SAFE_ARTIFACT",reason:`BLOCKED: Recursive delete target "${safeTarget}" is not an allowlisted build/cache artifact.`};let normalizedRelative=relative13.replace(/\\/g,"/");if(components.length!==1){if(hasNested=!0,!input.verifiedScope?.bindingId||!input.verifiedScope.generationId)return{allowed:!1,code:"DESTRUCTIVE_TARGET_SCOPE_REQUIRED",reason:`BLOCKED: Nested safe artifact "${safeTarget}" requires a verified active coder scope binding.`};if(!input.verifiedScope.files.some((entry)=>dcScopeContains(entry,normalizedRelative)))return{allowed:!1,code:"DESTRUCTIVE_TARGET_OUT_OF_SCOPE",reason:`BLOCKED: Nested safe artifact "${safeTarget}" is outside the verified active coder scope.`}}normalizedTargets.push(normalizedRelative)}return{allowed:!0,kind:hasNested?"scoped-nested-safe-artifact":"bare-safe-artifact",targets:normalizedTargets}}function dcCheckJunctionCreation(segment,cwd){let mklinkMatch=/^mklink(?:\.exe)?\s+\/[JjDd]\s+"?([^"\s]+)"?\s+"?([^"\s]+)"?/i.exec(segment);if(mklinkMatch){let target=mklinkMatch[2].trim();if(!dcHasUnresolvableVars(target)){let resolved=path57.resolve(cwd,target),rel=path57.relative(cwd,resolved);if(rel.startsWith("..")||path57.isAbsolute(rel))return`BLOCKED: Junction/symlink creation targeting path outside working directory: mklink target "${target}" resolves to "${resolved}" which is outside "${cwd}". Creating junctions to external paths and then deleting them recursively can destroy data.`}return null}let newItemTypeMatch=/New-Item\b.*-ItemType\s+(?:Junction|SymbolicLink|HardLink)\b/i.test(segment),newItemTargetMatch=/-Target\s+"?([^"\s;]+)"?/i.exec(segment),newItemMatch=newItemTypeMatch?newItemTargetMatch:null;if(newItemMatch){let target=newItemMatch[1].trim();if(!dcHasUnresolvableVars(target)){let resolved=path57.resolve(cwd,target),rel=path57.relative(cwd,resolved);if(rel.startsWith("..")||path57.isAbsolute(rel))return`BLOCKED: Junction/symlink creation targeting path outside working directory: New-Item target "${target}" resolves to "${resolved}" which is outside "${cwd}". This pattern caused the K2.6 data-loss incident.`}return null}let lnMatch=/^ln\s+(?:-[sfnv]*s[sfnv]*|-s)\s+"?([^"\s]+)"?(?:\s+"?[^"\s]+"?)?\s*$/.exec(segment);if(lnMatch){let target=lnMatch[1].trim();if(!dcHasUnresolvableVars(target)){let resolved=path57.resolve(cwd,target),rel=path57.relative(cwd,resolved);if(rel.startsWith("..")||path57.isAbsolute(rel))return`BLOCKED: Symlink creation targeting path outside working directory: ln -s target "${target}" resolves to "${resolved}" which is outside "${cwd}". Symlinks to external paths combined with recursive deletion can destroy data.`}return null}return null}function dcExtractWindowsCmdTargets(segment){let rmdirMatch=/^(?:rmdir|rd)(?:\.exe)?\s+(?:\/[sqSQ]\s+)*"?(.+?)"?\s*$/i.exec(segment);if(rmdirMatch)return[rmdirMatch[1].trim()];let delMatch=/^del(?:\.exe)?\s+(?:\/[sqfSQF]\s+)*"?(.+?)"?\s*$/i.exec(segment);if(delMatch)return[delMatch[1].trim()];return[]}function dcExtractPowerShellTargets(segment){let verbMatch=/^(?:Remove-Item|ri|rm|rmdir|del|erase|rd)\s+/i.exec(segment);if(!verbMatch)return[];let tokens=segment.slice(verbMatch[0].length).match(/"[^"]*"|'[^']*'|[^\s]+/g)??[],targets=[],valueFlags=new Set(["-literalpath","-path","-filter","-include","-exclude","-lp"]),skipNext=!1;for(let tok of tokens){if(skipNext){skipNext=!1;continue}if(tok.startsWith("-")){if(valueFlags.has(tok.toLowerCase())){skipNext=!0;let idx=tokens.indexOf(tok);if(idx!==-1&&idx+1<tokens.length){let val=tokens[idx+1].replace(/^["']|["']$/g,"");if(val)targets.push(val);skipNext=!0}}}else{let cleaned=tok.replace(/^["']|["']$/g,"");if(cleaned)targets.push(cleaned)}}return targets}var DC_MAX_UNWRAP_DEPTH=5,DC_SAFE_TARGETS,DC_BLOCKED_ABSOLUTE_PREFIXES,DC_FS_ROOTS,DC_REMOTE_PREFIXES;var init_destructive_command=__esm(()=>{init_shell_executor_context();DC_SAFE_TARGETS=new Set(["node_modules","dist","build","coverage",".next",".turbo",".cache",".venv","venv","__pycache__","target","out",".parcel-cache",".svelte-kit",".nuxt",".output",".angular",".gradle","vendor"]),DC_BLOCKED_ABSOLUTE_PREFIXES=["/root","/home","/Users","/etc","/var","/usr","/opt","/bin","/sbin","/lib","/boot","/proc","/sys","/dev","/run","/System","/Library","/Applications","C:\\Windows","C:\\Users","C:\\Program Files","C:\\ProgramData","C:/Windows","C:/Users","C:/Program Files","C:/ProgramData"],DC_FS_ROOTS=new Set(["/","C:\\","C:/","D:\\","D:/","E:\\","E:/"]),DC_REMOTE_PREFIXES=["\\\\","/Volumes/","/net/","/nfs/","/smb/","/run/user/"]});import{createHash as createHash30}from"node:crypto";function digest2(value){return createHash30("sha256").update(value).digest("hex")}function hasAmbiguousSyntax(value){let single=!1,double=!1,escaped=!1;for(let character of value){if(escaped){escaped=!1;continue}if(character==="\\"){escaped=!0;continue}if(character==="'"&&!double)single=!single;if(character==='"'&&!single)double=!double}return single||double||escaped||/<<[-]?\s*\w+/.test(value)||/\$\(|`|\$\{?|\$IFS\b/i.test(value)}function matchRule(rules,segment){for(let rule of rules)if(rule.pattern.test(segment))return rule;return null}function classifySegment(segment,ambiguous){let bounded=segment.slice(0,MAX_EVIDENCE_CHARS),catastrophic=matchRule(CATASTROPHIC,segment);if(catastrophic)return{segment:bounded,category:"catastrophic",reason:catastrophic.reason??catastrophic.pattern.source,ruleId:catastrophic.id};let destructive=matchRule(DESTRUCTIVE,segment);if(destructive)return{segment:bounded,category:"destructive",reason:destructive.reason??destructive.pattern.source,ruleId:destructive.id};if(ambiguous||/[<>]|\|\s*(?:sh|bash|zsh|fish|pwsh|powershell|cmd)\b/i.test(segment))return{segment:bounded,category:"unknown",reason:"ambiguous shell syntax"};let escalate=matchRule(ESCALATE,segment);if(escalate)return{segment:bounded,category:"escalate",reason:escalate.reason??escalate.pattern.source,ruleId:escalate.id};let safe=matchRule(SAFE,segment);if(safe)return{segment:bounded,category:"safe",reason:safe.reason??safe.pattern.source,ruleId:safe.id};return{segment:bounded,category:"unknown",reason:"command is not in the bounded classifier corpus"}}function getSharedClassifierGuardrailBlock(classification){if(classification.aggregate!=="catastrophic"&&classification.aggregate!=="destructive")return null;for(let segment of classification.segments){if(segment.category!==classification.aggregate||typeof segment.ruleId!=="string")continue;let rule=BLOCK_RULES_BY_ID.get(segment.ruleId);if(!rule?.liveGuardrail||rule.liveGuardrail.mode!=="immediate-block")continue;return Object.freeze({ruleId:rule.id,category:classification.aggregate,destructiveCategory:rule.liveGuardrail.destructiveCategory,message:rule.liveGuardrail.message})}return null}function classifyCommand(original){let originalDigest=digest2(typeof original==="string"?original:String(original));if(typeof original!=="string"||original.length===0)return Object.freeze({v:1,originalDigest,aggregate:"unknown",ambiguous:!0,segments:Object.freeze([])});if(Buffer.byteLength(original,"utf8")>MAX_COMMAND_BYTES)return Object.freeze({v:1,originalDigest,aggregate:"unknown",ambiguous:!0,segments:Object.freeze([])});let normalized=dcNormalizeCommand(original),unwrapped=dcUnwrapWrappers(normalized),candidates=[...new Set([normalized,unwrapped,...dcSplitSegments(normalized),...dcSplitSegments(unwrapped),...dcSplitSegments(normalized).map(dcUnwrapWrappers)])];if(candidates.length===0||candidates.length>MAX_SEGMENTS)return Object.freeze({v:1,originalDigest,aggregate:"unknown",ambiguous:!0,segments:Object.freeze([])});let ambiguous=hasAmbiguousSyntax(normalized),segments=candidates.map((segment)=>classifySegment(segment.trim(),ambiguous)),aggregate=segments.reduce((highest,current)=>SEVERITY[current.category]>SEVERITY[highest]?current.category:highest,"safe"),frozenSegments=Object.freeze(segments.map((segment)=>Object.freeze(segment)));return Object.freeze({v:1,originalDigest,aggregate,ambiguous,segments:frozenSegments})}var MAX_COMMAND_BYTES=65536,MAX_SEGMENTS=128,MAX_EVIDENCE_CHARS=512,SEVERITY,CATASTROPHIC,DESTRUCTIVE,ESCALATE,SAFE,BLOCK_RULES_BY_ID;var init_command_classifier=__esm(()=>{init_destructive_command();SEVERITY={safe:0,escalate:1,unknown:2,destructive:3,catastrophic:4},CATASTROPHIC=[{id:"fork-bomb",pattern:/:\s*\(\s*\)\s*\{[^}]*\|[^}]*:/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"fork bomb",message:"BLOCKED: catastrophic shell operation detected by the shared command classifier; critic approval cannot waive this policy"}},{id:"power-control",pattern:/\b(?:shutdown|reboot|halt|poweroff)\b/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"system shutdown",message:"BLOCKED: catastrophic shell operation detected by the shared command classifier; critic approval cannot waive this policy"}},{id:"mkfs-suffixed",pattern:/\bmkfs[./]/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"disk format",message:"BLOCKED: catastrophic shell operation detected by the shared command classifier; critic approval cannot waive this policy"}},{id:"diskpart",pattern:/^diskpart(?:\.exe)?$/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"disk format",message:"BLOCKED: catastrophic shell operation detected by the shared command classifier; critic approval cannot waive this policy"}},{id:"format-drive",pattern:/^format\s+[A-Za-z]:/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"disk format",message:"BLOCKED: catastrophic shell operation detected by the shared command classifier; critic approval cannot waive this policy"}},{id:"vssadmin-delete",pattern:/^vssadmin(?:\.exe)?\s+delete\b/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"data wipe",message:"BLOCKED: catastrophic shell operation detected by the shared command classifier; critic approval cannot waive this policy"}},{id:"wbadmin-delete",pattern:/^wbadmin(?:\.exe)?\s+delete\b/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"data wipe",message:"BLOCKED: catastrophic shell operation detected by the shared command classifier; critic approval cannot waive this policy"}},{id:"bcdedit-delete",pattern:/^bcdedit(?:\.exe)?\s+\/delete\b/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"boot configuration delete",message:"BLOCKED: catastrophic shell operation detected by the shared command classifier; critic approval cannot waive this policy"}},{id:"dd-data-wipe",pattern:/\bdd\b[^\n]*(?:of=\s*(?:\/dev\/|[A-Za-z]:)|if=\s*\/dev\/(?:zero|random|urandom))/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"data wipe",message:'BLOCKED: "dd" with destructive data-wipe parameters detected by the shared command classifier; critic approval cannot waive this policy'}},{id:"git-push-force",pattern:/\bgit\s+push\b[^\n]*(?:--force(?!-with-lease)|\s-f\b)/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"force push",message:"BLOCKED: Force push detected — git push --force is not allowed (use --force-with-lease instead)"}},{id:"curl-pipe-shell",pattern:/\b(?:curl|wget)\b[^|\n]*\|\s*(?:sh|bash|zsh|fish)\b/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"script pipe execution",message:"BLOCKED: catastrophic shell operation detected by the shared command classifier; critic approval cannot waive this policy"}}],DESTRUCTIVE=[{id:"git-reset-hard",pattern:/\bgit\s+(?:-C\s+\S+\s+)?reset\s+--hard\b/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"git reset",message:'BLOCKED: "git reset --hard" detected — use --soft or --mixed with caution'}},{id:"git-reset-mixed-target",pattern:/\bgit\s+(?:-C\s+\S+\s+)?reset\s+--mixed\s+\S+/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"git reset",message:'BLOCKED: "git reset --mixed" with a target branch/commit is not allowed'}},{id:"git-clean-force",pattern:/\bgit\s+(?:-C\s+\S+\s+)?clean\s+-[^\s]*[fdx]/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"git clean",message:'BLOCKED: "git clean -fd" detected — permanently deletes untracked files and directories'}},{id:"rm-recursive",pattern:/\brm\b[^\n]*(?:-[^\s]*[rf]|--recursive|--force)/i,liveGuardrail:{mode:"target-aware",destructiveCategory:"recursive delete",message:"target-aware recursive delete"}},{id:"windows-recursive-delete",pattern:/\b(?:rmdir|rd|del)(?:\.exe)?\b[^\n]*\/[sqf]/i,liveGuardrail:{mode:"target-aware",destructiveCategory:"recursive delete",message:"target-aware Windows recursive delete"}},{id:"powershell-recursive-delete",pattern:/\bRemove-Item\b[^\n]*(?:-Recurse|-Force)/i,liveGuardrail:{mode:"target-aware",destructiveCategory:"recursive remove",message:"target-aware PowerShell recursive delete"}},{id:"find-delete",pattern:/\bfind\b[^\n]*\s-delete\b/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"find delete",message:'BLOCKED: "find -delete" detected — dynamic delete expansion is not allowed from shell commands'}},{id:"rsync-delete",pattern:/\brsync\b[^\n]*--delete(?:-after|-before|-during|-delay)?\b/i,liveGuardrail:{mode:"target-aware",destructiveCategory:"rsync delete",message:"target-aware rsync delete"}},{id:"docker-system-prune",pattern:/\bdocker\s+system\s+prune\b/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"docker prune",message:'BLOCKED: "docker system prune" detected — destructive container operation'}},{id:"kubectl-delete",pattern:/\bkubectl\s+delete\b/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"kubectl delete",message:'BLOCKED: "kubectl delete" detected — destructive cluster operation'}},{id:"sql-drop",pattern:/\bDROP\s+(?:TABLE|DATABASE|SCHEMA)\b/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"sql drop",message:"BLOCKED: SQL DROP command detected — destructive database operation"}},{id:"sql-truncate",pattern:/\bTRUNCATE\s+TABLE\b/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"sql truncate",message:"BLOCKED: SQL TRUNCATE command detected — destructive database operation"}},{id:"sed-config-rewrite",pattern:/\bsed\s+-i\b[^\n]*(?:biome\.json|oxlintrc|eslint)/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"config rewrite",message:"BLOCKED: in-place configuration rewrite detected — protected lint or policy config edit matched the shared command classifier"}},{id:"sdelete",pattern:/^sdelete(?:\.exe)?\s+/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"secure delete",message:'BLOCKED: "sdelete" detected — secure file deletion (Sysinternals)'}},{id:"fsutil-destructive",pattern:/^fsutil(?:\.exe)?\s+(?:reparsepoint\s+delete|file\s+setzerodata)\b/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"data wipe",message:'BLOCKED: "fsutil" destructive subcommand detected'}},{id:"takeown-recursive",pattern:/^takeown(?:\.exe)?\s+.*\/[rR]\b/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"ownership takeover",message:'BLOCKED: "takeown /R" (recursive ownership takeover) detected — often precedes destructive operations'}},{id:"cipher-wipe",pattern:/^cipher(?:\.exe)?\s+\/[wW]\b/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"data wipe",message:'BLOCKED: "cipher /w" detected — overwrites free disk space (data wipe operation)'}},{id:"robocopy-mirror",pattern:/^robocopy(?:\.exe)?\s+.*\/(?:MIR|mir)\b/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"mirror sync",message:'BLOCKED: "robocopy /MIR" (mirror) detected — can delete files in the destination that do not exist in the source'}},{id:"chmod-permission-wipe",pattern:/^chmod\s+.*-[rR]\b.*000\b/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"permission wipe",message:'BLOCKED: "chmod -R 000" detected — removes all permissions recursively'}},{id:"chattr-immutable",pattern:/^chattr\s+.*\+i\b/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"immutable flag",message:'BLOCKED: "chattr +i" detected — makes files immutable'}},{id:"icacls-deny",pattern:/^icacls(?:\.exe)?\s+.*\/deny\b/i,liveGuardrail:{mode:"immediate-block",destructiveCategory:"permission deny",message:'BLOCKED: "icacls /deny" detected — denies filesystem permissions'}}],ESCALATE=[{id:"sudo-network-permissions",pattern:/\b(?:sudo|chmod|chown|curl|wget|ssh|scp|sftp|nc|netcat)\b/i},{id:"dynamic-eval",pattern:/\b(?:eval|Invoke-Expression|iex)\b/i}],SAFE=[{id:"safe-readonly-shell",pattern:/^(?:cat|head|tail|file|stat|wc|sort|uniq|cut|grep|rg|ag|ls|pwd|whoami|hostname|uname|date|which|type|tree)\b/i},{id:"safe-readonly-git",pattern:/^git\s+(?:-C\s+\S+\s+)?(?:status|log|show|diff|branch|describe|rev-parse|rev-list|ls-files|remote\s+-v)\b/i},{id:"safe-shell-builtin",pattern:/^(?:true|false|test|echo|printf)\b/i},{id:"safe-package-scripts",pattern:/^(?:bun|npm|yarn|pnpm)\s+(?:run\s+(?:typecheck|lint|test|build)|test|typecheck|lint)\b/i}],BLOCK_RULES_BY_ID=new Map([...CATASTROPHIC,...DESTRUCTIVE].map((rule)=>[rule.id,rule]))});import*as path58 from"node:path";function normalizeProtectedPath(value){return value.replace(/\\/g,"/").replace(/^\.\//,"").replace(/\/+$/,"")}function equalsOrDescendant(candidate,protectedPath){let left=process.platform==="win32"?candidate.toLowerCase():candidate,right=process.platform==="win32"?protectedPath.toLowerCase():protectedPath;return left===right||left.startsWith(`${right}/`)}function isPolicyProtectedPath(filePath,options={}){if(!filePath)return!1;let normalized=normalizeProtectedPath(filePath),segments=normalized.split("/").filter(Boolean);if(options.includeDefaults!==!1){if(segments.some((segment)=>DEFAULT_SEGMENTS.has(process.platform==="win32"?segment.toLowerCase():segment)))return!0;if(DEFAULT_PREFIXES.some((prefix)=>equalsOrDescendant(normalized,prefix)))return!0}return(options.additional??[]).some((entry)=>{let protectedPath=normalizeProtectedPath(entry);if(!protectedPath)return!1;if(equalsOrDescendant(normalized,protectedPath))return!0;if(protectedPath.includes("/"))return!1;return segments.some((segment)=>(process.platform==="win32"?segment.toLowerCase():segment)===(process.platform==="win32"?protectedPath.toLowerCase():protectedPath))})}function protectedRoots(projectRoot,additional=[]){return[...DEFAULT_PREFIXES,...DEFAULT_SEGMENTS,...additional].map((entry)=>path58.resolve(projectRoot,entry))}var DEFAULT_SEGMENTS,DEFAULT_PREFIXES,DEFAULT_PROTECTED_PATH_PREFIXES;var init_protected_path_policy=__esm(()=>{DEFAULT_SEGMENTS=new Set([".git",".swarm",".env","package.json","package-lock.json","bun.lock","CHANGELOG.md",".release-please-manifest.json","release-please-config.json","CODEOWNERS"]),DEFAULT_PREFIXES=[".github/workflows",".github/CODEOWNERS","src/sandbox","src/hooks/guardrails","src/security","src/evaluation","docs/releases","tests/fixtures/evaluation"],DEFAULT_PROTECTED_PATH_PREFIXES=DEFAULT_PREFIXES});class Reader{src;pos=0;constructor(src){this.src=src}eof(){return this.pos>=this.src.length}peek(){return this.src[this.pos]??""}skipWs(){while(!this.eof()&&WHITESPACE.test(this.peek()))this.pos+=1}eat(ch){if(this.peek()===ch)return this.pos+=1,!0;return!1}eatWord(word){if(!this.src.startsWith(word,this.pos))return!1;let next=this.src[this.pos+word.length]??"";if(next!==""&&IDENT_PART.test(next))return!1;return this.pos+=word.length,!0}ident(){if(!IDENT_START.test(this.peek()))return null;let start=this.pos;this.pos+=1;while(!this.eof()&&IDENT_PART.test(this.peek()))this.pos+=1;return this.src.slice(start,this.pos)}string(){let quote=this.peek();if(quote!=='"'&"e!=="'")return null;this.pos+=1;let out="";while(!this.eof()){let ch=this.peek();if(this.pos+=1,ch===quote)return out;if(ch===`
|
|
708
708
|
`||ch==="\r")return null;if(ch==="\\"){let esc2=this.peek();if(!SIMPLE_ESCAPES.has(esc2))return null;this.pos+=1,out+=esc2;continue}out+=ch}return null}number(){let m=/^-?\d+(\.\d+)?([eE][+-]?\d+)?/.exec(this.src.slice(this.pos));if(!m)return!1;return this.pos+=m[0].length,!0}}function parseValue(r,depth){if(depth>8)return!1;r.skipWs();let ch=r.peek();if(ch==='"'||ch==="'")return r.string()!==null;if(ch==="{")return parseObject(r,depth+1);if(ch==="[")return parseArray(r,depth+1);if(r.eatWord("true")||r.eatWord("false")||r.eatWord("null"))return!0;return r.number()}function parseArray(r,depth){if(!r.eat("["))return!1;if(r.skipWs(),r.eat("]"))return!0;for(;;){if(!parseValue(r,depth))return!1;if(r.skipWs(),r.eat(",")){if(r.skipWs(),r.eat("]"))return!0;continue}return r.eat("]")}}function parseObject(r,depth){if(!r.eat("{"))return!1;if(r.skipWs(),r.eat("}"))return!0;for(;;){r.skipWs();let key=r.peek()==='"'||r.peek()==="'"?r.string():r.ident();if(key===null||BLOCKED_NAMES.has(key))return!1;if(r.skipWs(),!r.eat(":"))return!1;if(!parseValue(r,depth))return!1;if(r.skipWs(),r.eat(",")){if(r.skipWs(),r.eat("}"))return!0;continue}return r.eat("}")}}function parseCallee(r){if(r.eatWord("search"))return!0;if(!r.eatWord("tools"))return!1;let segments=0;for(;;){if(r.skipWs(),r.eat(".")){r.skipWs();let name=r.ident();if(name===null||BLOCKED_NAMES.has(name))return!1;segments+=1;continue}if(r.peek()==="["){r.pos+=1,r.skipWs();let name=r.string();if(r.skipWs(),name===null||!SEGMENT_NAME.test(name)||BLOCKED_NAMES.has(name)||!r.eat("]"))return!1;segments+=1;continue}return segments>0}}function isSingleToolCallProgram(code){if(typeof code!=="string")return!1;if(code.length===0||code.length>20000)return!1;let r=new Reader(code);if(r.skipWs(),r.eatWord("return"),r.skipWs(),r.eatWord("await"),r.skipWs(),!parseCallee(r))return!1;if(r.skipWs(),!r.eat("("))return!1;if(r.skipWs(),!r.eat(")")){if(!parseValue(r,0))return!1;if(r.skipWs(),!r.eat(")"))return!1}return r.skipWs(),r.eat(";"),r.skipWs(),r.eof()}var BLOCKED_NAMES,IDENT_START,IDENT_PART,SEGMENT_NAME,WHITESPACE,SIMPLE_ESCAPES;var init_code_mode_program=__esm(()=>{BLOCKED_NAMES=new Set(["constructor","prototype","__proto__","__defineGetter__","__defineSetter__","__lookupGetter__","__lookupSetter__"]),IDENT_START=/[A-Za-z_$]/,IDENT_PART=/[A-Za-z0-9_$]/,SEGMENT_NAME=/^[A-Za-z0-9_-]{1,100}$/,WHITESPACE=/[ \t\r\n]/,SIMPLE_ESCAPES=new Set(["n","r","t",'"',"'","\\","/"])});import*as fs33 from"node:fs";import*as path59 from"node:path";function isReadOnlyTool(toolName){if(!toolName)return!1;return READ_ONLY_TOOLS.has(toolName.toLowerCase())}function isWriteLikeTool(toolName){if(!toolName)return!1;return WRITE_LIKE_TOOLS.has(toolName.toLowerCase())}function isSubagentDelegation(toolName,args2){if(isTaskToolId(toolName)&&args2&&typeof args2==="object")return!0;let lower=normalizeToolNameLowerCase(toolName??"");return SUBAGENT_TOOLS.has(lower)}function isWithinDirectory(target,root){if(!target||!root)return!1;let resolvedTarget=path59.resolve(target),resolvedRoot=path59.resolve(root);if(resolvedTarget===resolvedRoot)return!0;let withSep=resolvedRoot.endsWith(path59.sep)?resolvedRoot:resolvedRoot+path59.sep;if(process.platform==="win32")return resolvedTarget.toLowerCase().startsWith(withSep.toLowerCase());return resolvedTarget.startsWith(withSep)}function isProtectedPath2(filePath,config2){if(!filePath)return!1;let normalized=normalizePath(filePath);for(let prefix of ALWAYS_PROTECTED_PREFIXES){let np=normalizePath(prefix);if(normalized===np||normalized.startsWith(`${np}/`))return!0}let allowDefaults=config2?.permission_policy?.allow_defaults!==!1;return isPolicyProtectedPath(normalized,{includeDefaults:allowDefaults,additional:[...allowDefaults?PROTECTED_PATH_DEFAULTS:[],...config2?.permission_policy?.protected_paths??[]]})}function classifyPathRisk(filePath,context){if(!filePath)return{withinProjectRoot:!1,withinDeclaredScope:null,protected:!1,highRiskBuild:!1};let absolute=path59.isAbsolute(filePath)?filePath:path59.resolve(context.directory,filePath),resolvedAbsolute=(()=>{try{let candidate=absolute,depth=0;while(depth<32){if(fs33.existsSync(candidate)){if(isWithinDirectory(candidate,context.directory))try{return fs33.realpathSync(candidate)}catch{return candidate}return absolute}let parent=path59.dirname(candidate);if(parent===candidate)break;candidate=parent,depth+=1}return absolute}catch{return absolute}})(),withinProjectRoot=isWithinDirectory(absolute,context.directory)&&isWithinDirectory(resolvedAbsolute,context.directory),relative14=normalizePath(path59.relative(context.directory,absolute)),withinDeclaredScope=null;if(Array.isArray(context.declaredScope))withinDeclaredScope=context.declaredScope.length===0?!1:context.declaredScope.some((scope)=>{let s=normalizePath(scope);if(!s)return!1;return relative14===s||relative14.startsWith(`${s}/`)});let highRiskBuild=HIGH_RISK_BUILD_PATHS.some((entry)=>{let e=normalizePath(entry);if(e.endsWith("/"))return relative14.startsWith(e);return relative14===e||relative14.startsWith(`${e}/`)});return{withinProjectRoot,withinDeclaredScope,protected:!1,highRiskBuild}}function classifyCommandRisk(command,_cwd,_context){if(FULL_AUTO_SECRET_READ_PATTERN.test(command)||FULL_AUTO_SECRET_ENV_PATTERN.test(command)||FULL_AUTO_PRIMARY_PUSH_PATTERN.test(command))return{decision:"deny",reason:"full-auto consumer policy: command reads secrets or targets a primary branch push"};let classification=classifyCommand(command);if(classification.aggregate==="catastrophic"||classification.aggregate==="destructive")return{decision:"deny",reason:`shared classifier: ${classification.aggregate}`};if(classification.aggregate==="safe")return{decision:"allow",reason:"shared classifier: safe"};return{decision:"escalate_critic",reason:`shared classifier: ${classification.aggregate}`}}function extractPathArgs(toolName,args2){if(!args2||typeof args2!=="object")return[];let found=[];for(let key of PATH_ARG_KEYS){let v=args2[key];if(typeof v==="string"&&v.trim())found.push(v)}let filesArg=args2.files;if(Array.isArray(filesArg)){for(let f of filesArg)if(typeof f==="string"&&f.trim())found.push(f);else if(f&&typeof f==="object"&&typeof f.path==="string")found.push(f.path)}let editsArg=args2.edits;if(Array.isArray(editsArg)){for(let e of editsArg)if(e&&typeof e==="object"&&typeof e.file_path==="string")found.push(e.file_path)}if(toolName==="declare_scope"&&Array.isArray(args2.files));return found}function extractCommandArg(args2){if(!args2||typeof args2!=="object")return;return typeof args2.command==="string"&&args2.command||typeof args2.cmd==="string"&&args2.cmd||typeof args2.script==="string"&&args2.script||void 0}function extractURLArg(args2){if(!args2||typeof args2!=="object")return;return typeof args2.url==="string"&&args2.url||typeof args2.uri==="string"&&args2.uri||typeof args2.endpoint==="string"&&args2.endpoint||void 0}function isTrustedDomain(url2,config2){let domains=config2?.permission_policy?.trusted_domains??[];if(domains.length===0)return!1;let host="";try{host=new URL(url2).hostname.toLowerCase()}catch{return!1}return domains.some((d)=>{let dl=d.toLowerCase();return host===dl||host.endsWith(`.${dl}`)})}function resolveAgentCapabilityTools(roleName,pluginConfig){let tools=pluginConfig?.tool_filter?.overrides?.[roleName]??AGENT_TOOL_MAP[roleName]??[];if(pluginConfig?.memory?.enabled===!0)tools=Array.from(new Set([...tools,...MEMORY_AGENT_TOOL_MAP[roleName]??[]]));if(pluginConfig?.external_skills?.curation_enabled===!0)tools=Array.from(new Set([...tools,...EXTERNAL_SKILL_AGENT_TOOL_MAP[roleName]??[]]));if(pluginConfig?.council?.enabled===!0)tools=Array.from(new Set([...tools,...COUNCIL_AGENT_TOOL_MAP[roleName]??[]]));if(pluginConfig?.council?.general?.enabled===!0)tools=Array.from(new Set([...tools,...GENERAL_COUNCIL_AGENT_TOOL_MAP[roleName]??[]]));if(pluginConfig?.turbo!==void 0)tools=Array.from(new Set([...tools,...TURBO_AGENT_TOOL_MAP[roleName]??[]]));if(isEpicModeConfigEnabled(pluginConfig))tools=Array.from(new Set([...tools,...EPIC_AGENT_TOOL_MAP[roleName]??[]]));let skillTools=SKILL_AGENT_TOOL_MAP[roleName]??[];if(skillTools.length>0)if(pluginConfig?.skills?.enabled===!0)tools=Array.from(new Set([...tools,...skillTools]));else{let skillSet=new Set(skillTools);tools=tools.filter((tool)=>!skillSet.has(tool))}if(pluginConfig?.skills?.enabled!==!0&&roleName!=="skill_improver"){let allSkillTools=new Set(SKILL_TOOL_NAMES);tools=tools.filter((tool)=>!allSkillTools.has(tool))}return tools}function resolveDelegationRisk(input,subagentName){let role=input.generatedAgentNames&&input.generatedAgentNames.length>0?resolveGeneratedAgentRole(subagentName,input.generatedAgentNames):getCanonicalAgentRole(subagentName);if(!isKnownCanonicalRole(role))return{risk:"high",reason:"subagent role is unknown or not registry-backed",role,tools:[],safeReadOnly:!1};let tools=resolveAgentCapabilityTools(role,input.pluginConfig);if(tools.length===0)return{risk:"high",reason:"subagent has no registered capability map",role,tools,safeReadOnly:!1};let dangerous=tools.some((tool)=>isWriteLikeTool(tool)||SHELL_TOOLS.has(tool)||NETWORK_TOOLS.has(tool)||tool==="swarm_command"||tool==="Task"||tool==="task"),unknown2=tools.some((tool)=>!isReadOnlyTool(tool)&&!isWriteLikeTool(tool)&&!SHELL_TOOLS.has(tool)&&!NETWORK_TOOLS.has(tool)&&tool!=="swarm_command");if(dangerous||unknown2)return{risk:"high",reason:dangerous?"delegated role can write, execute, publish, or recurse":"delegated role exposes non-read-only unknown capabilities",role,tools,safeReadOnly:!1};return{risk:"medium",reason:"delegated role is limited to registered read-only capabilities",role,tools,safeReadOnly:!0}}function classifyFullAutoToolAction(input){let tool=input.toolName?.toLowerCase()??"",config2=input.fullAutoConfig,mode=config2?.mode??"supervised";if(!(mode==="strict"||config2?.permission_policy?.enabled!==!1))return{action:"allow",reason:"permission policy disabled by config",tier:"local"};if(isReadOnlyTool(tool))return{action:"allow",reason:"read-only tool",tier:"safe"};if(tool==="execute"&&config2?.permission_policy?.trust_code_mode_wrapper===!0&&input.hostCodeModeWrapper===!0&&isSingleToolCallProgram(input.args?.code))return{action:"allow",reason:"OpenCode v2 Code Mode wrapper around a single tool call (operator-trusted) — the nested call is classified individually",tier:"local"};if(tool==="swarm_command"&&mode!=="strict"&&input.swarmCommandReadOnly===!0)return{action:"allow",reason:"swarm_command is on the explicit read-only allowlist and permitted by the tool policy",tier:"local"};if(isSubagentDelegation(tool,input.args)){let subagentName=typeof input.args?.subagent_type==="string"&&input.args.subagent_type||typeof input.args?.agent==="string"&&input.args.agent||"unknown",delegationRisk=resolveDelegationRisk(input,subagentName);if(mode!=="strict"&&delegationRisk.safeReadOnly)return{action:"allow",reason:`read-only subagent delegation allowed (${delegationRisk.role})`,tier:"local"};return{action:"escalate_critic",reason:`subagent delegation requires plan/scope verification (${delegationRisk.reason})`,risk:mode==="strict"?"high":delegationRisk.risk,context:{tool,subagent:subagentName,canonicalRole:delegationRisk.role,registeredTools:delegationRisk.tools,currentTaskID:input.currentTaskID,currentPhase:input.currentPhase}}}if(tool==="phase_complete")return{action:"escalate_critic",reason:"phase_complete requires Full-Auto approval evidence",risk:"high",context:{tool,currentPhase:input.currentPhase}};if(tool==="update_task_status"){let status=typeof input.args?.status==="string"&&input.args.status||"";if(status==="completed"){if(mode==="strict"||config2?.oversight?.on_task_completion===!0)return{action:"escalate_critic",reason:"task completion requires Full-Auto critic verification",risk:"medium",context:{tool,status}}}else{if(mode==="strict")return{action:"escalate_critic",reason:`strict mode: update_task_status with status=${status} requires critic verification`,risk:"medium",context:{tool,status}};return{action:"allow",reason:`update_task_status with status=${status} is a routine state change`,tier:"local"}}}if(tool==="save_plan")return{action:"escalate_critic",reason:"plan mutation requires Full-Auto critic verification",risk:"high",context:{tool}};if(NETWORK_TOOLS.has(tool)){let url2=extractURLArg(input.args);if(url2&&isTrustedDomain(url2,config2))return{action:"allow",reason:"network tool with trusted domain",tier:"local"};return{action:"escalate_critic",reason:"network/web tool — verify intent and target",risk:"medium",context:{tool,url:url2}}}if(SHELL_TOOLS.has(tool)){let command=extractCommandArg(input.args);if(!command)return{action:"deny",reason:"shell tool invoked without a command argument",code:"shell_no_command",recoverable:!0};let cmdRisk=classifyCommandRisk(command,input.workingDirectory??"",{directory:input.directory});if(cmdRisk.decision==="deny")return{action:"deny",reason:cmdRisk.reason,code:"shell_deny",recoverable:!0};if(cmdRisk.decision==="allow")return{action:"allow",reason:cmdRisk.reason,tier:"local"};return{action:"escalate_critic",reason:cmdRisk.reason,risk:"medium",context:{tool,command}}}if(isWriteLikeTool(tool)||tool==="patch"||tool==="edit"){let paths=extractPathArgs(tool,input.args);if(paths.length===0){if(new Set(["declare_scope","declare_council_criteria","submit_council_verdicts","submit_phase_council_verdicts","set_qa_gates","write_retro","write_drift_evidence","write_hallucination_evidence","write_mutation_evidence","knowledge_add","knowledge_remove","curator_analyze","consensus_mine"]).has(tool))return{action:"allow",reason:`pathless plan/evidence tool '${tool}' allowed under Full-Auto`,tier:"local"};return{action:"escalate_critic",reason:"write-like tool without explicit path — verify side effects",risk:"medium",context:{tool,args:input.args}}}for(let p of paths){let risk=classifyPathRisk(p,{directory:input.directory,declaredScope:input.declaredScope??null});if(!risk.withinProjectRoot)return{action:"deny",reason:`write target outside project root: ${p}`,code:"path_out_of_root",recoverable:!0};if(isProtectedPath2(path59.relative(input.directory,path59.resolve(input.directory,p)),config2))return{action:"escalate_critic",reason:`write to protected path requires critic approval: ${p}`,risk:"high",context:{tool,path:p}};if(risk.highRiskBuild)return{action:"escalate_critic",reason:`write to high-risk build/plugin path requires critic approval: ${p}`,risk:"high",context:{tool,path:p}};if(input.normalizedAgentName==="coder"&&Array.isArray(input.declaredScope)&&input.declaredScope.length>0&&risk.withinDeclaredScope===!1)return{action:"deny",reason:`coder write outside declared scope: ${p}`,code:"path_out_of_scope",recoverable:!0}}return{action:"allow",reason:"write within project root and declared scope",tier:"local"}}return{action:"escalate_critic",reason:`tool '${tool||"<empty>"}' not deterministically classifiable`,risk:"medium",context:{tool}}}function buildStructuredDenial(decision,tool){return{full_auto_denial:!0,tool,code:decision.code,reason:decision.reason,recoverable:decision.recoverable,guidance:decision.recoverable?"Choose a safer path: stay within the project root, respect declared scope, avoid destructive shell, and avoid protected paths. Consider declaring scope or escalating to a human.":"This action cannot be retried under Full-Auto. Ask a human to authorize it."}}var READ_ONLY_TOOLS,WRITE_LIKE_TOOLS,SHELL_TOOLS,NETWORK_TOOLS,SUBAGENT_TOOLS,HIGH_RISK_BUILD_PATHS,ALWAYS_PROTECTED_PREFIXES,PROTECTED_PATH_DEFAULTS,FULL_AUTO_SECRET_READ_PATTERN,FULL_AUTO_SECRET_ENV_PATTERN,FULL_AUTO_PRIMARY_PUSH_PATTERN,PATH_ARG_KEYS;var init_policy=__esm(()=>{init_constants();init_schema();init_config();init_normalize_tool_name();init_command_classifier();init_protected_path_policy();init_path();init_code_mode_program();READ_ONLY_TOOLS=new Set(["check_gate_status","completion_verify","evidence_check","get_approved_plan","get_qa_gate_profile","diff","diff_summary","imports","symbols","batch_symbols","search","repo_map","retrieve_summary","knowledge_recall","knowledge_query","co_change_analyzer","complexity_hotspots","detect_domains","lint","lint_spec","pkg_audit","placeholder_scan","pre_check_batch","quality_budget","sast_scan","sbom_generate","schema_drift","secretscan","syntax_check","test_impact","todo_extract","doc_scan","doc_extract","req_coverage","req_coverage".toLowerCase(),"read","glob","grep","list","ls","view"]),WRITE_LIKE_TOOLS=new Set([...WRITE_TOOL_NAMES,"multiedit","multi_edit","todo_write","save_plan","update_task_status","phase_complete","declare_scope","declare_council_criteria","submit_council_verdicts","submit_phase_council_verdicts","set_qa_gates","write_retro","write_drift_evidence","write_hallucination_evidence","write_mutation_evidence","knowledge_add","knowledge_remove","curator_analyze","consensus_mine","suggest_patch"]),SHELL_TOOLS=new Set(["bash","shell","exec","run"]),NETWORK_TOOLS=new Set(["web_search","webfetch","web_fetch","fetch","http","request","gitingest"]),SUBAGENT_TOOLS=new Set(["agent","delegate"]),HIGH_RISK_BUILD_PATHS=["src/index.ts","src/hooks/guardrails.ts","src/hooks/delegation-gate.ts","src/hooks/scope-guard.ts","src/hooks/full-auto-permission.ts","src/hooks/full-auto-intercept.ts","src/full-auto/","src/config/schema.ts","src/config/constants.ts","src/tools/phase-complete.ts","src/tools/index.ts","package.json","package-lock.json","bun.lock","biome.json","tsconfig.json","CHANGELOG.md",".release-please-manifest.json","release-please-config.json","dist/",".github/workflows/"],ALWAYS_PROTECTED_PREFIXES=[".git/",".git\\"],PROTECTED_PATH_DEFAULTS=[".git",".github/workflows",".opencode",".swarm","package.json","package-lock.json","bun.lock","CHANGELOG.md",".release-please-manifest.json","release-please-config.json"];FULL_AUTO_SECRET_READ_PATTERN=/\b(?:cat|head|tail|less|more)\s+[^\n]*(?:\.env|credentials|id_rsa|id_ed25519|\.pem|\.key)\b/i,FULL_AUTO_SECRET_ENV_PATTERN=/\bprintenv\b.*(?:SECRET|TOKEN|KEY|PASSWORD)/i,FULL_AUTO_PRIMARY_PUSH_PATTERN=/\bgit\s+push\s+(?:[^\s]+\s+)?(?:main|master|production|prod)\b/i;PATH_ARG_KEYS=["file_path","filepath","path","file","target","to","dest","destination","output_path"]});var exports_runtime={};__export(exports_runtime,{resolveGrammarsDir:()=>resolveGrammarsDir,parserCache:()=>parserCache,loadGrammar:()=>loadGrammar,isGrammarAvailable:()=>isGrammarAvailable,getSupportedLanguages:()=>getSupportedLanguages,getInitializedLanguages:()=>getInitializedLanguages,clearParserCache:()=>clearParserCache,_internals:()=>_internals57});import{existsSync as existsSync30,statSync as statSync19}from"node:fs";import*as path60 from"node:path";import{fileURLToPath as fileURLToPath2}from"node:url";import{Language,Parser as TreeSitterParser}from"web-tree-sitter";async function initTreeSitter(){if(!treeSitterInitPromise)treeSitterInitPromise=(async()=>{if(_internals57.getModuleDir().replace(/\\/g,"/").endsWith("/src/lang"))await _internals57.parserInit();else{let grammarsDir=getGrammarsDirAbsolute(),coreWasmPath=path60.join(grammarsDir,"tree-sitter.wasm");if(!_internals57.fileExists(coreWasmPath))throw Error(`Core tree-sitter WASM runtime missing: ${coreWasmPath}
|
|
709
709
|
The installed OpenCode plugin cache is incomplete or stale. Run 'bunx opencode-swarm update', then restart OpenCode so it fetches a fresh package from npm.`);await _internals57.parserInit({locateFile(scriptName){return path60.join(grammarsDir,scriptName)}})}})().catch((err)=>{throw treeSitterInitPromise=null,err});return treeSitterInitPromise}function sanitizeLanguageId(languageId){let normalized=languageId.toLowerCase();if(!/^[a-z0-9-]+$/.test(normalized))throw Error(`Invalid language ID: ${languageId}`);return normalized}function getWasmFileName(languageId){let sanitized=sanitizeLanguageId(languageId).toLowerCase();if(LANGUAGE_WASM_MAP[sanitized])return LANGUAGE_WASM_MAP[sanitized];return`tree-sitter-${sanitized}.wasm`}function resolveGrammarsDir(thisDir){let normalized=thisDir.replace(/\\/g,"/"),isSource=normalized.endsWith("/src/lang"),isCliBundle=normalized.endsWith("/cli");return isSource?path60.join(thisDir,"grammars"):isCliBundle?path60.join(thisDir,"..","lang","grammars"):path60.join(thisDir,"lang","grammars")}function getGrammarsDirAbsolute(){let thisDir=_internals57.getModuleDir();return resolveGrammarsDir(thisDir)}async function loadGrammar(languageId){if(typeof languageId!=="string"||languageId.length>100)throw Error("Invalid languageId: must be a string of at most 100 characters");let normalizedId=sanitizeLanguageId(languageId).toLowerCase();if(normalizedId.length===0)throw Error("Invalid languageId: empty after sanitization");if(parserCache.has(normalizedId))return parserCache.get(normalizedId);let existing=inflightLoads.get(normalizedId);if(existing)return existing;let loadPromise=(async()=>{await initTreeSitter();let parser=new TreeSitterParser,wasmFileName=getWasmFileName(normalizedId),wasmPath=path60.join(getGrammarsDirAbsolute(),wasmFileName);if(!_internals57.fileExists(wasmPath))throw Error(`Grammar file not found for ${languageId}: ${wasmPath}
|
|
@@ -1172,10 +1172,10 @@ in`);return tk},In(tk,iterable){if((iterable.behind(1)||tokens.mkToken("EMPTY"))
|
|
|
1172
1172
|
`)}};module.exports=()=>compose(filterNonNull,map3(tokens.applyTokenizerVisitor(SkipRepeatedNewLines)),lookahead)});var require_assignment_word=__commonJS((exports,module)=>{var map3=require_map_iterable(),isValidName=require_is_valid_name();module.exports=function(){return map3((tk,idx,ctx)=>{if(tk._.maybeStartOfSimpleCommand)ctx.commandPrefixNotAllowed=!1;if(!ctx.commandPrefixNotAllowed&&tk.is("WORD")&&tk.value.indexOf("=")>0&&isValidName(tk.value.slice(0,tk.value.indexOf("="))))return tk.changeTokenType("ASSIGNMENT_WORD",tk.value);return ctx.commandPrefixNotAllowed=!0,tk})}});var require_syntaxerror_oncontinue=__commonJS((exports,module)=>{var map3=require_map_iterable();module.exports=function(){return map3((tk)=>{if(tk&&tk.is("CONTINUE"))throw SyntaxError("Unclosed "+tk.value);return tk})}});var require_rules=__commonJS((exports)=>{exports.parameterExpansion=require_parameter_expansion();exports.commandExpansion=require_command_expansion();exports.arithmeticExpansion=require_arithmetic_expansion();exports.aliasSubstitution=require_alias_substitution2();exports.defaultNodeType=require_default_node_type();exports.fieldSplitting=require_field_splitting();exports.tildeExpanding=require_tilde_expanding();exports.pathExpansion=require_path_expansion();exports.quoteRemoval=require_quote_removal();exports.identifySimpleCommandNames=require_identify_simplecommand_names();exports.identifyMaybeSimpleCommands=require_identify_maybe_simple_commands();exports.operatorTokens=require_operator_tokens();exports.reservedWords=require_reserved_words();exports.separator=require_separator();exports.linebreakIn=require_linebreak_in();exports.forNameVariable=require_for_name_variable();exports.functionName=require_function_name();exports.ioNumber=require_io_number();exports.newLineList=require_new_line_list();exports.assignmentWord=require_assignment_word();exports.syntaxerrorOnContinue=require_syntaxerror_oncontinue()});var require_grammar=__commonJS((exports,module)=>{module.exports={start:"complete_command",bnf:{complete_command:[["list separator EOF"," return yy.checkAsync($list, $separator)"],["list EOF"," return $list "],["separator list EOF"," return $list "],["separator list separator EOF"," return yy.checkAsync($list, $separator)"]],list:[["list separator and_or","$$ = yy.listAppend($list, $and_or, $separator);"],["and_or","$$ = yy.list($and_or);"]],and_or:[["pipeline","$$ = $pipeline;"],["and_or AND_IF linebreak pipeline","$$ = yy.andAndOr($and_or, $pipeline);"],["and_or OR_IF linebreak pipeline","$$ = yy.orAndOr($and_or, $pipeline);"]],pipeline:[["pipe_sequence","$$ = yy.pipeLine($pipe_sequence);"],["Bang pipe_sequence","$$ = yy.bangPipeLine($pipe_sequence);"]],pipe_sequence:[["command","$$ = yy.pipeSequence($command);"],["pipe_sequence PIPE linebreak command","$$ = yy.pipeSequenceAppend($pipe_sequence, $command);"]],command:["simple_command","compound_command",["compound_command redirect_list","$$ = yy.addRedirections($compound_command, $redirect_list)"],"function_definition"],compound_command:["brace_group","subshell","for_clause","case_clause","if_clause","while_clause","until_clause"],subshell:[["OPEN_PAREN compound_list CLOSE_PAREN","$$ = yy.subshell($compound_list, $OPEN_PAREN.loc, $CLOSE_PAREN.loc);"]],compound_list:[["term","$$ = $term;"],["NEWLINE_LIST term","$$ = $term;"],["term separator","$$ = yy.checkAsync($term, $separator);"],["NEWLINE_LIST term separator","$$ = yy.checkAsync($term, $separator);"]],term:[["term separator and_or","$$ = yy.termAppend($term, $and_or, $separator);"],["and_or","$$ = yy.term($and_or);"]],for_clause:[["For name linebreak do_group","$$ = yy.forClauseDefault($name, $do_group, $For.loc);"],["For name LINEBREAK_IN separator do_group","$$ = yy.forClauseDefault($name, $do_group, $For.loc);"],["For name In separator do_group","$$ = yy.forClauseDefault($name, $do_group, $For.loc);"],["For name in wordlist separator do_group","$$ = yy.forClause($name, $wordlist, $do_group, $For.loc);"]],name:["NAME"],in:["In"],wordlist:["wordlist_repetition_plus0"],case_clause:[["Case WORD linebreak in linebreak case_list Esac","$$ = yy.caseClause($WORD, $case_list, $Case.loc, $Esac.loc);"],["Case WORD linebreak in linebreak case_list_ns Esac","$$ = yy.caseClause($WORD, $case_list_ns, $Case.loc, $Esac.loc);"],["Case WORD linebreak in linebreak Esac","$$ = yy.caseClause($WORD, null, $Case.loc, $Esac.loc);"]],case_list_ns:[["case_list case_item_ns","$$ = yy.caseListAppend($case_list, $case_item_ns);"],["case_item_ns","$$ = yy.caseList($case_item_ns);"]],case_list:[["case_list case_item","$$ = yy.caseListAppend($case_list, $case_item);"],["case_item","$$ = yy.caseList($case_item);"]],case_item_ns:[["pattern CLOSE_PAREN linebreak","$$ = yy.caseItem($pattern, null, $pattern[0].loc, $CLOSE_PAREN.loc);"],["pattern CLOSE_PAREN compound_list linebreak","$$ = yy.caseItem($pattern, $compound_list, $pattern[0].loc, $compound_list.loc);"],["OPEN_PAREN pattern CLOSE_PAREN linebreak","$$ = yy.caseItem($pattern, null, $OPEN_PAREN.loc, $CLOSE_PAREN.loc );"],["OPEN_PAREN pattern CLOSE_PAREN compound_list linebreak","$$ = yy.caseItem($pattern, $compound_list, $OPEN_PAREN.loc, $compound_list.loc);"]],case_item:[["pattern CLOSE_PAREN linebreak DSEMI linebreak","$$ = yy.caseItem($pattern, null, $pattern[0].loc, $DSEMI.loc);"],["pattern CLOSE_PAREN compound_list DSEMI linebreak","$$ = yy.caseItem($pattern, $compound_list, $pattern[0].loc, $DSEMI.loc);"],["OPEN_PAREN pattern CLOSE_PAREN linebreak DSEMI linebreak","$$ = yy.caseItem($pattern, null, $OPEN_PAREN.loc, $DSEMI.loc );"],["OPEN_PAREN pattern CLOSE_PAREN compound_list DSEMI linebreak","$$ = yy.caseItem($pattern, $compound_list, $OPEN_PAREN.loc, $DSEMI.loc);"]],pattern:[["WORD","$$ = yy.pattern($WORD);"],["pattern PIPE WORD","$$ = yy.patternAppend($pattern, $WORD);"]],if_clause:[["If compound_list Then compound_list else_part Fi","$$ = yy.ifClause($2, $4, $else_part, $If.loc, $Fi.loc);"],["If compound_list Then compound_list Fi","$$ = yy.ifClause($2, $4, null, $If.loc, $Fi.loc);"]],else_part:[["Elif compound_list Then compound_list","$$ = yy.ifClause($2, $4, null, $Elif.loc, $4.loc);"],["Elif compound_list Then compound_list else_part","$$ = yy.ifClause($2, $4, $else_part, $Elif.loc, $else_part.loc);"],["Else compound_list","$$ = yy.elseClause($compound_list, $Else);"]],while_clause:[["While compound_list do_group","$$ = yy.while($2, $3, $While);"]],until_clause:[["Until compound_list do_group","$$ = yy.until($2, $3, $Until);"]],function_definition:[["fname OPEN_PAREN CLOSE_PAREN linebreak function_body","$$ = yy.functionDefinition($fname, $function_body);"]],function_body:[["compound_command","$$ = [$compound_command, null];"],["compound_command redirect_list","$$ = [$compound_command, $redirect_list];"]],fname:["NAME"],brace_group:[["Lbrace compound_list Rbrace","$$ = yy.braceGroup($compound_list, $Lbrace.loc, $Rbrace.loc);"]],do_group:[["Do compound_list Done","$$ = yy.doGroup($compound_list, $Do.loc, $Done.loc);"]],simple_command:[["cmd_prefix cmd_word cmd_suffix","$$ =yy.command($cmd_prefix, $cmd_word, $cmd_suffix);"],["cmd_prefix cmd_word","$$ =yy.command($cmd_prefix, $cmd_word, null);"],["cmd_prefix","$$ =yy.commandAssignment($cmd_prefix);"],["cmd_name cmd_suffix","$$ =yy.command(null, $cmd_name, $cmd_suffix);"],["cmd_name","$$ =yy.command(null, $cmd_name);"]],cmd_name:[["WORD","$$ =yy.commandName(yytext) /* Apply rule 7a */;"]],cmd_word:[["WORD","$$ = yytext\t/* Apply rule 7B */;"]],cmd_prefix:[["io_redirect","$$ = yy.prefix($io_redirect);"],["cmd_prefix io_redirect","$$ = yy.prefixAppend($1, $2);"],["ASSIGNMENT_WORD","$$ = yy.prefix($1);"],["cmd_prefix ASSIGNMENT_WORD","$$ = yy.prefixAppend($1, $2);"]],cmd_suffix:[["io_redirect","$$ = yy.suffix($io_redirect);"],["cmd_suffix io_redirect","$$ = yy.suffixAppend($cmd_suffix, $io_redirect);"],["WORD","$$ = yy.suffix($1);"],["cmd_suffix WORD","$$ = yy.suffixAppend($cmd_suffix, $2);"]],redirect_list:[["io_redirect","$$ = [$io_redirect];"],["redirect_list io_redirect","$$ = $redirect_list.concat($io_redirect);"]],io_redirect:[["io_file","$$ = $io_file;"],["IO_NUMBER io_file","$$ = yy.numberIoRedirect($io_file, $1);"],"io_here","IO_NUMBER io_here"],io_file:[["LESS filename","$$ =yy.ioRedirect($1, $filename);"],["LESSAND filename","$$ =yy.ioRedirect($1, $filename);"],["GREAT filename","$$ =yy.ioRedirect($1, $filename);"],["GREATAND filename","$$ =yy.ioRedirect($1, $filename);"],["DGREAT filename","$$ =yy.ioRedirect($1, $filename);"],["LESSGREAT filename","$$ =yy.ioRedirect($1, $filename);"],["CLOBBER filename","$$ =yy.ioRedirect($1, $filename);"]],filename:["WORD"],io_here:["DLESS here_end","DLESSDASH here_end"],here_end:["WORD"],linebreak:["NEWLINE_LIST",""],separator:["SEPARATOR_OP","NEWLINE_LIST"],wordlist_repetition_plus0:[["WORD","$$ = [$1];"],["wordlist_repetition_plus0 WORD","$1.push($2);"]]}}});var require_io_file_operators=__commonJS((exports,module)=>{var ioFileOperators=module.exports=["LESS","DLESS","DGREAT","LESSAND","GREATAND","GREAT","LESSGREAT","CLOBBER"];ioFileOperators.isOperator=function(tk){for(let op of ioFileOperators)if(tk.type===op)return!0;return!1}});var require_parameter_operators=__commonJS((exports,module)=>{var parameterOps={["^([a-zA-Z_][a-zA-Z0-9_]*):\\-(.*)$"]:{op:"useDefaultValue",parameter:(m)=>m[1],word:(m)=>m[2],expand:["word"]},["^([a-zA-Z_][a-zA-Z0-9_]*):\\=(.*)$"]:{op:"assignDefaultValue",parameter:(m)=>m[1],word:(m)=>m[2],expand:["word"]},["^([a-zA-Z_][a-zA-Z0-9_]*):\\?(.*)$"]:{op:"indicateErrorIfNull",parameter:(m)=>m[1],word:(m)=>m[2],expand:["word"]},["^([a-zA-Z_][a-zA-Z0-9_]*):\\+(.*)$"]:{op:"useAlternativeValue",parameter:(m)=>m[1],word:(m)=>m[2],expand:["word"]},["^([a-zA-Z_][a-zA-Z0-9_]*)\\-(.*)$"]:{op:"useDefaultValueIfUnset",parameter:(m)=>m[1],word:(m)=>m[2],expand:["word"]},["^([a-zA-Z_][a-zA-Z0-9_]*)\\=(.*)$"]:{op:"assignDefaultValueIfUnset",parameter:(m)=>m[1],word:(m)=>m[2],expand:["word"]},["^([a-zA-Z_][a-zA-Z0-9_]*)\\?(.*)$"]:{op:"indicateErrorIfUnset",parameter:(m)=>m[1],word:(m)=>m[2],expand:["word"]},["^([a-zA-Z_][a-zA-Z0-9_]*)\\+(.*)$"]:{op:"useAlternativeValueIfUnset",parameter:(m)=>m[1],word:(m)=>m[2],expand:["word"]},["^([a-zA-Z_][a-zA-Z0-9_]*)\\%\\%(.*)$"]:{op:"removeLargestSuffixPattern",parameter:(m)=>m[1],word:(m)=>m[2],expand:["word"]},["^([a-zA-Z_][a-zA-Z0-9_]*)\\#\\#(.*)$"]:{op:"removeLargestPrefixPattern",parameter:(m)=>m[1],word:(m)=>m[2],expand:["word"]},["^([a-zA-Z_][a-zA-Z0-9_]*)\\%(.*)$"]:{op:"removeSmallestSuffixPattern",parameter:(m)=>m[1],word:(m)=>m[2],expand:["word"]},["^([a-zA-Z_][a-zA-Z0-9_]*)\\#(.*)$"]:{op:"removeSmallestPrefixPattern",parameter:(m)=>m[1],word:(m)=>m[2],expand:["word"]},["^\\#([a-zA-Z_][a-zA-Z0-9_]*)$"]:{op:"stringLength",parameter:(m)=>m[1]},["^([1-9][0-9]*)$"]:{kind:"positional",parameter:(m)=>Number(m[1])},"^!$":{kind:"last-background-pid"},"^\\@$":{kind:"positional-list"},"^\\-$":{kind:"current-option-flags"},"^\\#$":{kind:"positional-count"},"^\\?$":{kind:"last-exit-status"},"^\\*$":{kind:"positional-string"},"^\\$$":{kind:"shell-process-id"},"^0$":{kind:"shell-script-name"}};module.exports=parameterOps});var require_reserved_words2=__commonJS((exports,module)=>{module.exports={if:"If",then:"Then",else:"Else",elif:"Elif",fi:"Fi",do:"Do",done:"Done",case:"Case",esac:"Esac",while:"While",until:"Until",for:"For",in:"In","{":"Lbrace","}":"Rbrace","!":"Bang"}});var require_enums=__commonJS((exports)=>{exports.IOFileOperators=require_io_file_operators();exports.operators=require_operators();exports.parameterOperators=require_parameter_operators();exports.reservedWords=require_reserved_words2()});var require_built_grammar=__commonJS((exports,module)=>{var parser=function(){var o=function(k,v,o2,l){for(o2=o2||{},l=k.length;l--;o2[k[l]]=v);return o2},$V0=[1,9],$V1=[1,28],$V2=[1,6],$V3=[1,29],$V4=[1,34],$V5=[1,30],$V6=[1,26],$V7=[1,31],$V8=[1,32],$V9=[1,33],$Va=[1,27],$Vb=[1,25],$Vc=[1,36],$Vd=[1,38],$Ve=[1,39],$Vf=[1,40],$Vg=[1,41],$Vh=[1,42],$Vi=[1,43],$Vj=[1,44],$Vk=[1,45],$Vl=[1,46],$Vm=[1,5],$Vn=[6,31,84],$Vo=[1,50],$Vp=[1,51],$Vq=[6,13,27,29,31,32,39,41,42,44,49,50,51,53,54,55,56,57,60,61,62,63,69,71,73,75,76,77,78,79,80,81,83],$Vr=[6,9,11,29,31,44,49,51,53,54,55,61,62,63,84],$Vs=[1,52],$Vt=[6,9,11,15,29,31,44,49,51,53,54,55,61,62,63,84],$Vu=[1,62],$Vv=[6,9,11,15,29,31,44,49,51,53,54,55,61,62,63,71,73,75,76,77,78,79,80,81,83,84],$Vw=[6,9,11,15,29,31,42,44,49,51,53,54,55,61,62,63,69,71,73,75,76,77,78,79,80,81,83,84],$Vx=[6,9,11,15,29,31,42,44,49,51,53,54,55,61,62,63,71,73,75,76,77,78,79,80,81,83,84],$Vy=[1,66],$Vz=[1,78],$VA=[1,86],$VB=[13,27,32,39,41,42,50,56,57,60,69,71,73,75,76,77,78,79,80,81,83],$VC=[2,102],$VD=[1,93],$VE=[1,99],$VF=[29,44,49,51,53,54,55,61,62,63],$VG=[29,31,44,49,51,53,54,55,61,62,63,84],$VH=[1,112],$VI=[2,101],$VJ=[29,31,44,49,51,53,54,55,61,62,63],$VK=[2,37],$VL=[31,42,84],$VM=[27,42,44],$VN=[1,140],$VO=[1,141],$VP=[1,151],$VQ=[1,152],$VR=[1,161],$VS=[15,29],$VT=[44,49],$VU=[1,166],parser2={trace:function(){},yy:{},symbols_:{error:2,complete_command:3,list:4,separator:5,EOF:6,and_or:7,pipeline:8,AND_IF:9,linebreak:10,OR_IF:11,pipe_sequence:12,Bang:13,command:14,PIPE:15,simple_command:16,compound_command:17,redirect_list:18,function_definition:19,brace_group:20,subshell:21,for_clause:22,case_clause:23,if_clause:24,while_clause:25,until_clause:26,OPEN_PAREN:27,compound_list:28,CLOSE_PAREN:29,term:30,NEWLINE_LIST:31,For:32,name:33,do_group:34,LINEBREAK_IN:35,In:36,in:37,wordlist:38,NAME:39,wordlist_repetition_plus0:40,Case:41,WORD:42,case_list:43,Esac:44,case_list_ns:45,case_item_ns:46,case_item:47,pattern:48,DSEMI:49,If:50,Then:51,else_part:52,Fi:53,Elif:54,Else:55,While:56,Until:57,fname:58,function_body:59,Lbrace:60,Rbrace:61,Do:62,Done:63,cmd_prefix:64,cmd_word:65,cmd_suffix:66,cmd_name:67,io_redirect:68,ASSIGNMENT_WORD:69,io_file:70,IO_NUMBER:71,io_here:72,LESS:73,filename:74,LESSAND:75,GREAT:76,GREATAND:77,DGREAT:78,LESSGREAT:79,CLOBBER:80,DLESS:81,here_end:82,DLESSDASH:83,SEPARATOR_OP:84,$accept:0,$end:1},terminals_:{2:"error",6:"EOF",9:"AND_IF",11:"OR_IF",13:"Bang",15:"PIPE",27:"OPEN_PAREN",29:"CLOSE_PAREN",31:"NEWLINE_LIST",32:"For",35:"LINEBREAK_IN",36:"In",39:"NAME",41:"Case",42:"WORD",44:"Esac",49:"DSEMI",50:"If",51:"Then",53:"Fi",54:"Elif",55:"Else",56:"While",57:"Until",60:"Lbrace",61:"Rbrace",62:"Do",63:"Done",69:"ASSIGNMENT_WORD",71:"IO_NUMBER",73:"LESS",75:"LESSAND",76:"GREAT",77:"GREATAND",78:"DGREAT",79:"LESSGREAT",80:"CLOBBER",81:"DLESS",83:"DLESSDASH",84:"SEPARATOR_OP"},productions_:[0,[3,3],[3,2],[3,3],[3,4],[4,3],[4,1],[7,1],[7,4],[7,4],[8,1],[8,2],[12,1],[12,4],[14,1],[14,1],[14,2],[14,1],[17,1],[17,1],[17,1],[17,1],[17,1],[17,1],[17,1],[21,3],[28,1],[28,2],[28,2],[28,3],[30,3],[30,1],[22,4],[22,5],[22,5],[22,6],[33,1],[37,1],[38,1],[23,7],[23,7],[23,6],[45,2],[45,1],[43,2],[43,1],[46,3],[46,4],[46,4],[46,5],[47,5],[47,5],[47,6],[47,6],[48,1],[48,3],[24,6],[24,5],[52,4],[52,5],[52,2],[25,3],[26,3],[19,5],[59,1],[59,2],[58,1],[20,3],[34,3],[16,3],[16,2],[16,1],[16,2],[16,1],[67,1],[65,1],[64,1],[64,2],[64,1],[64,2],[66,1],[66,2],[66,1],[66,2],[18,1],[18,2],[68,1],[68,2],[68,1],[68,2],[70,2],[70,2],[70,2],[70,2],[70,2],[70,2],[70,2],[74,1],[72,2],[72,2],[82,1],[10,1],[10,0],[5,1],[5,1],[40,1],[40,2]],performAction:function(yytext,yyleng,yylineno,yy,yystate,$$,_$){var $0=$$.length-1;switch(yystate){case 1:return yy.checkAsync($$[$0-2],$$[$0-1]);case 2:case 3:return $$[$0-1];case 4:return yy.checkAsync($$[$0-2],$$[$0-3]);case 5:this.$=yy.listAppend($$[$0-2],$$[$0],$$[$0-1]);break;case 6:this.$=yy.list($$[$0]);break;case 7:case 26:case 27:case 86:this.$=$$[$0];break;case 8:this.$=yy.andAndOr($$[$0-3],$$[$0]);break;case 9:this.$=yy.orAndOr($$[$0-3],$$[$0]);break;case 10:this.$=yy.pipeLine($$[$0]);break;case 11:this.$=yy.bangPipeLine($$[$0]);break;case 12:this.$=yy.pipeSequence($$[$0]);break;case 13:this.$=yy.pipeSequenceAppend($$[$0-3],$$[$0]);break;case 16:this.$=yy.addRedirections($$[$0-1],$$[$0]);break;case 25:this.$=yy.subshell($$[$0-1],$$[$0-2].loc,$$[$0].loc);break;case 28:case 29:this.$=yy.checkAsync($$[$0-1],$$[$0]);break;case 30:this.$=yy.termAppend($$[$0-2],$$[$0],$$[$0-1]);break;case 31:this.$=yy.term($$[$0]);break;case 32:this.$=yy.forClauseDefault($$[$0-2],$$[$0],$$[$0-3].loc);break;case 33:case 34:this.$=yy.forClauseDefault($$[$0-3],$$[$0],$$[$0-4].loc);break;case 35:this.$=yy.forClause($$[$0-4],$$[$0-2],$$[$0],$$[$0-5].loc);break;case 39:case 40:this.$=yy.caseClause($$[$0-5],$$[$0-1],$$[$0-6].loc,$$[$0].loc);break;case 41:this.$=yy.caseClause($$[$0-4],null,$$[$0-5].loc,$$[$0].loc);break;case 42:case 44:this.$=yy.caseListAppend($$[$0-1],$$[$0]);break;case 43:case 45:this.$=yy.caseList($$[$0]);break;case 46:this.$=yy.caseItem($$[$0-2],null,$$[$0-2][0].loc,$$[$0-1].loc);break;case 47:this.$=yy.caseItem($$[$0-3],$$[$0-1],$$[$0-3][0].loc,$$[$0-1].loc);break;case 48:this.$=yy.caseItem($$[$0-2],null,$$[$0-3].loc,$$[$0-1].loc);break;case 49:this.$=yy.caseItem($$[$0-3],$$[$0-1],$$[$0-4].loc,$$[$0-1].loc);break;case 50:this.$=yy.caseItem($$[$0-4],null,$$[$0-4][0].loc,$$[$0-1].loc);break;case 51:this.$=yy.caseItem($$[$0-4],$$[$0-2],$$[$0-4][0].loc,$$[$0-1].loc);break;case 52:this.$=yy.caseItem($$[$0-4],null,$$[$0-5].loc,$$[$0-1].loc);break;case 53:this.$=yy.caseItem($$[$0-4],$$[$0-2],$$[$0-5].loc,$$[$0-1].loc);break;case 54:this.$=yy.pattern($$[$0]);break;case 55:this.$=yy.patternAppend($$[$0-2],$$[$0]);break;case 56:this.$=yy.ifClause($$[$0-4],$$[$0-2],$$[$0-1],$$[$0-5].loc,$$[$0].loc);break;case 57:this.$=yy.ifClause($$[$0-3],$$[$0-1],null,$$[$0-4].loc,$$[$0].loc);break;case 58:this.$=yy.ifClause($$[$0-2],$$[$0],null,$$[$0-3].loc,$$[$0].loc);break;case 59:this.$=yy.ifClause($$[$0-3],$$[$0-1],$$[$0],$$[$0-4].loc,$$[$0].loc);break;case 60:this.$=yy.elseClause($$[$0],$$[$0-1]);break;case 61:this.$=yy.while($$[$0-1],$$[$0],$$[$0-2]);break;case 62:this.$=yy.until($$[$0-1],$$[$0],$$[$0-2]);break;case 63:this.$=yy.functionDefinition($$[$0-4],$$[$0]);break;case 64:this.$=[$$[$0],null];break;case 65:this.$=[$$[$0-1],$$[$0]];break;case 67:this.$=yy.braceGroup($$[$0-1],$$[$0-2].loc,$$[$0].loc);break;case 68:this.$=yy.doGroup($$[$0-1],$$[$0-2].loc,$$[$0].loc);break;case 69:this.$=yy.command($$[$0-2],$$[$0-1],$$[$0]);break;case 70:this.$=yy.command($$[$0-1],$$[$0],null);break;case 71:this.$=yy.commandAssignment($$[$0]);break;case 72:this.$=yy.command(null,$$[$0-1],$$[$0]);break;case 73:this.$=yy.command(null,$$[$0]);break;case 74:this.$=yy.commandName(yytext);break;case 75:this.$=yytext;break;case 76:case 78:this.$=yy.prefix($$[$0]);break;case 77:case 79:this.$=yy.prefixAppend($$[$0-1],$$[$0]);break;case 80:case 82:this.$=yy.suffix($$[$0]);break;case 81:case 83:this.$=yy.suffixAppend($$[$0-1],$$[$0]);break;case 84:case 105:this.$=[$$[$0]];break;case 85:this.$=$$[$0-1].concat($$[$0]);break;case 87:this.$=yy.numberIoRedirect($$[$0],$$[$0-1]);break;case 90:case 91:case 92:case 93:case 94:case 95:case 96:this.$=yy.ioRedirect($$[$0-1],$$[$0]);break;case 106:$$[$0-1].push($$[$0]);break}},table:[{3:1,4:2,5:3,7:4,8:7,12:8,13:$V0,14:10,16:11,17:12,19:13,20:16,21:17,22:18,23:19,24:20,25:21,26:22,27:$V1,31:$V2,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,58:23,60:$Va,64:14,67:15,68:24,69:$Vb,70:35,71:$Vc,72:37,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl,84:$Vm},{1:[3]},{5:47,6:[1,48],31:$V2,84:$Vm},{4:49,7:4,8:7,12:8,13:$V0,14:10,16:11,17:12,19:13,20:16,21:17,22:18,23:19,24:20,25:21,26:22,27:$V1,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,58:23,60:$Va,64:14,67:15,68:24,69:$Vb,70:35,71:$Vc,72:37,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl},o($Vn,[2,6],{9:$Vo,11:$Vp}),o($Vq,[2,103]),o($Vq,[2,104]),o($Vr,[2,7]),o($Vr,[2,10],{15:$Vs}),{12:53,14:10,16:11,17:12,19:13,20:16,21:17,22:18,23:19,24:20,25:21,26:22,27:$V1,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,58:23,60:$Va,64:14,67:15,68:24,69:$Vb,70:35,71:$Vc,72:37,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl},o($Vt,[2,12]),o($Vt,[2,14]),o($Vt,[2,15],{70:35,72:37,18:54,68:55,71:$Vc,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl}),o($Vt,[2,17]),o($Vt,[2,71],{70:35,72:37,65:56,68:57,42:[1,59],69:[1,58],71:$Vc,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl}),o($Vt,[2,73],{70:35,72:37,66:60,68:61,42:$Vu,71:$Vc,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl}),o($Vv,[2,18]),o($Vv,[2,19]),o($Vv,[2,20]),o($Vv,[2,21]),o($Vv,[2,22]),o($Vv,[2,23]),o($Vv,[2,24]),{27:[1,63]},o($Vw,[2,76]),o($Vw,[2,78]),o($Vx,[2,74]),{7:67,8:7,12:8,13:$V0,14:10,16:11,17:12,19:13,20:16,21:17,22:18,23:19,24:20,25:21,26:22,27:$V1,28:64,30:65,31:$Vy,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,58:23,60:$Va,64:14,67:15,68:24,69:$Vb,70:35,71:$Vc,72:37,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl},{7:67,8:7,12:8,13:$V0,14:10,16:11,17:12,19:13,20:16,21:17,22:18,23:19,24:20,25:21,26:22,27:$V1,28:68,30:65,31:$Vy,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,58:23,60:$Va,64:14,67:15,68:24,69:$Vb,70:35,71:$Vc,72:37,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl},{33:69,39:[1,70]},{42:[1,71]},{7:67,8:7,12:8,13:$V0,14:10,16:11,17:12,19:13,20:16,21:17,22:18,23:19,24:20,25:21,26:22,27:$V1,28:72,30:65,31:$Vy,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,58:23,60:$Va,64:14,67:15,68:24,69:$Vb,70:35,71:$Vc,72:37,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl},{7:67,8:7,12:8,13:$V0,14:10,16:11,17:12,19:13,20:16,21:17,22:18,23:19,24:20,25:21,26:22,27:$V1,28:73,30:65,31:$Vy,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,58:23,60:$Va,64:14,67:15,68:24,69:$Vb,70:35,71:$Vc,72:37,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl},{7:67,8:7,12:8,13:$V0,14:10,16:11,17:12,19:13,20:16,21:17,22:18,23:19,24:20,25:21,26:22,27:$V1,28:74,30:65,31:$Vy,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,58:23,60:$Va,64:14,67:15,68:24,69:$Vb,70:35,71:$Vc,72:37,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl},{27:[2,66]},o($Vw,[2,86]),{70:75,72:76,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl},o($Vw,[2,88]),{42:$Vz,74:77},{42:$Vz,74:79},{42:$Vz,74:80},{42:$Vz,74:81},{42:$Vz,74:82},{42:$Vz,74:83},{42:$Vz,74:84},{42:$VA,82:85},{42:$VA,82:87},{6:[1,88],7:89,8:7,12:8,13:$V0,14:10,16:11,17:12,19:13,20:16,21:17,22:18,23:19,24:20,25:21,26:22,27:$V1,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,58:23,60:$Va,64:14,67:15,68:24,69:$Vb,70:35,71:$Vc,72:37,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl},{1:[2,2]},{5:91,6:[1,90],31:$V2,84:$Vm},o($VB,$VC,{10:92,31:$VD}),o($VB,$VC,{10:94,31:$VD}),o([27,32,39,41,42,50,56,57,60,69,71,73,75,76,77,78,79,80,81,83],$VC,{10:95,31:$VD}),o($Vr,[2,11],{15:$Vs}),o($Vt,[2,16],{70:35,72:37,68:96,71:$Vc,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl}),o($Vv,[2,84]),o($Vt,[2,70],{70:35,72:37,68:61,66:97,42:$Vu,71:$Vc,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl}),o($Vw,[2,77]),o($Vw,[2,79]),o($Vx,[2,75]),o($Vt,[2,72],{70:35,72:37,68:98,42:$VE,71:$Vc,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl}),o($Vx,[2,80]),o($Vx,[2,82]),{29:[1,100]},{61:[1,101]},o($VF,[2,26],{5:102,31:$V2,84:$Vm}),{7:67,8:7,12:8,13:$V0,14:10,16:11,17:12,19:13,20:16,21:17,22:18,23:19,24:20,25:21,26:22,27:$V1,30:103,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,58:23,60:$Va,64:14,67:15,68:24,69:$Vb,70:35,71:$Vc,72:37,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl},o($VG,[2,31],{9:$Vo,11:$Vp}),{29:[1,104]},{10:105,31:$VD,35:[1,106],36:[1,107],37:108,62:$VC},o([31,35,36,62],[2,36]),{10:109,31:$VD,36:$VC},{51:[1,110]},{34:111,62:$VH},{34:113,62:$VH},o($Vw,[2,87]),o($Vw,[2,89]),o($Vw,[2,90]),o($Vw,[2,97]),o($Vw,[2,91]),o($Vw,[2,92]),o($Vw,[2,93]),o($Vw,[2,94]),o($Vw,[2,95]),o($Vw,[2,96]),o($Vw,[2,98]),o($Vw,[2,100]),o($Vw,[2,99]),{1:[2,1]},o($Vn,[2,5],{9:$Vo,11:$Vp}),{1:[2,3]},{6:[1,114],7:89,8:7,12:8,13:$V0,14:10,16:11,17:12,19:13,20:16,21:17,22:18,23:19,24:20,25:21,26:22,27:$V1,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,58:23,60:$Va,64:14,67:15,68:24,69:$Vb,70:35,71:$Vc,72:37,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl},{8:115,12:8,13:$V0,14:10,16:11,17:12,19:13,20:16,21:17,22:18,23:19,24:20,25:21,26:22,27:$V1,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,58:23,60:$Va,64:14,67:15,68:24,69:$Vb,70:35,71:$Vc,72:37,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl},o([13,27,32,36,39,41,42,44,50,56,57,60,62,69,71,73,75,76,77,78,79,80,81,83],$VI),{8:116,12:8,13:$V0,14:10,16:11,17:12,19:13,20:16,21:17,22:18,23:19,24:20,25:21,26:22,27:$V1,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,58:23,60:$Va,64:14,67:15,68:24,69:$Vb,70:35,71:$Vc,72:37,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl},{14:117,16:11,17:12,19:13,20:16,21:17,22:18,23:19,24:20,25:21,26:22,27:$V1,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,58:23,60:$Va,64:14,67:15,68:24,69:$Vb,70:35,71:$Vc,72:37,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl},o($Vv,[2,85]),o($Vt,[2,69],{70:35,72:37,68:98,42:$VE,71:$Vc,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl}),o($Vx,[2,81]),o($Vx,[2,83]),o([27,32,41,50,56,57,60],$VC,{10:118,31:$VD}),o($Vv,[2,67]),o($VJ,[2,28],{8:7,12:8,14:10,16:11,17:12,19:13,64:14,67:15,20:16,21:17,22:18,23:19,24:20,25:21,26:22,58:23,68:24,70:35,72:37,7:119,13:$V0,27:$V1,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,60:$Va,69:$Vb,71:$Vc,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl}),o($VF,[2,27],{5:120,31:$V2,84:$Vm}),o($Vv,[2,25]),{34:121,62:$VH},{5:122,31:$V2,84:$Vm},{5:123,31:$V2,42:$VK,84:$Vm},{38:124,40:125,42:[1,126]},{36:[1,128],37:127},{7:67,8:7,12:8,13:$V0,14:10,16:11,17:12,19:13,20:16,21:17,22:18,23:19,24:20,25:21,26:22,27:$V1,28:129,30:65,31:$Vy,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,58:23,60:$Va,64:14,67:15,68:24,69:$Vb,70:35,71:$Vc,72:37,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl},o($Vv,[2,61]),{7:67,8:7,12:8,13:$V0,14:10,16:11,17:12,19:13,20:16,21:17,22:18,23:19,24:20,25:21,26:22,27:$V1,28:130,30:65,31:$Vy,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,58:23,60:$Va,64:14,67:15,68:24,69:$Vb,70:35,71:$Vc,72:37,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl},o($Vv,[2,62]),{1:[2,4]},o($Vr,[2,8]),o($Vr,[2,9]),o($Vt,[2,13]),{17:132,20:16,21:17,22:18,23:19,24:20,25:21,26:22,27:$V1,32:$V3,41:$V5,50:$V7,56:$V8,57:$V9,59:131,60:$Va},o($VG,[2,30],{9:$Vo,11:$Vp}),o($VJ,[2,29],{8:7,12:8,14:10,16:11,17:12,19:13,64:14,67:15,20:16,21:17,22:18,23:19,24:20,25:21,26:22,58:23,68:24,70:35,72:37,7:119,13:$V0,27:$V1,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,60:$Va,69:$Vb,71:$Vc,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl}),o($Vv,[2,32]),{34:133,62:$VH},{34:134,62:$VH},{5:135,31:$V2,84:$Vm},o([31,84],[2,38],{42:[1,136]}),o($VL,[2,105]),o($VM,$VC,{10:137,31:$VD}),o([27,31,42,44],$VK),{52:138,53:[1,139],54:$VN,55:$VO},{63:[1,142]},o($Vt,[2,63]),o($Vt,[2,64],{70:35,72:37,68:55,18:143,71:$Vc,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl}),o($Vv,[2,33]),o($Vv,[2,34]),{34:144,62:$VH},o($VL,[2,106]),{27:$VP,42:$VQ,43:145,44:[1,147],45:146,46:149,47:148,48:150},{53:[1,153]},o($Vv,[2,57]),{7:67,8:7,12:8,13:$V0,14:10,16:11,17:12,19:13,20:16,21:17,22:18,23:19,24:20,25:21,26:22,27:$V1,28:154,30:65,31:$Vy,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,58:23,60:$Va,64:14,67:15,68:24,69:$Vb,70:35,71:$Vc,72:37,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl},{7:67,8:7,12:8,13:$V0,14:10,16:11,17:12,19:13,20:16,21:17,22:18,23:19,24:20,25:21,26:22,27:$V1,28:155,30:65,31:$Vy,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,58:23,60:$Va,64:14,67:15,68:24,69:$Vb,70:35,71:$Vc,72:37,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl},o($Vv,[2,68]),o($Vt,[2,65],{70:35,72:37,68:96,71:$Vc,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl}),o($Vv,[2,35]),{27:$VP,42:$VQ,44:[1,156],46:158,47:157,48:150},{44:[1,159]},o($Vv,[2,41]),o($VM,[2,45]),{44:[2,43]},{15:$VR,29:[1,160]},{42:$VQ,48:162},o($VS,[2,54]),o($Vv,[2,56]),{51:[1,163]},{53:[2,60]},o($Vv,[2,39]),o($VM,[2,44]),{44:[2,42]},o($Vv,[2,40]),o($VT,$VC,{8:7,12:8,14:10,16:11,17:12,19:13,64:14,67:15,20:16,21:17,22:18,23:19,24:20,25:21,26:22,58:23,68:24,70:35,72:37,30:65,7:67,10:164,28:165,13:$V0,27:$V1,31:$VU,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,60:$Va,69:$Vb,71:$Vc,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl}),{42:[1,167]},{15:$VR,29:[1,168]},{7:67,8:7,12:8,13:$V0,14:10,16:11,17:12,19:13,20:16,21:17,22:18,23:19,24:20,25:21,26:22,27:$V1,28:169,30:65,31:$Vy,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,58:23,60:$Va,64:14,67:15,68:24,69:$Vb,70:35,71:$Vc,72:37,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl},{44:[2,46],49:[1,170]},{10:172,31:$VD,44:$VC,49:[1,171]},o($VT,$VI,{8:7,12:8,14:10,16:11,17:12,19:13,64:14,67:15,20:16,21:17,22:18,23:19,24:20,25:21,26:22,58:23,68:24,70:35,72:37,7:67,30:103,13:$V0,27:$V1,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,60:$Va,69:$Vb,71:$Vc,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl}),o($VS,[2,55]),o($VT,$VC,{8:7,12:8,14:10,16:11,17:12,19:13,64:14,67:15,20:16,21:17,22:18,23:19,24:20,25:21,26:22,58:23,68:24,70:35,72:37,30:65,7:67,10:173,28:174,13:$V0,27:$V1,31:$VU,32:$V3,39:$V4,41:$V5,42:$V6,50:$V7,56:$V8,57:$V9,60:$Va,69:$Vb,71:$Vc,73:$Vd,75:$Ve,76:$Vf,77:$Vg,78:$Vh,79:$Vi,80:$Vj,81:$Vk,83:$Vl}),{52:175,53:[2,58],54:$VN,55:$VO},o($VM,$VC,{10:176,31:$VD}),o($VM,$VC,{10:177,31:$VD}),{44:[2,47]},{44:[2,48],49:[1,178]},{10:180,31:$VD,44:$VC,49:[1,179]},{53:[2,59]},o($VM,[2,50]),o($VM,[2,51]),o($VM,$VC,{10:181,31:$VD}),o($VM,$VC,{10:182,31:$VD}),{44:[2,49]},o($VM,[2,52]),o($VM,[2,53])],defaultActions:{34:[2,66],48:[2,2],88:[2,1],90:[2,3],114:[2,4],149:[2,43],155:[2,60],158:[2,42],172:[2,47],175:[2,59],180:[2,49]},parseError:function(str,hash4){if(hash4.recoverable)this.trace(str);else{let _parseError2=function(msg,hash5){this.message=msg,this.hash=hash5};var _parseError=_parseError2;throw _parseError2.prototype=Error,new _parseError2(str,hash4)}},parse:function(input){var self=this,stack=[0],tstack=[],vstack=[null],lstack=[],table=this.table,yytext="",yylineno=0,yyleng=0,recovering=0,TERROR=2,EOF=1,args2=lstack.slice.call(arguments,1),lexer=Object.create(this.lexer),sharedState={yy:{}};for(var k in this.yy)if(Object.prototype.hasOwnProperty.call(this.yy,k))sharedState.yy[k]=this.yy[k];if(lexer.setInput(input,sharedState.yy),sharedState.yy.lexer=lexer,sharedState.yy.parser=this,typeof lexer.yylloc>"u")lexer.yylloc={};var yyloc=lexer.yylloc;lstack.push(yyloc);var ranges=lexer.options&&lexer.options.ranges;if(typeof sharedState.yy.parseError==="function")this.parseError=sharedState.yy.parseError;else this.parseError=Object.getPrototypeOf(this).parseError;function popStack(n){stack.length=stack.length-2*n,vstack.length=vstack.length-n,lstack.length=lstack.length-n}_token_stack:var lex=function(){var token=lexer.lex()||EOF;if(typeof token!=="number")token=self.symbols_[token]||token;return token};var symbol3,preErrorSymbol,state2,action,a,r,yyval={},p,len,newState2,expected;while(!0){if(state2=stack[stack.length-1],this.defaultActions[state2])action=this.defaultActions[state2];else{if(symbol3===null||typeof symbol3>"u")symbol3=lex();action=table[state2]&&table[state2][symbol3]}if(typeof action>"u"||!action.length||!action[0]){var errStr="";expected=[];for(p in table[state2])if(this.terminals_[p]&&p>TERROR)expected.push("'"+this.terminals_[p]+"'");if(lexer.showPosition)errStr="Parse error on line "+(yylineno+1)+`:
|
|
1173
1173
|
`+lexer.showPosition()+`
|
|
1174
1174
|
Expecting `+expected.join(", ")+", got '"+(this.terminals_[symbol3]||symbol3)+"'";else errStr="Parse error on line "+(yylineno+1)+": Unexpected "+(symbol3==EOF?"end of input":"'"+(this.terminals_[symbol3]||symbol3)+"'");this.parseError(errStr,{text:lexer.match,token:this.terminals_[symbol3]||symbol3,line:lexer.yylineno,loc:yyloc,expected})}if(action[0]instanceof Array&&action.length>1)throw Error("Parse Error: multiple actions possible at state: "+state2+", token: "+symbol3);switch(action[0]){case 1:if(stack.push(symbol3),vstack.push(lexer.yytext),lstack.push(lexer.yylloc),stack.push(action[1]),symbol3=null,!preErrorSymbol){if(yyleng=lexer.yyleng,yytext=lexer.yytext,yylineno=lexer.yylineno,yyloc=lexer.yylloc,recovering>0)recovering--}else symbol3=preErrorSymbol,preErrorSymbol=null;break;case 2:if(len=this.productions_[action[1]][1],yyval.$=vstack[vstack.length-len],yyval._$={first_line:lstack[lstack.length-(len||1)].first_line,last_line:lstack[lstack.length-1].last_line,first_column:lstack[lstack.length-(len||1)].first_column,last_column:lstack[lstack.length-1].last_column},ranges)yyval._$.range=[lstack[lstack.length-(len||1)].range[0],lstack[lstack.length-1].range[1]];if(r=this.performAction.apply(yyval,[yytext,yyleng,yylineno,sharedState.yy,action[1],vstack,lstack].concat(args2)),typeof r<"u")return r;if(len)stack=stack.slice(0,-1*len*2),vstack=vstack.slice(0,-1*len),lstack=lstack.slice(0,-1*len);stack.push(this.productions_[action[1]][0]),vstack.push(yyval.$),lstack.push(yyval._$),newState2=table[stack[stack.length-2]][stack[stack.length-1]],stack.push(newState2);break;case 3:return!0}}return!0}};function Parser(){this.yy={}}return Parser.prototype=parser2,parser2.Parser=Parser,new Parser}();if(typeof exports<"u")exports.parser=parser,exports.Parser=parser.Parser,exports.parse=function(){return parser.parse.apply(parser,arguments)},exports.main=function(args2){if(!args2[1])console.log("Usage: "+args2[0]+" FILE"),process.exit(1);var source=__require("fs").readFileSync(__require("path").normalize(args2[1]),"utf8");return exports.parser.parse(source)}});var require_posix=__commonJS((exports,module)=>{var astBuilder=require_ast_builder(),tokenizer=require_tokenizer(),phaseCatalog=require_rules(),grammarSource=require_grammar(),enums=require_enums(),lexerPhases=()=>[phaseCatalog.newLineList,phaseCatalog.operatorTokens,phaseCatalog.separator,phaseCatalog.reservedWords,phaseCatalog.linebreakIn,phaseCatalog.ioNumber,phaseCatalog.identifyMaybeSimpleCommands,phaseCatalog.assignmentWord,phaseCatalog.parameterExpansion,phaseCatalog.arithmeticExpansion,phaseCatalog.commandExpansion,phaseCatalog.forNameVariable,phaseCatalog.functionName,phaseCatalog.identifySimpleCommandNames,phaseCatalog.aliasSubstitution,phaseCatalog.tildeExpanding,phaseCatalog.parameterExpansion.resolve,phaseCatalog.commandExpansion.resolve,phaseCatalog.arithmeticExpansion.resolve,phaseCatalog.fieldSplitting.split,phaseCatalog.pathExpansion,phaseCatalog.quoteRemoval,phaseCatalog.syntaxerrorOnContinue,phaseCatalog.defaultNodeType];module.exports={inherits:null,init:(posixMode,utils)=>{let grammar=null;try{grammar=require_built_grammar()}catch(err){}return{enums,phaseCatalog,lexerPhases:lexerPhases(utils),tokenizer,grammarSource,grammar,astBuilder}}}});var require_word_expansion=__commonJS((exports,module)=>{var map3=require_map_iterable(),tokenOrEmpty=require_tokens().tokenOrEmpty,convertToWord=()=>map3((tk)=>{if(tk.is("TOKEN"))return tk.changeTokenType("WORD",tk.value);return tk});function start(state2,source,reducers){let char=source&&source.shift();if(char===void 0)return{nextReduction:reducers.end,tokensToEmit:tokenOrEmpty(state2),nextState:state2.resetCurrent().saveCurrentLocAsStart()};if(state2.escaping&&char===`
|
|
1175
|
-
`)return{nextReduction:reducers.start,nextState:state2.setEscaping(!1).removeLastChar()};if(!state2.escaping&&char==="\\")return{nextReduction:reducers.start,nextState:state2.setEscaping(!0).appendChar(char)};if(!state2.escaping&&char==="'")return{nextReduction:reducers.singleQuoting,nextState:state2.appendChar(char)};if(!state2.escaping&&char==='"')return{nextReduction:reducers.doubleQuoting,nextState:state2.appendChar(char)};if(!state2.escaping&&char==="$")return{nextReduction:reducers.expansionStart,nextState:state2.appendChar(char).appendEmptyExpansion()};if(!state2.escaping&&char==="`")return{nextReduction:reducers.expansionCommandTick,nextState:state2.appendChar(char).appendEmptyExpansion()};return{nextReduction:reducers.start,nextState:state2.appendChar(char).setEscaping(!1)}}module.exports={inherits:"posix",init:(posixMode)=>{let phaseCatalog=posixMode.phaseCatalog,lexerPhases=[convertToWord,phaseCatalog.parameterExpansion,phaseCatalog.arithmeticExpansion,phaseCatalog.commandExpansion,phaseCatalog.tildeExpanding,phaseCatalog.parameterExpansion.resolve,phaseCatalog.commandExpansion.resolve,phaseCatalog.arithmeticExpansion.resolve,phaseCatalog.fieldSplitting.split,phaseCatalog.pathExpansion,phaseCatalog.quoteRemoval,phaseCatalog.defaultNodeType],reducers=Object.assign({},posixMode.tokenizer.reducers,{start});return Object.assign({},posixMode,{lexerPhases,tokenizer:()=>posixMode.tokenizer({},reducers)})}}});var require_src=__commonJS((exports,module)=>{var shellLexer=require_shell_lexer(),utils=require_utils2(),modes={bash:require_bash(),posix:require_posix(),"word-expansion":require_word_expansion()};function loadPlugin(name){let modePlugin=modes[name];if(modePlugin.inherits)return modePlugin.init(loadPlugin(modePlugin.inherits),utils);return modePlugin.init(null,utils)}module.exports=function(sourceCode,options){try{options=options||{},options.mode=options.mode||"posix";let mode=loadPlugin(options.mode),Parser=mode.grammar.Parser,astBuilder=mode.astBuilder,parser=new Parser;return parser.lexer=shellLexer(mode,options),parser.yy=astBuilder(options),parser.parse(sourceCode)}catch(err){if(err instanceof SyntaxError)throw err;throw Error(err.stack||err.message)}}});import*as path97 from"node:path";function unsafeShellCommandTextReason(value){return unsafePathTextReason(value.replace(/[\r\n]/g,""))}function mergeWriteAnalyses(primary,additional,additionalIsAuthoritative=!0,wrapperDeclared=!1){if(additional.writes.length===0&&!additional.hasWrites)return primary;let posixAuthoritative=wrapperDeclared?!1:!additionalIsAuthoritative||!primary.parseError,authority=posixAuthoritative?primary:additional,supplementary=posixAuthoritative?additional:primary,authorityConstructs=new Set(authority.writes.map((write)=>`${write.category}|${write.operator}`)),authorityKeys=new Set(authority.writes.map((write)=>buildDedupeKey(write.category,write.operator,write.path))),stripQuotes2=(p)=>p===null||p===void 0?p:p.replace(/^['"]+/,"").replace(/['"]+$/,""),isQuoteArtifact=(write)=>{let stripped=stripQuotes2(write.path);if(stripped===write.path)return!1;return authority.writes.some((other)=>other.category===write.category&&other.operator===write.operator&&stripQuotes2(other.path)===stripped)},keptIndex=new Map,writes=[],demoteKept=(key2)=>{let index=keptIndex.get(key2);if(index!==void 0)writes[index]=withoutEmptyDirectoryRemoval(writes[index])};for(let write of[...authority.writes,...supplementary.writes]){let key2=buildDedupeKey(write.category,write.operator,write.path);if(supplementary.writes.includes(write))if(wrapperDeclared){let construct=`${write.category}|${write.operator}`;if(authorityConstructs.has(construct))continue}else{if(authorityKeys.has(key2)){demoteKept(key2);continue}if(isQuoteArtifact(write))continue}if(keptIndex.has(key2)){demoteKept(key2);continue}keptIndex.set(key2,writes.length),writes.push(write)}return{writes,hasWrites:writes.length>0||primary.hasWrites||additional.hasWrites,parseError:primary.parseError}}function buildDedupeKey(category,operator,path98){return`${category}|${operator}|${path98??"null"}`}function withoutEmptyDirectoryRemoval(write){if(write.emptyDirectoryRemoval!==!0)return write;let{emptyDirectoryRemoval:_dropped,...rest}=write;return rest}function dedupeWriteTargets(writes){let keptIndex=new Map,kept=[];for(let write of writes){let key2=buildDedupeKey(write.category,write.operator,write.path),index=keptIndex.get(key2);if(index===void 0){keptIndex.set(key2,kept.length),kept.push(write);continue}kept[index]=withoutEmptyDirectoryRemoval(kept[index])}return kept}function isBareRmdirOperand(word){return BARE_RMDIR_OPERAND.test(word)&&!word.split("/").includes("..")}function unquotedWordTokens(command){let tokens=[],current="",quote=null,flush=()=>{if(current.length>0)tokens.push(current);current=""};for(let i=0;i<command.length;i+=1){let ch=command[i];if(quote){if(ch===quote)quote=null;continue}if(ch==='"'||ch==="'"){flush(),quote=ch;continue}if(/\s/.test(ch)){flush();continue}current+=ch}return flush(),tokens.map((token)=>token.replace(/^[({]+/,"").replace(/[)}]+$/,""))}function isPowerShellShaped(command){if(!command)return!1;return unquotedWordTokens(command).some((token)=>{let lower=token.toLowerCase();return POWERSHELL_WRITE_CMDLETS.has(lower)||POWERSHELL_READ_ONLY_COMMANDS.has(lower)})}function isReadOnlyScriptBlockBody(body){if(/[()[\]=@|`;]/.test(body)||body.includes("::")||body.includes("$("))return!1;let tokens=body.match(/"[^"]*"|'[^']*'|\S+/g)?.map((token)=>token.replace(/^[({]+/,"").replace(/[)}]+$/,""))??[];if(tokens.length===0)return!1;for(let token of tokens){if(token===",")continue;if(/^(?:"[^"]*"|'[^']*')$/.test(token))continue;if(/^-?\d+(?:\.\d+)?$/.test(token))continue;if(READ_ONLY_SCRIPT_BLOCK_OPERATORS.has(token.toLowerCase()))continue;if(/^(?:\$_|\$this)(?:\.[A-Za-z_]\w*)*$/.test(token))continue;return!1}return!0}function extractScriptBlockBodies(command){let bodies=[],depth=0,start=-1,quote=null;for(let i=0;i<command.length;i+=1){let ch=command[i];if(quote){if(ch===quote)quote=null;continue}if(ch==='"'||ch==="'"){quote=ch;continue}if(ch==="{"){if(depth===0)start=i+1;depth+=1;continue}if(ch==="}"){if(depth-=1,depth<0)return null;if(depth===0&&start>=0)bodies.push(command.slice(start,i)),start=-1}}if(quote!==null||depth!==0)return null;return bodies}function isPowerShellReadOnlyPipeline(command){if(!command)return!1;if(/[>;&`\r\n]/.test(command)||/\$\(/.test(command))return!1;let quote=null,braceDepth=0;for(let ch of command){if(quote){if(ch===quote)quote=null;continue}if(ch==='"'||ch==="'"){quote=ch;continue}if(ch==="{")braceDepth+=1;if(ch==="}")braceDepth-=1;if(braceDepth<0)return!1}if(quote!==null||braceDepth!==0)return!1;for(let token of unquotedWordTokens(command)){let lower=token.toLowerCase();if(POWERSHELL_WRITE_CMDLETS.has(lower)||AMBIGUOUS_WRITE_ALIASES.has(lower)||POSIX_WRITE_TOKENS.has(lower))return!1;if((token==="sed"||token==="perl"||token==="awk")&&/(^|[\s'"])--?[a-zA-Z-]*(?:\bi|\bin-place|\bpi)\b/.test(command))return!1}let bodies=extractScriptBlockBodies(command);if(bodies===null)return!1;for(let body of bodies)if(!isReadOnlyScriptBlockBody(body))return!1;let segments=[],current="";quote=null;for(let i=0;i<command.length;i+=1){let ch=command[i];if(quote){if(ch===quote)quote=null;current+=ch;continue}if(ch==='"'||ch==="'"){quote=ch,current+=ch;continue}if(ch==="|"){segments.push(current),current="";continue}current+=ch}segments.push(current);for(let segment of segments){let tokens=unquotedWordTokens(segment.trim());if(tokens.length===0)return!1;if(!POWERSHELL_READ_ONLY_COMMANDS.has(tokens[0].toLowerCase()))return!1}return segments.length>0}function detectProcessSubstitutionWrites(command){let results=[],writeProcSubPattern=/>\s*\(([^)]+)\)/g;while(!0){let match=writeProcSubPattern.exec(command);if(match===null)break;let innerCommand=match[1].trim();if(!innerCommand)continue;let stages=innerCommand.split("|").map((s)=>s.trim());for(let stage of stages){let builtinResult=detectBuiltinWritesFromString(stage);if(builtinResult)results.push(builtinResult);let appendMatch=stage.match(/^\s*(.*?)\s*>>(\s*)(\S+)\s*$/);if(appendMatch){let path98=appendMatch[3];if(path98&&!isNullDevice(path98))results.push({category:"redirect",operator:">>",path:path98})}else{let writeMatch=stage.match(/^\s*(.*?)\s*>(?!>)(\s*)(\S+)\s*$/);if(writeMatch){let path98=writeMatch[3];if(path98&&!isNullDevice(path98))results.push({category:"redirect",operator:">",path:path98})}}}}return results}function detectBuiltinWritesFromString(cmd){let tokens=cmd.trim().split(/\s+/);if(tokens.length===0)return null;let name=tokens[0].toLowerCase();if(name==="rmdir"&&tokens.some((token)=>/^\/(?:s|q)$/i.test(token)))return null;if(BUILTIN_WRITE_COMMANDS.has(name)){for(let i=tokens.length-1;i>=1;i--)if(!tokens[i].startsWith("-"))return{category:"builtin_write",operator:name,path:tokens[i]}}return null}function wordText(node){if(!node||typeof node!=="object")return null;if(isBashWord(node))return node.text;return null}function isBashWord(node){return!!node&&typeof node==="object"&&node.type==="Word"&&typeof node.text==="string"}function annotateRawWordText(node,source){let unitIndex=null;if(/[\uD800-\uDFFF]/.test(source)){unitIndex=[];let u=0;for(let cp2 of source)unitIndex.push(u),u+=cp2.length;unitIndex.push(u)}let toUnit=(cp2)=>unitIndex===null?cp2:unitIndex[cp2],stack=[node],seen=new Set;while(stack.length>0){let n=stack.pop();if(!n||typeof n!=="object"||seen.has(n))continue;if(seen.add(n),isBashWord(n)){let loc=n.loc,start=loc?.start?.char,end=loc?.end?.char;if(typeof start==="number"&&typeof end==="number"&&end>=start){let from=toUnit(start),to=toUnit(end+1);if(from!==void 0&&to!==void 0)RAW_WORD_TEXT.set(n,source.slice(from,to))}}for(let value of Object.values(n))if(value&&typeof value==="object")stack.push(value)}}function hasUnquotedGlob(word){let projection=unquotedProjection(word);return projection===null||/[*?[]/.test(projection)}function hasUnquotedBraceExpansion(word,text){let projection=unquotedProjection(word);return BRACE_EXPANSION.test(projection===null?text:projection)}function unquotedProjection(word){if(!word||typeof word!=="object")return null;let raw=RAW_WORD_TEXT.get(word);if(raw===void 0)return null;let{projection,dequoted}=scanQuoting(raw),hasExpansion=Array.isArray(word.expansion)&&(word.expansion.length??0)>0,text=word.text;if(!hasExpansion&&dequoted!==text&&decodeParserEscapes(dequoted)!==text)return null;return projection}function scanQuoting(raw){let state2="none",projection="",dequoted="";for(let c=0;c<raw.length;c++){let ch=raw[c];if(state2==="single")if(ch==="'")state2="none";else dequoted+=ch,projection+="\x00";else if(ch==="\\"){let next=raw[c+1]??"";if(state2==="double"&&!/[$`"\\\n]/.test(next)){dequoted+=ch,projection+="\x00";continue}if(next!==`
|
|
1176
|
-
`)dequoted+=next,projection+="\x00";c++}else if(ch==='"')state2=state2==="double"?"none":"double";else if(state2==="none"&&ch==="'")state2="single";else dequoted+=ch,projection+=state2==="none"?ch:"\x00"}return{projection,dequoted}}function decodeParserEscapes(s){return s.replace(/\\(?:x([0-9A-Fa-f]{2})|u([0-9A-Fa-f]{4})|U([0-9A-Fa-f]{8})|([0-7]{1,3})|([\\tnrbfv"']))/g,(m,x,u,big,octal,c)=>{let hex5=x??u??big;if(hex5!==void 0){let cp2=Number.parseInt(hex5,16);return cp2<=1114111?String.fromCodePoint(cp2):m}if(octal!==void 0)return String.fromCodePoint(Number.parseInt(octal,8));return PARSER_CHAR_ESCAPES[c]??c})}function collectLeafCommands(node,out){if(!node||typeof node!=="object")return;switch(node.type){case"Script":if(Array.isArray(node.commands))for(let cmd of node.commands)collectLeafCommands(cmd,out);break;case"Pipeline":case"Sequence":if(Array.isArray(node.commands))for(let cmd of node.commands)collectLeafCommands(cmd,out);break;case"CompoundList":if(out.push(node),Array.isArray(node.commands))for(let cmd of node.commands)collectLeafCommands(cmd,out);break;case"LogicalExpression":if(node.left)collectLeafCommands(node.left,out);if(node.right)collectLeafCommands(node.right,out);break;case"And":case"Or":if(node.left)collectLeafCommands(node.left,out);if(node.right)collectLeafCommands(node.right,out);break;case"Subshell":if(out.push(node),node.list)collectLeafCommands(node.list,out);break;case"ProcessSubstitution":{let opNode=node.op;if(opNode&&typeof opNode==="object"){if(opNode.type?.toUpperCase()==="GREAT"){if(node.command)collectLeafCommands(node.command,out)}}}break;case"If":if(out.push(node),node.clause)collectLeafCommands(node.clause,out);if(node.then)collectLeafCommands(node.then,out);if(node.else)collectLeafCommands(node.else,out);break;case"While":case"Until":if(out.push(node),node.clause)collectLeafCommands(node.clause,out);if(node.do)collectLeafCommands(node.do,out);break;case"For":if(out.push(node),node.do)collectLeafCommands(node.do,out);break;case"Case":if(out.push(node),Array.isArray(node.cases)){for(let entry of node.cases)if(entry?.body)collectLeafCommands(entry.body,out)}break;case"Function":if(out.push(node),node.body)collectLeafCommands(node.body,out);break;default:out.push(node);break}}function getCommandName(cmd){if(!cmd||typeof cmd!=="object")return null;let c=cmd;if(typeof c.name==="string")return c.name;return wordText(c.name)}function getSuffixWords(cmd){if(!cmd||typeof cmd!=="object")return[];let suffix=cmd.suffix;if(!Array.isArray(suffix))return[];let words=[];for(let s of suffix){let text=wordText(s);if(text!==null)words.push(text)}return words}function getSuffixWordExpansionFlags(cmd){if(!cmd||typeof cmd!=="object")return[];let suffix=cmd.suffix;if(!Array.isArray(suffix))return[];let flags=[];for(let s of suffix){if(!isBashWord(s))continue;let expansion=s.expansion;flags.push(Array.isArray(expansion)&&expansion.length>0)}return flags}function getSuffixWordUnquotedExpansionFlags(cmd){if(!cmd||typeof cmd!=="object")return[];let suffix=cmd.suffix;if(!Array.isArray(suffix))return[];let flags=[];for(let s of suffix){if(!isBashWord(s))continue;let expansion=s.expansion;if(!Array.isArray(expansion)||expansion.length===0){flags.push(!1);continue}let text=s.text,hasSubstitution=/\$\(|`/.test(text),hasListExpansion=/\$\{?[!#]?[A-Za-z0-9_]*(?:\[[@*]\]|@|\*)/.test(text)||/\$\{?[!#]?[@*]|\[[@*]\]/.test(text);if(hasSubstitution||hasListExpansion){flags.push(!0);continue}let quotedAt=[],state2="none";for(let c=0;c<text.length;c++){let ch=text[c];if(quotedAt[c]=state2!=="none",state2==="single"){if(ch==="'")state2="none"}else if(ch==="\\")quotedAt[c+1]=!0,c++;else if(ch==='"')state2=state2==="double"?"none":"double";else if(ch==="'"&&state2==="none")state2="single"}flags.push(expansion.some((e)=>{let start=e.loc?.start;return typeof start!=="number"||quotedAt[start]!==!0}))}return flags}function getRedirections(cmd){if(!cmd||typeof cmd!=="object")return[];let c=cmd;if(Array.isArray(c.redirections))return c.redirections;let results=[],suffix=c.suffix,prefix=c.prefix;if(Array.isArray(suffix)){for(let item of suffix)if(isRedirectNode(item))results.push(item)}if(Array.isArray(prefix)){for(let item of prefix)if(isRedirectNode(item))results.push(item)}return results}function isRedirectNode(node){return!!(node&&typeof node==="object"&&node.type==="Redirect")}function operatorLabel(op){if(!op||typeof op!=="object")return"unknown";let opType=op.type?.toUpperCase();switch(opType){case"GREAT":return">";case"DGREAT":return">>";case"CLOBBER":return">|";case"LESS":return"<";case"DLESS":return"<<";case"DLESSDASH":return"<<-";case"LESSAND":return"<&";case"GREATAND":return">&";case"LESSGREAT":return"<>";default:return opType||"unknown"}}function extractRedirectPath(fileNode){let text=wordText(fileNode);if(!text)return null;return text}function isNullDevice(path98){return path98==="/dev/null"||path98==="/dev/zero"||path98==="/dev/urandom"}function isNullDeviceWord(word,path98){if(!isNullDevice(path98)||!word||typeof word!=="object")return!1;let raw=RAW_WORD_TEXT.get(word);return raw!==void 0&&isNullDevice(scanQuoting(raw).dequoted)}function isNumeric(s){return/^\d+$/.test(s)}function isNonFileGreatAndTarget(path98){return path98!==null&&(isNumeric(path98)||path98==="-")}function detectRedirects(cmd){let results=[];results.push(...detectHereDocMarkers(cmd));let redirections=getRedirections(cmd);for(let redirect of redirections){if(!redirect||typeof redirect!=="object")continue;let r=redirect,opNode=r.op;if(!opNode||typeof opNode!=="object")continue;let opType=opNode.type?.toUpperCase();if(!opType||!REDIRECT_ALL_WRITE_TOKENS.has(opType))continue;let fileNode=r.file,path98=extractRedirectPath(fileNode),opLabel=operatorLabel(opNode);if(REDIRECT_WRITE_TOKENS.has(opType)||REDIRECT_GREATAND_TOKENS.has(opType)&&!isNonFileGreatAndTarget(path98)){if(path98!==null&&isNullDeviceWord(fileNode,path98))continue;results.push({category:"redirect",operator:opLabel,path:path98})}else if(REDIRECT_HERE_TOKENS.has(opType))results.push({category:"here_doc",operator:opLabel,path:path98})}return results}function detectHereDocMarkers(cmd){let results=[];if(!cmd||typeof cmd!=="object")return results;let suffix=cmd.suffix;if(!Array.isArray(suffix))return results;for(let item of suffix){if(!item||typeof item!=="object")continue;if(isHereDocMarker(item))results.push({category:"here_doc",operator:item.text==="<<-"?"<<-":"<<",path:null})}return results}function isHereDocMarker(node){if(!node||typeof node!=="object")return!1;let type=node.type?.toLowerCase();return type==="dless"||type==="dlessdash"}function detectBuiltinWrites(cmd){let results=[],name=getCommandName(cmd);if(!name)return results;let lowerName=name.toLowerCase();if(lowerName==="dd"){let suffixWords2=getSuffixWords(cmd);for(let word of suffixWords2)if(word.startsWith("of=")){let path98=word.slice(3);if(path98&&!isNullDevice(path98))results.push({category:"builtin_write",operator:"dd of=",path:path98})}return results}if(lowerName==="tee"){let suffixWords2=getSuffixWords(cmd),pastDoubleDash=!1;for(let word of suffixWords2){if(word==="--"){pastDoubleDash=!0;continue}if(!pastDoubleDash&&word.startsWith("-"))continue;if(word&&!isNullDevice(word))results.push({category:"builtin_write",operator:"tee",path:word})}return results}if(!BUILTIN_WRITE_COMMANDS.has(lowerName))return results;let suffixWords=getSuffixWords(cmd);if(lowerName==="rmdir"&&suffixWords.some((word)=>/^\/(?:s|q)$/i.test(word)))return results;if(lowerName==="rmdir"&&suffixWords.length===1&&isBareRmdirOperand(suffixWords[0]))return results.push({category:"builtin_write",operator:name,path:suffixWords[0],emptyDirectoryRemoval:!0}),results;if(lowerName==="truncate"){for(let word of suffixWords)if(!word.startsWith("-")&&!isNumeric(word)){results.push({category:"builtin_write",operator:"truncate",path:word});break}}else for(let i=suffixWords.length-1;i>=0;i--){let word=suffixWords[i];if(!word.startsWith("-")){results.push({category:"builtin_write",operator:name,path:word});break}}return results}function looksLikeSedScript(w){if(hasParentComponent(w)||/^[A-Za-z]:[\\/]/.test(w))return!1;return/^(?:(?:[0-9]+|\$)(?:,(?:[0-9]+|\$))?!?|!)[a-zA-Z=]$/.test(w)||/[;{}]/.test(w)&&!/[\\/:]/.test(w)&&!w.startsWith(".")||/^s([^A-Za-z0-9\s\\])(?:\\.|(?!\1)[^\\])*\1(?:\\.|(?!\1)[^\\])*\1[gpiImMe0-9]*$/.test(w)||/^y([^A-Za-z0-9\s\\])(?:\\.|(?!\1)[^\\])*\1(?:\\.|(?!\1)[^\\])*\1$/.test(w)}function hasParentComponent(w){return w.split(/[\\/]/).includes("..")}function detectInplaceEdit(cmd){let results=[],name=getCommandName(cmd);if(!name)return results;let lowerName=name.toLowerCase();if(!INPLACE_EDIT_COMMANDS.has(lowerName))return[];let suffixWords=getSuffixWords(cmd);if(!suffixWords.some((word)=>{if(lowerName==="sed")return word.startsWith("-i")&&word.length>1||/^--i(?:n(?:-(?:p(?:l(?:a(?:c(?:e)?)?)?)?)?)?)?(?:=|$)/.test(word);return word==="-i"||word.startsWith("-i")}))return[];let scriptPattern=/^[ssy]\/.*\/[gim]*$/,quotedScriptPattern=/^["'].*["']$/,isScriptShaped=(w)=>scriptPattern.test(w)&&!hasParentComponent(w),isScriptWord=(i)=>{let w=suffixWords[i];if(quotedScriptPattern.test(w))return unquotedExpansionFlags[i]!==!0&&isScriptShaped(w.slice(1,-1));return isScriptShaped(w)},flagArgs=lowerName==="sed"?new Set(["-e","-f","--expression","--file"]):lowerName==="perl"?new Set(["-e","-E"]):new Set(["-f","-e","-v","-F"]),combinedFlagArgs=/^-[0-9AacSlnpstTuUwWX]+[eE]$/,perlAttachedScript=/^-[0-9AacSlnpstTuUwWX]*[eE]./,sedScriptBundle=/^-[nrEszub]*[ef]$/,sedAttachedScript=/^-[nrEszub]*[ef]./,consumesNext=(w)=>flagArgs.has(w)||lowerName==="sed"&&sedScriptBundle.test(w)||lowerName==="perl"&&combinedFlagArgs.test(w),suppliesScript=(w)=>{if(lowerName==="awk")return w==="-f"||w==="-e"||/^-[fe]./.test(w)||w.startsWith("--file=")||w.startsWith("--source=");if(lowerName==="sed")return consumesNext(w)||sedAttachedScript.test(w)||/^--(?:expression|file)=/.test(w);return consumesNext(w)||perlAttachedScript.test(w)},expansionFlags=getSuffixWordExpansionFlags(cmd),unquotedExpansionFlags=getSuffixWordUnquotedExpansionFlags(cmd),suffixNodes=(Array.isArray(cmd.suffix)?cmd.suffix:[]).filter((s)=>wordText(s)!==null),mayExpandToSeveralWords=(i)=>unquotedExpansionFlags[i]===!0||hasUnquotedBraceExpansion(suffixNodes[i],suffixWords[i]),isKnownOption=(w)=>{if(w==="-"||w==="--")return!0;if(lowerName==="sed")return/^-[nrEszub]+$/.test(w)||/^-[nrEszub]*[ef]/.test(w)||/^-[nrEszub]*l/.test(w)||/^-i/.test(w)||SED_LONG_SWITCHES.has(w)||/^--(?:expression|file|line-length|in-place)(?:=|$)/.test(w);if(lowerName==="perl")return/^-[0-9AacSlnpstTuUwWX]*(?:[eE].*)?$/.test(w)||/^-i/.test(w)||/^-I./.test(w);return/^-[fevFil]/.test(w)||/^-[PcrSVh]$/.test(w)||AWK_LONG_SWITCHES.has(w)||/^--(?:file|source|lint)=/.test(w)},isOpaqueFlag=(i)=>suffixWords[i].startsWith("-")&&(mayExpandToSeveralWords(i)||!isKnownOption(suffixWords[i])),sedOptionArg=(w)=>lowerName==="sed"&&(/^-[nrEszub]*l$/.test(w)||w==="--line-length"),takesDetachedArg=(w)=>consumesNext(w)||sedOptionArg(w)||lowerName==="awk"&&w==="-i",fileArgOption=(w)=>lowerName==="sed"&&(/^-[nrEszub]*f$/.test(w)||w==="--file")||lowerName==="awk"&&(w==="-f"||w==="-i"),detachedArgMaySplit=(option,i)=>mayExpandToSeveralWords(i)||(fileArgOption(option)?/[*?[]/.test(suffixWords[i]):hasUnquotedGlob(suffixNodes[i])),permutes=lowerName==="sed",operandsFrom=suffixWords.length,optionArgs=new Set,expandingOptionArgs=new Set;for(let i=0;i<suffixWords.length;i++){let w=suffixWords[i];if(w==="--"){if(!permutes)operandsFrom=i+1;break}if(!w.startsWith("-")){if(!permutes){operandsFrom=i;break}continue}if(isOpaqueFlag(i)){if(!permutes){operandsFrom=i+1;break}continue}if(!takesDetachedArg(w))continue;if(i+1<suffixWords.length){if(optionArgs.add(i+1),detachedArgMaySplit(w,i+1)){if(expandingOptionArgs.add(i+1),!permutes){operandsFrom=i+2;break}}}i++}let inOptionArea=(i)=>i<operandsFrom,hasExplicitScript=!1;for(let i=0;i<suffixWords.length&&inOptionArea(i);i++){if(optionArgs.has(i))continue;let w=suffixWords[i];if(w==="--")break;if(!w.startsWith("-")||isOpaqueFlag(i))continue;if(expandingOptionArgs.has(i+1)){i++;continue}if(suppliesScript(w)){hasExplicitScript=!0;break}if(consumesNext(w)||lowerName==="awk"&&w==="-i")i++}let skipIndices=new Set,isDetachedSuffix=(w)=>lowerName==="sed"&&w!==void 0&&(w===""||w.startsWith(".")),isLiteralWord=(i)=>expansionFlags[i]!==!0&&!/[*?[]/.test(suffixWords[i])&&!/\{[^{}]*(?:,|\.\.)[^{}]*\}/.test(suffixWords[i]),isLiteralSedScript=(i)=>isLiteralWord(i)&&looksLikeSedScript(suffixWords[i]),isReportableWord=(i)=>suffixWords[i]!==""&&!isScriptWord(i)&&!isLiteralSedScript(i),firstPositionalFrom=(from)=>{let j=from;while(j<suffixWords.length&&(inOptionArea(j)&&suffixWords[j].startsWith("-")||optionArgs.has(j)))j++;return j},dashDash=suffixWords.findIndex((w,i)=>w==="--"&&!optionArgs.has(i)&&inOptionArea(i)),hasOpaqueFlag=suffixWords.some((_w,i)=>(dashDash<0||i<dashDash)&&inOptionArea(i)&&!optionArgs.has(i)&&isOpaqueFlag(i)),implicitScriptPlaced=hasOpaqueFlag||expandingOptionArgs.size>0;if(lowerName==="sed"&&!hasExplicitScript&&!implicitScriptPlaced)for(let i=0;i<suffixWords.length;i++){if(optionArgs.has(i))continue;let w=suffixWords[i];if(w==="--"||w.startsWith("-i")||w.startsWith("--in-place"))break;if(w.startsWith("-"))continue;if(!mayExpandToSeveralWords(i))skipIndices.add(i);implicitScriptPlaced=!0;break}let consumeImplicitScript=(from,bareInplace)=>{if(implicitScriptPlaced)return;implicitScriptPlaced=!0;let j=firstPositionalFrom(from);if(j>=suffixWords.length||mayExpandToSeveralWords(j))return;if(skipIndices.add(j),!bareInplace||!isDetachedSuffix(suffixWords[j]))return;let k=firstPositionalFrom(j+1);if(k>=suffixWords.length||!isLiteralSedScript(k))return;for(let m=firstPositionalFrom(k+1);m<suffixWords.length;){if(isReportableWord(m)){skipIndices.add(k);return}m=firstPositionalFrom(m+1)}},isConventionalBackupSuffix=(w)=>isDetachedSuffix(w)&&!w.includes("/")&&/^\.(?:bak|orig|old|save|backup|tmp|swp|~)$/i.test(w),dotWordAfterBareInplace=null,pastDoubleDash=!1,awkProgramSeen=!1;for(let i=0;i<suffixWords.length;i++){let word=suffixWords[i];if(optionArgs.has(i)){if(!expandingOptionArgs.has(i))skipIndices.add(i);continue}if(!pastDoubleDash&&word==="--"&&inOptionArea(i)){skipIndices.add(i),pastDoubleDash=!0;continue}if(!pastDoubleDash&&inOptionArea(i)&&word.startsWith("-")){if(isOpaqueFlag(i))continue;skipIndices.add(i);let next=suffixWords[i+1];if(lowerName==="sed"&&(word==="--in-place"||word.startsWith("--in-place="))){if(!hasExplicitScript)consumeImplicitScript(i+1,!1);continue}if(word==="-i"){if(next===void 0)continue;if(lowerName==="awk"){if(!expandingOptionArgs.has(i+1))skipIndices.add(i+1)}else if(!hasExplicitScript)consumeImplicitScript(i+1,!0);else if(isConventionalBackupSuffix(next))skipIndices.add(i+1),dotWordAfterBareInplace=next;continue}if(/^-i.+/.test(word)){if(lowerName!=="awk"&&!hasExplicitScript)consumeImplicitScript(i+1,!1);continue}if(consumesNext(word)||sedOptionArg(word)){if(next!==void 0&&!expandingOptionArgs.has(i+1))skipIndices.add(i+1)}continue}if(skipIndices.has(i))continue;if(lowerName==="awk"){if(!hasExplicitScript&&!hasOpaqueFlag&&expandingOptionArgs.size===0&&!awkProgramSeen)awkProgramSeen=!0,skipIndices.add(i);continue}if(isScriptWord(i))skipIndices.add(i)}let candidates=suffixWords.map((word,i)=>({word,i})).filter(({word,i})=>word!==""&&!skipIndices.has(i));if(candidates.length===0&&dotWordAfterBareInplace!==null)candidates.push({word:dotWordAfterBareInplace,i:-1});if(candidates.length>0)for(let{word}of candidates)results.push({category:"inplace_edit",operator:`${name} -i`,path:word});return results}function detectInterpreterEval(cmd){let results=[],name=getCommandName(cmd);if(!name)return results;let lowerName=name.toLowerCase();if(!INTERPRETER_EVAL_COMMANDS.has(lowerName))return[];let suffixWords=getSuffixWords(cmd),evalFlags={python:["-c"],python3:["-c"],python2:["-c"],node:["-e","-p","-pe"],bun:["-e","-p","-pe"],ruby:["-e"],perl:["-e","-E"],php:["-r","-R","-F"],bash:["-c"],sh:["-c"],dash:["-c"],zsh:["-c"],ksh:["-c"]};if(lowerName==="eval")return results.push({category:"interpreter_eval",operator:"eval",path:null}),results;let relevantFlags=evalFlags[lowerName]??[];if(!suffixWords.some((word)=>relevantFlags.some((f)=>word===f||word.startsWith(f)&&word.length>f.length)))return[];return results.push({category:"interpreter_eval",operator:`${name} [eval]`,path:null}),results}function detectNetworkDownloaders(cmd){let results=[],name=getCommandName(cmd);if(!name)return results;let lowerName=name.toLowerCase();if(!NETWORK_DOWNLOAD_COMMANDS.has(lowerName))return[];let suffixWords=getSuffixWords(cmd);if(lowerName==="curl")for(let i=0;i<suffixWords.length;i++){let word=suffixWords[i];if(word==="-o"&&i+1<suffixWords.length){let path98=suffixWords[i+1];if(!path98.startsWith("-"))results.push({category:"network_download",operator:"curl -o",path:path98})}else if(word.startsWith("-o")&&word.length>2)results.push({category:"network_download",operator:"curl -o",path:word.slice(2)})}else if(lowerName==="wget")for(let i=0;i<suffixWords.length;i++){let word=suffixWords[i];if(word==="-O"&&i+1<suffixWords.length){let path98=suffixWords[i+1];if(!path98.startsWith("-"))results.push({category:"network_download",operator:"wget -O",path:path98})}else if(word.startsWith("-O")&&word.length>2)results.push({category:"network_download",operator:"wget -O",path:word.slice(2)})}else if(lowerName==="scp")for(let i=suffixWords.length-1;i>=0;i--){let word=suffixWords[i];if(!word.startsWith("-")&&(word.includes(":")||word.startsWith("/")||word.startsWith("."))){results.push({category:"network_download",operator:"scp",path:word});break}}return results}function detectArchiveExtract(cmd){let results=[],name=getCommandName(cmd);if(!name)return results;let lowerName=name.toLowerCase();if(!ARCHIVE_EXTRACT_COMMANDS.has(lowerName))return[];let suffixWords=getSuffixWords(cmd);if(lowerName==="tar"){if(suffixWords.some((word)=>{if(word==="--extract"||word==="--get")return!0;if(word.startsWith("-")&&word.includes("x"))return!0;return!1}))for(let i=suffixWords.length-1;i>=0;i--){let word=suffixWords[i];if(!word.startsWith("-")){results.push({category:"archive_extract",operator:"tar -x",path:word});break}if(word.startsWith("--file=")&&word.length>7){results.push({category:"archive_extract",operator:"tar -x",path:word.slice(7)});break}}}else if(lowerName==="unzip")for(let i=suffixWords.length-1;i>=0;i--){let word=suffixWords[i];if(!word.startsWith("-")){results.push({category:"archive_extract",operator:"unzip",path:word});break}}else if(lowerName==="gunzip"||lowerName==="gzip"||lowerName==="bzip2"||lowerName==="xz"||lowerName==="7z"||lowerName==="rar"){if(suffixWords.includes("-d")||suffixWords.includes("--decompress")||lowerName==="gunzip")for(let i=suffixWords.length-1;i>=0;i--){let word=suffixWords[i];if(!word.startsWith("-")){results.push({category:"archive_extract",operator:`${name} [decompress]`,path:word});break}}}return results}function detectGitDestructive(cmd){let results=[],name=getCommandName(cmd);if(!name)return results;if(name.toLowerCase()!==GIT_COMMAND)return[];let suffixWords=getSuffixWords(cmd);if(suffixWords.length===0)return[];let first=suffixWords[0].toLowerCase();if(first==="checkout"){let dashDashIdx=suffixWords.indexOf("--");if(dashDashIdx!==-1&&dashDashIdx+1<suffixWords.length){let path98=suffixWords[dashDashIdx+1],op=path98==="."?"git checkout -- .":"git checkout --";results.push({category:"git_destructive",operator:op,path:path98})}}else if(first==="restore"){let hasHard=suffixWords.some((w)=>w==="--hard"||w==="-H"||w.startsWith("-")&&w.includes("H")),hasForce=suffixWords.some((w)=>w==="--force"||w==="-f"||w.startsWith("-")&&w.includes("f"));if(hasHard||hasForce){let dashDashIdx=suffixWords.indexOf("--");if(dashDashIdx!==-1&&dashDashIdx+1<suffixWords.length)results.push({category:"git_destructive",operator:"git restore",path:suffixWords[dashDashIdx+1]});else results.push({category:"git_destructive",operator:"git restore",path:null})}}else if(first==="reset"){if(suffixWords.some((w)=>w==="--hard"||w==="-H"||w.startsWith("-")&&w.includes("H")))results.push({category:"git_destructive",operator:"git reset --hard",path:null})}else if(first==="clean"){if(suffixWords.some((w)=>w==="-n"||w==="--dry-run"||w.startsWith("-")&&w.includes("n")))return results;let hasForce=suffixWords.some((w)=>w==="-f"||w==="--force"||w.startsWith("-")&&w.includes("f")),hasDir=suffixWords.some((w)=>w==="-d"||w==="--dir"||w.startsWith("-")&&w.includes("d"));if(hasForce&&hasDir)results.push({category:"git_destructive",operator:"git clean -fd",path:null})}return results}function splitWindowsCommands(command,shell){let commands=[],current="",inSingleQuote=!1,inDoubleQuote=!1,parenDepth=0;for(let i=0;i<command.length;i++){let ch=command[i];if(shell==="powershell"&&ch==="'"&&!inDoubleQuote)inSingleQuote=!inSingleQuote;else if(ch==='"'&&!inSingleQuote)inDoubleQuote=!inDoubleQuote;else if(ch==="("&&!inSingleQuote&&!inDoubleQuote)parenDepth++;else if(ch===")"&&!inSingleQuote&&!inDoubleQuote)parenDepth--;if(ch===`
|
|
1177
|
-
`&&!inSingleQuote&&!inDoubleQuote&&parenDepth===0){if(current.trim())commands.push(current.trim());current="";continue}if(shell==="powershell"&&(ch===";"||ch==="{"||ch==="}")&&!inSingleQuote&&!inDoubleQuote&&parenDepth===0){if(current.trim())commands.push(current.trim());current="";continue}if(ch==="|"&&!inSingleQuote&&!inDoubleQuote&&parenDepth===0){if(current.trim())commands.push(current.trim());current="";continue}if((ch==="&"||ch==="|")&&i+1<command.length&&command[i+1]===ch&&!inSingleQuote&&!inDoubleQuote&&parenDepth===0){if(current.trim())commands.push(current.trim());commands.push(ch==="&"?"&&":"||"),current="",i++;continue}if(ch==="&"&&!inSingleQuote&&!inDoubleQuote&&parenDepth===0){if(command[i-1]===">"){current+=ch;continue}if(!(i+1<command.length&&command[i+1]==="&")){if(current.trim())commands.push(current.trim());current="";continue}}current+=ch}if(current.trim())commands.push(current.trim());return commands.filter((c)=>c!=="&&"&&c!=="||")}function detectPowerShellRedirects(command){let results=[],inSingleQuote=!1,inDoubleQuote=!1,isBoundary=(character)=>character===void 0||/[\s;|&()]/.test(character);for(let index=0;index<command.length;index++){let character=command[index];if(inSingleQuote){if(character==="'")if(command[index+1]==="'")index++;else inSingleQuote=!1;continue}if(inDoubleQuote){if(character==="`"&&index+1<command.length){index++;continue}if(character==='"')inDoubleQuote=!1;continue}if(character==="'"){inSingleQuote=!0;continue}if(character==='"'){inDoubleQuote=!0;continue}if(character===">"&&command[index-1]==="^")continue;if(character!==">")continue;let operator=command[index+1]===">"?">>":">",cursor=index+operator.length;while(/\s/.test(command[cursor]??""))cursor++;if(command[cursor]==="&"){cursor++;while(/\s/.test(command[cursor]??""))cursor++;let descriptorStart=cursor;while(/\d/.test(command[cursor]??""))cursor++;if(command.slice(descriptorStart,cursor)&&isBoundary(command[cursor])){index=Math.max(index,cursor-1);continue}results.push({category:"redirect",operator,path:null}),index=Math.max(index,cursor-1);continue}let pathValue=null;if(cursor<command.length){let quote=command[cursor];if(quote==='"'||quote==="'"){cursor++;let pathStart=cursor,closed=!1;while(cursor<command.length){if(quote==='"'&&command[cursor]==="`"){cursor+=2;continue}if(command[cursor]===quote){if(quote==="'"&&command[cursor+1]==="'"){cursor+=2;continue}pathValue=command.slice(pathStart,cursor),cursor++,closed=!0;break}cursor++}if(!closed)pathValue=null}else{let pathStart=cursor;while(cursor<command.length&&!/\s|[;|&()<>]/.test(command[cursor]??""))cursor++;if(cursor>pathStart)pathValue=command.slice(pathStart,cursor)}}results.push({category:"redirect",operator,path:pathValue}),index=Math.max(index,cursor-1)}if(inSingleQuote||inDoubleQuote)results.push({category:"redirect",operator:">",path:null});return results}function detectPowerShellWrites(command){let results=[],trimmed=command.trim();if(!trimmed)return results;if(/^(?:powershell|pwsh)(?:\.exe)?\s+/i.test(trimmed)&&/(?:^|\s)-(?:e|ec|enc|encodedcommand)(?=\s|=|$)/i.test(trimmed))return results.push({category:"interpreter_eval",operator:"PowerShell -EncodedCommand",path:null}),results;let innerCommand=trimmed,cmdMatch=trimmed.match(new RegExp(`${PS_STRIP_PREFIX.source}(.*)$`,"i"));if(cmdMatch){if(innerCommand=cmdMatch[1].trim(),innerCommand.startsWith('"')&&innerCommand.endsWith('"')||innerCommand.startsWith("'")&&innerCommand.endsWith("'"))innerCommand=innerCommand.slice(1,-1)}if(/(?:^|[;{}|&])\s*(?:Set-Location|Push-Location|Pop-Location|cd|chdir|sl)\b/i.test(innerCommand))results.push({category:"builtin_write",operator:"working-directory mutation",path:null});if(/[({]\s*(?:Out-File|Set-Content|Add-Content|Clear-Content|Copy-Item|Move-Item|Remove-Item)\b/i.test(innerCommand))results.push({category:"interpreter_eval",operator:"nested PowerShell script block",path:null});if(/(?:^|[;|])\s*&\s*(?:['"$({]|\S+\s*\()/i.test(innerCommand)||/(?:^|[;|])\s*(?:Invoke-Expression|IEX)\b/i.test(innerCommand))results.push({category:"interpreter_eval",operator:"dynamic PowerShell invocation",path:null});results.push(...detectPowerShellRedirects(innerCommand));let iwrMatch=trimmed.match(/^(?:Invoke-WebRequest|curl)\s.*?(?:-OutFile\s+(\S+)|-o\s+(\S+))/i);if(iwrMatch){let path98=iwrMatch[1]||iwrMatch[2];if(path98)results.push({category:"network_download",operator:"Invoke-WebRequest -OutFile",path:path98})}function detectPsContentCmdlet(cmd){let cmdletMatch=cmd.match(/^(Out-File|Set-Content|Add-Content|Clear-Content)\b/i);if(!cmdletMatch)return[];let cmdletName=cmdletMatch[1],rest=cmd.slice(cmdletMatch[0].length).trim(),pathFlagMatch=rest.match(/(?:-Path|-FilePath|-LiteralPath)\s+((?:"[^"]*"|'[^']*'|[^,\s]+)(?:\s*,\s*(?:"[^"]*"|'[^']*'|[^,\s]+))*)/i);if(pathFlagMatch)return pathFlagMatch[1].split(/\s*,\s*/).map((value)=>value.replace(/^(["'])|(["'])$/g,"")).map((path98)=>({category:"redirect",operator:cmdletName,path:path98||null}));if(/(?:-Path|-FilePath|-LiteralPath)(?:\s|$)/i.test(rest))return[{category:"redirect",operator:cmdletName,path:null}];let tokens=rest.match(/(?:[^\s"-]+|"[^"]*"|'[^']*'|-[^\s]+)/g)??[];for(let token of tokens){if(token.startsWith("-"))continue;let path98=token.replace(/^["']|["']$/g,"");return[{category:"redirect",operator:cmdletName,path:path98}]}return[]}results.push(...detectPsContentCmdlet(innerCommand));let pipeContentMatch=innerCommand.match(/\|\s*(Out-File|Set-Content|Add-Content|Clear-Content)\b\s*(.*)$/i);if(pipeContentMatch){let cmdletName=pipeContentMatch[1],tokens=pipeContentMatch[2].trim().match(/(?:[^\s"-]+|"[^"]*"|'[^']*'|-[^\s]+)/g)??[];for(let token of tokens){if(token.startsWith("-"))continue;let path98=token.replace(/^["']|["']$/g,"");if(path98){results.push({category:"redirect",operator:cmdletName,path:path98});break}}}function detectPsFileOp(cmd){let opMatch=cmd.match(/^(Copy-Item|Move-Item|Remove-Item)\b/i);if(!opMatch)return null;let cmdletName=opMatch[1],rest=cmd.slice(opMatch[0].length).trim(),destFlagMatch=rest.match(/-Destination\s+(\S+|"[^"]+"|'[^']+')/i);if(destFlagMatch){let path98=destFlagMatch[1].replace(/^["']|["']$/g,"");return{category:"builtin_write",operator:cmdletName,path:path98}}let tokens=[],flagTakingValue=new Set(["-Path","-LiteralPath","-Exclude","-Include","-Filter"]),switchFlags=new Set(["-Recurse","-Force","-Confirm","-WhatIf","-PassThru","-Verbose","-Debug"]),parts=rest.match(/(?:[^\s"-]+|"[^"]*"|'[^']*'|-[^\s]+)/g)??[],i=0;while(i<parts.length){let part=parts[i];if(flagTakingValue.has(part)&&i+1<parts.length){let value=parts[i+1];if(!value.startsWith("-"))tokens.push(value);i+=2}else if(switchFlags.has(part))i++;else if(part.startsWith("-"))i++;else tokens.push(part),i++}if(tokens.length>=2){let path98=tokens[tokens.length-1].replace(/^["']|["']$/g,"");return{category:"builtin_write",operator:cmdletName,path:path98}}else if(tokens.length===1){let path98=tokens[0].replace(/^["']|["']$/g,"");return{category:"builtin_write",operator:cmdletName,path:path98}}return null}function detectPsNewItem(cmd){let opMatch=cmd.match(/^(?:New-Item|ni)\b/i);if(!opMatch)return null;let rest=cmd.slice(opMatch[0].length).trim(),SWITCH_FLAGS=new Set(["-force","-confirm","-whatif"]),VALUE_FLAGS=new Set(["-itemtype","-value","-description"]),PATH_FLAGS=new Set(["-path","-literalpath"]),tokens=rest.match(/"[^"]*"|'[^']*'|\S+/g)??[],unquote=(value)=>value.replace(/^["']|["']$/g,""),pathValue=null,nameValue=null,positional=null;for(let i=0;i<tokens.length;i+=1){let token=tokens[i],flag=token.toLowerCase();if(PATH_FLAGS.has(flag)){pathValue=unquote(tokens[i+1]??""),i+=1;continue}if(flag==="-name"){nameValue=unquote(tokens[i+1]??""),i+=1;continue}if(VALUE_FLAGS.has(flag)){i+=1;continue}if(SWITCH_FLAGS.has(flag))continue;if(flag.startsWith("-"))continue;if(positional===null)positional=unquote(token)}let basePath=(pathValue??positional)?.replace(/\/+$/,"")??null;if(basePath!==null&&nameValue){let base=basePath;return{category:"builtin_write",operator:"New-Item",path:base?`${base}/${nameValue}`:nameValue}}if(pathValue)return{category:"builtin_write",operator:"New-Item",path:pathValue};if(positional)return{category:"builtin_write",operator:"New-Item",path:positional};if(nameValue)return{category:"builtin_write",operator:"New-Item",path:nameValue};return{category:"builtin_write",operator:"New-Item",path:null}}let fileOp=detectPsFileOp(innerCommand)??detectPsNewItem(innerCommand);if(fileOp)results.push(fileOp);let pipeFileOpMatch=innerCommand.match(/\|\s*(Copy-Item|Move-Item)\b\s*(.*)$/i);if(pipeFileOpMatch){let cmdletName=pipeFileOpMatch[1],afterCmdlet=pipeFileOpMatch[2].trim(),destFlagMatch=afterCmdlet.match(/-Destination\s+(\S+|"[^"]+"|'[^']+')/i);if(destFlagMatch){let path98=destFlagMatch[1].replace(/^["']|["']$/g,"");results.push({category:"builtin_write",operator:cmdletName,path:path98})}else{let nonFlagTokens=(afterCmdlet.match(/(?:[^\s"-]+|"[^"]*"|'[^']*'|-[^\s]+)/g)??[]).filter((t)=>!t.startsWith("-")&&t.length>0);if(nonFlagTokens.length>0){let path98=nonFlagTokens[nonFlagTokens.length-1].replace(/^["']|["']$/g,"");results.push({category:"builtin_write",operator:cmdletName,path:path98})}}}return results}function tokenizeCmdArguments(command){let tokens=[],current="",inDoubleQuote=!1;for(let index=0;index<command.length;index++){let character=command[index];if(character==="^"&&!inDoubleQuote){if(index+1<command.length)current+=command[++index];continue}if(character==='"'){inDoubleQuote=!inDoubleQuote;continue}if(/\s/.test(character)&&!inDoubleQuote){if(current)tokens.push(current),current="";continue}current+=character}if(current)tokens.push(current);return tokens}function detectCmdRedirects(command){let results=[],inDoubleQuote=!1,isTokenBoundary=(character)=>character===void 0||/[;\s&|()]/.test(character);for(let index=0;index<command.length;index++){let character=command[index];if(character==="^"&&!inDoubleQuote){index++;continue}if(character==='"'){inDoubleQuote=!inDoubleQuote;continue}if(inDoubleQuote||character!==">")continue;let operator=command[index+1]===">"?">>":">",cursor=index+operator.length;while(/\s/.test(command[cursor]??""))cursor++;if(command[cursor]==="&"){cursor++;while(/\s/.test(command[cursor]??""))cursor++;let descriptorStart=cursor;while(/\d/.test(command[cursor]??""))cursor++;if(command.slice(descriptorStart,cursor)&&isTokenBoundary(command[cursor])){index=Math.max(index,cursor-1);continue}results.push({category:"redirect",operator,path:null}),index=Math.max(index,cursor-1);continue}let pathValue=null;if(cursor<command.length){let quote=command[cursor];if(quote==='"'){let closingQuote=command.indexOf(quote,cursor+1);if(closingQuote!==-1)pathValue=command.slice(cursor+1,closingQuote),cursor=closingQuote+1}else{let pathStart=cursor;while(cursor<command.length&&!/[\s&|()<>]/.test(command[cursor]??""))cursor++;if(cursor>pathStart)pathValue=command.slice(pathStart,cursor)}}results.push({category:"redirect",operator,path:pathValue}),index=Math.max(index,cursor-1)}if(inDoubleQuote)results.push({category:"redirect",operator:">",path:null});return results}function detectCmdWrites(command){let results=[],trimmed=command.trim();if(!trimmed)return results;let innerCommand=trimmed,cmdWrapperMatch=trimmed.match(new RegExp(`${CMD_STRIP_PREFIX.source}(.*)$`,"i"));if(cmdWrapperMatch){if(innerCommand=cmdWrapperMatch[1].trim(),innerCommand.startsWith('"')&&innerCommand.endsWith('"')||innerCommand.startsWith("'")&&innerCommand.endsWith("'"))innerCommand=innerCommand.slice(1,-1)}if(/^(?:powershell|pwsh)(?:\.exe)?\s+/i.test(innerCommand))results.push(...detectPowerShellWrites(innerCommand));results.push(...detectCmdRedirects(innerCommand));function detectCmdCopy(cmd){let commandMatch=cmd.match(new RegExp(`^${CMD_BUILTIN_PREFIX.source}copy(?=\\s|$)`,"i"));if(commandMatch){let start=(commandMatch.index??0)+commandMatch[0].length,positional=tokenizeCmdArguments(cmd.slice(start)).filter((token)=>!_CMD_COPY_MOVE_SWITCHES.has(token.toLowerCase()));if(positional.length<2)return null;return{category:"builtin_write",operator:"copy",path:positional[positional.length-1]}}return null}function detectCmdMove(cmd){let commandMatch=cmd.match(new RegExp(`^${CMD_BUILTIN_PREFIX.source}move(?=\\s|$)`,"i"));if(commandMatch){let start=(commandMatch.index??0)+commandMatch[0].length,positional=tokenizeCmdArguments(cmd.slice(start)).filter((token)=>!_CMD_COPY_MOVE_SWITCHES.has(token.toLowerCase()));if(positional.length<2)return null;return{category:"builtin_write",operator:"move",path:positional[positional.length-1]}}return null}let copyResult=detectCmdCopy(innerCommand);if(copyResult)results.push(copyResult);let moveResult=detectCmdMove(innerCommand);if(moveResult)results.push(moveResult);let renMatch=innerCommand.match(/^ren\s+(\S+|"[^"]+"|'[^']+')\s+(\S+|"[^"]+"|'[^']+')/i);if(renMatch){let dest=(renMatch[2]||"").replace(/^["']|["']$/g,"");if(dest)results.push({category:"builtin_write",operator:"ren",path:dest})}function detectCmdDel(cmd){let delMatch=cmd.match(/^del\s+/i);if(!delMatch)return null;let tokens=(cmd.slice(delMatch[0].length).trim().match(/(\/?[^\s]+|"[^"]*"|'[^']*')/g)??[]).filter((t)=>!t.startsWith("/"));if(tokens.length>0)return{category:"builtin_write",operator:"del",path:tokens[0].replace(/^["']|["']$/g,"")};return null}let delResult=detectCmdDel(innerCommand);if(delResult)results.push(delResult);let rdMatch=innerCommand.match(/^rd\s+(?:\/s\s+|\/q\s+)*(\S+)/i);if(rdMatch){let path98=rdMatch[1].replace(/^["']|["']$/g,"");if(!path98.startsWith("/"))results.push({category:"builtin_write",operator:"rd",path:path98})}let mdMatch=trimmed.match(/^md\s+(\S+)/i);if(mdMatch){let path98=mdMatch[1].replace(/^["']|["']$/g,"");if(!path98.startsWith("/"))results.push({category:"builtin_write",operator:"md",path:path98})}return results}function detectInteractiveSession(command,shell){if(!command||typeof command!=="string")return!1;let trimmed=command.trim();if(shell==="posix"){let lower=trimmed.toLowerCase();if(/^watch(\s|$)/.test(lower))return!0;if(/^screen(\s|$)/.test(lower))return!0;if(/^tmux(\s+new-session(\s+.*)?)?$/.test(lower))return!0}else if(shell==="powershell"){if(/^Start-Process\s/i.test(trimmed))return!0}return!1}function detectPosixWrites(command){if(!command||typeof command!=="string")return{writes:[],hasWrites:!1};if(unsafeShellCommandTextReason(command))return{writes:[{category:"interpreter_eval",operator:"unsafe command text",path:null}],hasWrites:!0,parseError:!0};let ast,parseFailed=!1;try{ast=import_bash_parser.default(command,{mode:"posix",insertLOC:!0}),annotateRawWordText(ast,command)}catch{parseFailed=!0}let allWrites=[],cwdNeutral=!1;if(!parseFailed&&ast&&typeof ast==="object"){let leafCommands=[];collectLeafCommands(ast,leafCommands),cwdNeutral=leafCommands.every(isCwdNeutralLeaf);for(let cmd of leafCommands)allWrites.push(...detectRedirects(cmd)),allWrites.push(...detectBuiltinWrites(cmd)),allWrites.push(...detectInplaceEdit(cmd)),allWrites.push(...detectInterpreterEval(cmd)),allWrites.push(...detectNetworkDownloaders(cmd)),allWrites.push(...detectArchiveExtract(cmd)),allWrites.push(...detectGitDestructive(cmd))}if(parseFailed){let procSubWrites=detectProcessSubstitutionWrites(command);allWrites.push(...procSubWrites)}let writes=dedupeWriteTargets(allWrites);if(!PLAIN_COMMAND_LINE.test(command))writes=writes.map(withoutEmptyDirectoryRemoval);if(!cwdNeutral)writes=writes.map(withoutEmptyDirectoryRemoval);return{writes,hasWrites:writes.length>0,parseError:parseFailed&&writes.length===0?!0:void 0}}function isCwdNeutralLeaf(node){if(node.type!=="Command")return CWD_TRANSPARENT_NODE_TYPES.has(node.type);let name=getCommandName(node);if(name!==null)return CWD_NEUTRAL_COMMANDS.has(name);let prefix=node.prefix??[];return Array.isArray(prefix)&&prefix.every((entry)=>{if(!entry||typeof entry!=="object")return!1;let type=entry.type;return type==="AssignmentWord"||type==="Redirect"})}function detectWindowsWrites(command,shell){if(!command||typeof command!=="string")return{writes:[],hasWrites:!1};if(unsafeShellCommandTextReason(command))return{writes:[{category:"interpreter_eval",operator:"unsafe command text",path:null}],hasWrites:!0,parseError:!0};try{let subCommands=splitWindowsCommands(command,shell),allWrites=[];for(let subCmd of subCommands){let psWrites=detectPowerShellWrites(subCmd),psFiltered=shell==="powershell"?psWrites:psWrites.filter((w)=>w.operator!=="working-directory mutation");allWrites.push(...psFiltered);let cmdWrites=detectCmdWrites(subCmd),cmdFiltered=shell==="powershell"?cmdWrites.filter((w)=>w.category!=="redirect"):cmdWrites;allWrites.push(...cmdFiltered)}let stripQuotes2=(p)=>p===null||p===void 0?p:p.replace(/^['"]+/,"").replace(/['"]+$/,""),seen=new Set,seenStripped=[],writes=allWrites.filter((wt)=>{let key2=buildDedupeKey(wt.category,wt.operator,wt.path);if(seen.has(key2))return!1;let stripped=stripQuotes2(wt.path);if(stripped!==wt.path){if(seenStripped.some((other)=>other.category===wt.category&&other.operator===wt.operator&&stripQuotes2(other.path)===stripped))return!1}return seen.add(key2),seenStripped.push({category:wt.category,operator:wt.operator,path:wt.path}),!0});return{writes,hasWrites:writes.length>0}}catch{return{writes:[],hasWrites:!1,parseError:!0}}}function isDynamicPath(pathText){if(pathText===null||pathText===void 0)return!1;if(/\$[A-Za-z_][A-Za-z0-9_]*/.test(pathText))return!0;if(/\$\{[^}]+\}/.test(pathText))return!0;if(/%[A-Za-z_][A-Za-z0-9_]*%/.test(pathText))return!0;if(/\$\([^)]+\)/.test(pathText))return!0;if(/`[^`]+`/.test(pathText))return!0;if(/^~(?:[^/\\\s]*)?(?:[/\\]|$)/.test(pathText))return!0;if(/%~[A-Za-z]*(?:\d+|\*)/.test(pathText))return!0;if(/%(?:\d+|\*)/.test(pathText))return!0;return!1}function resolvePath(pathText,cwd){if(pathText===null)return null;if(isDynamicPath(pathText))return null;if(/^[a-zA-Z]:[\\\\/]/.test(cwd)||cwd.includes("\\"))return path97.win32.resolve(cwd,pathText);let normalizedRelativeWindowsPath=!path97.posix.isAbsolute(pathText)&&!/^[a-zA-Z]:[\\/]/.test(pathText)?pathText.replace(/\\/g,"/"):pathText;return path97.posix.resolve(cwd,normalizedRelativeWindowsPath)}function getCdTarget(cmd){if(!cmd||typeof cmd!=="object")return null;let c=cmd;if(c.type!=="SimpleCommand"&&c.type!=="Command")return null;let name=c.name;if(!name||typeof name!=="object")return null;let n=name;if(n.type!=="Word")return null;if(n.text!=="cd")return null;let suffix=c.suffix;if(!Array.isArray(suffix)||suffix.length===0)return null;let first=suffix[0];if(!first||typeof first!=="object")return null;let firstWord=first;if(firstWord.type!=="Word")return null;let target=firstWord.text;if(target==="-"||target==="~"||target==="~/")return null;return target}function collectWritesWithNodes(node,out,cwdStack){if(!node||typeof node!=="object")return;switch(node.type){case"Script":{let _globalCwd=cwdStack[0]??"/";if(Array.isArray(node.commands))for(let cmd of node.commands)collectWritesWithNodes(cmd,out,cwdStack);break}case"Subshell":{let effectiveCwd=cwdStack[0]??"/",subshellRedirs=node.redirections;if(Array.isArray(subshellRedirs))for(let redirect of subshellRedirs){let writesFromRedirect=getWritesFromRedirectNode(redirect,effectiveCwd);for(let w of writesFromRedirect)out.push({write:w,context:effectiveCwd})}if(node.list){let subStack=[...cwdStack];collectWritesWithNodes(node.list,out,subStack)}break}case"CompoundList":{if(Array.isArray(node.commands)){let currentStack=cwdStack;for(let cmd of node.commands){let cdTarget=getCdTarget(cmd);if(cdTarget)currentStack[0]=path97.posix.resolve(currentStack[0]??"/",cdTarget);else collectWritesWithNodes(cmd,out,currentStack)}}break}case"Pipeline":case"Sequence":{if(Array.isArray(node.commands))for(let cmd of node.commands)collectWritesWithNodes(cmd,out,cwdStack);break}case"LogicalExpression":{if(node.left){collectWritesWithNodes(node.left,out,cwdStack);let leftContext=cwdStack[0]??"/";if(node.right){let rightStack=[leftContext];collectWritesWithNodes(node.right,out,rightStack)}}break}case"And":case"Or":{if(node.left){collectWritesWithNodes(node.left,out,cwdStack);let leftContext=cwdStack[0]??"/";if(node.right){let rightStack=[leftContext];collectWritesWithNodes(node.right,out,rightStack)}}break}case"If":{let effectiveCwd=cwdStack[0]??"/";if(Array.isArray(node.redirections))for(let redirect of node.redirections)for(let w of getWritesFromRedirectNode(redirect,effectiveCwd))out.push({write:w,context:effectiveCwd});for(let body of[node.clause,node.then,node.else])if(body)collectWritesWithNodes(body,out,[...cwdStack]);break}case"While":case"Until":{let effectiveCwd=cwdStack[0]??"/";if(Array.isArray(node.redirections))for(let redirect of node.redirections)for(let w of getWritesFromRedirectNode(redirect,effectiveCwd))out.push({write:w,context:effectiveCwd});if(node.clause)collectWritesWithNodes(node.clause,out,[...cwdStack]);if(node.do)collectWritesWithNodes(node.do,out,[...cwdStack]);break}case"For":{let effectiveCwd=cwdStack[0]??"/";if(Array.isArray(node.redirections))for(let redirect of node.redirections)for(let w of getWritesFromRedirectNode(redirect,effectiveCwd))out.push({write:w,context:effectiveCwd});if(node.do)collectWritesWithNodes(node.do,out,[...cwdStack]);break}case"Case":{let effectiveCwd=cwdStack[0]??"/";if(Array.isArray(node.redirections))for(let redirect of node.redirections)for(let w of getWritesFromRedirectNode(redirect,effectiveCwd))out.push({write:w,context:effectiveCwd});if(Array.isArray(node.cases)){for(let entry of node.cases)if(entry?.body)collectWritesWithNodes(entry.body,out,[...cwdStack])}break}case"Function":{let effectiveCwd=cwdStack[0]??"/";if(Array.isArray(node.redirections))for(let redirect of node.redirections)for(let w of getWritesFromRedirectNode(redirect,effectiveCwd))out.push({write:w,context:effectiveCwd});if(node.body)collectWritesWithNodes(node.body,out,[...cwdStack]);break}case"Command":case"SimpleCommand":{let effectiveCwd=cwdStack[0]??"/",cdTarget=getCdTarget(node);if(cdTarget){cwdStack[0]=path97.posix.resolve(cwdStack[0]??"/",cdTarget);return}let writesFromRedirs=getWritesFromCommandRedirs(node,effectiveCwd);for(let w of writesFromRedirs)out.push({write:w,context:effectiveCwd});let builtinWrites=detectBuiltinWrites(node);for(let w of builtinWrites)out.push({write:w,context:effectiveCwd});let inplaceWrites=detectInplaceEdit(node);for(let w of inplaceWrites)out.push({write:w,context:effectiveCwd});let interpreterWrites=detectInterpreterEval(node);for(let w of interpreterWrites)out.push({write:w,context:effectiveCwd});let networkWrites=detectNetworkDownloaders(node);for(let w of networkWrites)out.push({write:w,context:effectiveCwd});let archiveWrites=detectArchiveExtract(node);for(let w of archiveWrites)out.push({write:w,context:effectiveCwd});let gitWrites=detectGitDestructive(node);for(let w of gitWrites)out.push({write:w,context:effectiveCwd});break}}}function getWritesFromRedirectNode(redirect,_context){if(!redirect||typeof redirect!=="object")return[];let r=redirect,opNode=r.op;if(!opNode||typeof opNode!=="object")return[];let opType=opNode.type?.toUpperCase();if(!opType||!REDIRECT_ALL_WRITE_TOKENS.has(opType))return[];let fileNode=r.file,path98=extractRedirectPath(fileNode),opLabel=operatorLabel(opNode);if(REDIRECT_WRITE_TOKENS.has(opType)||REDIRECT_GREATAND_TOKENS.has(opType)&&!isNonFileGreatAndTarget(path98)){if(path98!==null&&isNullDevice(path98))return[];return[{category:"redirect",operator:opLabel,path:path98}]}else if(REDIRECT_HERE_TOKENS.has(opType))return[{category:"here_doc",operator:opLabel,path:path98}];return[]}function getWritesFromCommandRedirs(cmd,context){if(!cmd||typeof cmd!=="object")return[];let c=cmd,results=[];results.push(...detectHereDocMarkers(cmd));let{suffix,prefix}=c;if(Array.isArray(suffix)){for(let item of suffix)if(isRedirectNode(item)){let writes=getWritesFromRedirectNode(item,context);results.push(...writes)}}if(Array.isArray(prefix)){for(let item of prefix)if(isRedirectNode(item)){let writes=getWritesFromRedirectNode(item,context);results.push(...writes)}}return results}function resolveWriteTargets(command,writes,cwd){if(!writes||writes.length===0)return[];if(!command||typeof command!=="string")return writes.map((original)=>({original,resolvedPath:resolvePath(original.path,cwd),resolved:original.path!==null&&!isDynamicPath(original.path)}));let ast;try{ast=import_bash_parser.default(command,{mode:"posix",insertLOC:!0}),annotateRawWordText(ast,command)}catch{ast=null}if(!ast||typeof ast!=="object")return writes.map((original)=>({original,resolvedPath:resolvePath(original.path,cwd),resolved:original.path!==null&&!isDynamicPath(original.path)}));let cwdStack=[cwd],writesWithNodes=[];collectWritesWithNodes(ast,writesWithNodes,cwdStack);let seen=new Set,collidingKeys=new Set,deduplicated=writesWithNodes.filter((wwn)=>{let key2=buildDedupeKey(wwn.write.category,wwn.write.operator,wwn.write.path);if(seen.has(key2))return collidingKeys.add(key2),!1;return seen.add(key2),!0}),inputKeys=new Set;for(let write of writes){let key2=buildDedupeKey(write.category,write.operator,write.path);if(inputKeys.has(key2))collidingKeys.add(key2);inputKeys.add(key2)}let resolvedMap=new Map;for(let{write,context}of deduplicated){let resolvedPath=resolvePath(write.path,context),resolved=write.path!==null&&!isDynamicPath(write.path),key2=buildDedupeKey(write.category,write.operator,write.path);resolvedMap.set(key2,{resolvedPath,resolved})}return writes.map((input)=>{let key2=buildDedupeKey(input.category,input.operator,input.path),original=collidingKeys.has(key2)?withoutEmptyDirectoryRemoval(input):input,resolved=resolvedMap.get(key2);if(resolved)return{original,resolvedPath:resolved.resolvedPath,resolved:resolved.resolved};return{original,resolvedPath:resolvePath(original.path,cwd),resolved:original.path!==null&&!isDynamicPath(original.path)}})}var import_bash_parser,REDIRECT_WRITE_TOKENS,REDIRECT_HERE_TOKENS,REDIRECT_GREATAND_TOKENS,REDIRECT_ALL_WRITE_TOKENS,BUILTIN_WRITE_COMMANDS,BARE_RMDIR_OPERAND,INPLACE_EDIT_COMMANDS,SED_LONG_SWITCHES,AWK_LONG_SWITCHES,INTERPRETER_EVAL_COMMANDS,NETWORK_DOWNLOAD_COMMANDS,ARCHIVE_EXTRACT_COMMANDS,GIT_COMMAND="git",POWERSHELL_WRITE_CMDLETS,AMBIGUOUS_WRITE_ALIASES,POWERSHELL_READ_ONLY_COMMANDS,POSIX_WRITE_TOKENS,READ_ONLY_SCRIPT_BLOCK_OPERATORS,RAW_WORD_TEXT,BRACE_EXPANSION,PARSER_CHAR_ESCAPES,_CMD_COPY_MOVE_SWITCHES,PLAIN_COMMAND_LINE,CWD_NEUTRAL_COMMANDS,CWD_TRANSPARENT_NODE_TYPES;var init_shell_write_detect=__esm(()=>{init_path_identity();init_shell_executor_context();import_bash_parser=__toESM(require_src(),1);REDIRECT_WRITE_TOKENS=new Set(["GREAT","DGREAT","CLOBBER","LESSGREAT"]),REDIRECT_HERE_TOKENS=new Set(["DLESS","DLESSDASH"]),REDIRECT_GREATAND_TOKENS=new Set(["GREATAND"]),REDIRECT_ALL_WRITE_TOKENS=new Set([...REDIRECT_WRITE_TOKENS,...REDIRECT_HERE_TOKENS,...REDIRECT_GREATAND_TOKENS]),BUILTIN_WRITE_COMMANDS=new Set(["cp","mv","install","ln","truncate","unlink","rmdir"]),BARE_RMDIR_OPERAND=/^[^-*?[\]{}$`~"'\\#\s][^*?[\]{}$`~"'\\#\s]*$/;INPLACE_EDIT_COMMANDS=new Set(["sed","perl","awk"]),SED_LONG_SWITCHES=new Set(["--quiet","--silent","--debug","--follow-symlinks","--binary","--posix","--regexp-extended","--separate","--sandbox","--unbuffered","--null-data","--zero-terminated","--help","--version"]),AWK_LONG_SWITCHES=new Set(["--posix","--traditional","--lint","--re-interval","--sandbox","--version","--help"]),INTERPRETER_EVAL_COMMANDS=new Set(["python","python3","python2","node","bun","ruby","perl","php","bash","sh","dash","zsh","ksh","eval"]),NETWORK_DOWNLOAD_COMMANDS=new Set(["curl","wget","scp"]),ARCHIVE_EXTRACT_COMMANDS=new Set(["tar","unzip","gunzip","gzip","bzip2","xz","7z","rar"]),POWERSHELL_WRITE_CMDLETS=new Set(["set-content","add-content","out-file","clear-content","copy-item","move-item","remove-item","new-item","ni","ac","sc","epcsv"]),AMBIGUOUS_WRITE_ALIASES=new Set(["cp","cpi","mv","rm","del","ren","rd","md","type"]),POWERSHELL_READ_ONLY_COMMANDS=new Set(["get-content","gc","get-item","gi","get-childitem","gci","get-location","pwd","get-command","get-member","get-date","get-help","get-itemproperty","select-string","select-object","where-object","foreach-object","sort-object","group-object","measure-object","compare-object","resolve-path","test-path","format-table","out-string","write-output","write-host","write-verbose","write-warning"]),POSIX_WRITE_TOKENS=new Set(["cp","mv","rm","rmdir","tee","dd","ln","touch","truncate","unlink","install"]);READ_ONLY_SCRIPT_BLOCK_OPERATORS=new Set(["-gt","-ge","-lt","-le","-eq","-ne","-match","-notmatch","-like","-notlike","-replace","-contains","-notcontains","-in","-notin","-is","-isnot","-join","-split","-f","-band","-bor","-bnot","-shl","-shr","-and","-or","-not","-xor"].map((op)=>op.toLowerCase()));RAW_WORD_TEXT=new WeakMap;BRACE_EXPANSION=/\{[^{}]*(?:,|\.\.)[^{}]*\}/;PARSER_CHAR_ESCAPES={t:"\t",n:`
|
|
1178
|
-
`,r:"\r",b:"\b",f:"\f",v:"\v"};_CMD_COPY_MOVE_SWITCHES=new Set(["/a","/b","/d","/f","/n","/v","/y","/-y","/z"]);PLAIN_COMMAND_LINE=/^[A-Za-z0-9 \t\n_./=&|;<>-]*$/,CWD_NEUTRAL_COMMANDS=new Set(["rmdir","mkdir","echo","true","false","test"]),CWD_TRANSPARENT_NODE_TYPES=new Set(["CompoundList","If","While","Until","For"])});import*as fs61 from"node:fs";import*as path98 from"node:path";function extractFilename(code,language,index){let lines=code.trim().split(`
|
|
1175
|
+
`)return{nextReduction:reducers.start,nextState:state2.setEscaping(!1).removeLastChar()};if(!state2.escaping&&char==="\\")return{nextReduction:reducers.start,nextState:state2.setEscaping(!0).appendChar(char)};if(!state2.escaping&&char==="'")return{nextReduction:reducers.singleQuoting,nextState:state2.appendChar(char)};if(!state2.escaping&&char==='"')return{nextReduction:reducers.doubleQuoting,nextState:state2.appendChar(char)};if(!state2.escaping&&char==="$")return{nextReduction:reducers.expansionStart,nextState:state2.appendChar(char).appendEmptyExpansion()};if(!state2.escaping&&char==="`")return{nextReduction:reducers.expansionCommandTick,nextState:state2.appendChar(char).appendEmptyExpansion()};return{nextReduction:reducers.start,nextState:state2.appendChar(char).setEscaping(!1)}}module.exports={inherits:"posix",init:(posixMode)=>{let phaseCatalog=posixMode.phaseCatalog,lexerPhases=[convertToWord,phaseCatalog.parameterExpansion,phaseCatalog.arithmeticExpansion,phaseCatalog.commandExpansion,phaseCatalog.tildeExpanding,phaseCatalog.parameterExpansion.resolve,phaseCatalog.commandExpansion.resolve,phaseCatalog.arithmeticExpansion.resolve,phaseCatalog.fieldSplitting.split,phaseCatalog.pathExpansion,phaseCatalog.quoteRemoval,phaseCatalog.defaultNodeType],reducers=Object.assign({},posixMode.tokenizer.reducers,{start});return Object.assign({},posixMode,{lexerPhases,tokenizer:()=>posixMode.tokenizer({},reducers)})}}});var require_src=__commonJS((exports,module)=>{var shellLexer=require_shell_lexer(),utils=require_utils2(),modes={bash:require_bash(),posix:require_posix(),"word-expansion":require_word_expansion()};function loadPlugin(name){let modePlugin=modes[name];if(modePlugin.inherits)return modePlugin.init(loadPlugin(modePlugin.inherits),utils);return modePlugin.init(null,utils)}module.exports=function(sourceCode,options){try{options=options||{},options.mode=options.mode||"posix";let mode=loadPlugin(options.mode),Parser=mode.grammar.Parser,astBuilder=mode.astBuilder,parser=new Parser;return parser.lexer=shellLexer(mode,options),parser.yy=astBuilder(options),parser.parse(sourceCode)}catch(err){if(err instanceof SyntaxError)throw err;throw Error(err.stack||err.message)}}});import*as path97 from"node:path";function unsafeShellCommandTextReason(value){return unsafePathTextReason(value.replace(/[\r\n]/g,""))}function mergeWriteAnalyses(primary,additional,additionalIsAuthoritative=!0,wrapperDeclared=!1){if(additional.writes.length===0&&!additional.hasWrites)return primary;let posixAuthoritative=wrapperDeclared?!1:!additionalIsAuthoritative||!primary.parseError,authority=posixAuthoritative?primary:additional,supplementary=posixAuthoritative?additional:primary,authorityConstructs=new Set(authority.writes.map((write)=>`${write.category}|${write.operator}`)),authorityKeys=new Set(authority.writes.map((write)=>buildDedupeKey(write.category,write.operator,write.path))),stripQuotes2=(p)=>p===null||p===void 0?p:p.replace(/^['"]+/,"").replace(/['"]+$/,""),isQuoteArtifact=(write)=>{let stripped=stripQuotes2(write.path);if(stripped===write.path)return!1;return authority.writes.some((other)=>other.category===write.category&&other.operator===write.operator&&stripQuotes2(other.path)===stripped)},keptIndex=new Map,writes=[],demoteKept=(key2)=>{let index=keptIndex.get(key2);if(index!==void 0)writes[index]=withoutEmptyDirectoryRemoval(writes[index])};for(let write of[...authority.writes,...supplementary.writes]){let key2=buildDedupeKey(write.category,write.operator,write.path);if(supplementary.writes.includes(write))if(wrapperDeclared){let construct=`${write.category}|${write.operator}`;if(authorityConstructs.has(construct))continue}else{if(authorityKeys.has(key2)){demoteKept(key2);continue}if(isQuoteArtifact(write))continue}if(keptIndex.has(key2)){demoteKept(key2);continue}keptIndex.set(key2,writes.length),writes.push(write)}return{writes,hasWrites:writes.length>0||primary.hasWrites||additional.hasWrites,parseError:primary.parseError}}function buildDedupeKey(category,operator,path98){return`${category}|${operator}|${path98??"null"}`}function withoutEmptyDirectoryRemoval(write){if(write.emptyDirectoryRemoval!==!0)return write;let{emptyDirectoryRemoval:_dropped,...rest}=write;return rest}function isBareRmdirOperand(word){return BARE_RMDIR_OPERAND.test(word)&&!word.split("/").includes("..")}function unquotedWordTokens(command){let tokens=[],current="",quote=null,flush=()=>{if(current.length>0)tokens.push(current);current=""};for(let i=0;i<command.length;i+=1){let ch=command[i];if(quote){if(ch===quote)quote=null;continue}if(ch==='"'||ch==="'"){flush(),quote=ch;continue}if(/\s/.test(ch)){flush();continue}current+=ch}return flush(),tokens.map((token)=>token.replace(/^[({]+/,"").replace(/[)}]+$/,""))}function isPowerShellShaped(command){if(!command)return!1;return unquotedWordTokens(command).some((token)=>{let lower=token.toLowerCase();return POWERSHELL_WRITE_CMDLETS.has(lower)||POWERSHELL_READ_ONLY_COMMANDS.has(lower)})}function isReadOnlyScriptBlockBody(body){if(/[()[\]=@|`;]/.test(body)||body.includes("::")||body.includes("$("))return!1;let tokens=body.match(/"[^"]*"|'[^']*'|\S+/g)?.map((token)=>token.replace(/^[({]+/,"").replace(/[)}]+$/,""))??[];if(tokens.length===0)return!1;for(let token of tokens){if(token===",")continue;if(/^(?:"[^"]*"|'[^']*')$/.test(token))continue;if(/^-?\d+(?:\.\d+)?$/.test(token))continue;if(READ_ONLY_SCRIPT_BLOCK_OPERATORS.has(token.toLowerCase()))continue;if(/^(?:\$_|\$this)(?:\.[A-Za-z_]\w*)*$/.test(token))continue;return!1}return!0}function extractScriptBlockBodies(command){let bodies=[],depth=0,start=-1,quote=null;for(let i=0;i<command.length;i+=1){let ch=command[i];if(quote){if(ch===quote)quote=null;continue}if(ch==='"'||ch==="'"){quote=ch;continue}if(ch==="{"){if(depth===0)start=i+1;depth+=1;continue}if(ch==="}"){if(depth-=1,depth<0)return null;if(depth===0&&start>=0)bodies.push(command.slice(start,i)),start=-1}}if(quote!==null||depth!==0)return null;return bodies}function isPowerShellReadOnlyPipeline(command){if(!command)return!1;if(/[>;&`\r\n]/.test(command)||/\$\(/.test(command))return!1;let quote=null,braceDepth=0;for(let ch of command){if(quote){if(ch===quote)quote=null;continue}if(ch==='"'||ch==="'"){quote=ch;continue}if(ch==="{")braceDepth+=1;if(ch==="}")braceDepth-=1;if(braceDepth<0)return!1}if(quote!==null||braceDepth!==0)return!1;for(let token of unquotedWordTokens(command)){let lower=token.toLowerCase();if(POWERSHELL_WRITE_CMDLETS.has(lower)||AMBIGUOUS_WRITE_ALIASES.has(lower)||POSIX_WRITE_TOKENS.has(lower))return!1;if((token==="sed"||token==="perl"||token==="awk")&&/(^|[\s'"])--?[a-zA-Z-]*(?:\bi|\bin-place|\bpi)\b/.test(command))return!1}let bodies=extractScriptBlockBodies(command);if(bodies===null)return!1;for(let body of bodies)if(!isReadOnlyScriptBlockBody(body))return!1;let segments=[],current="";quote=null;for(let i=0;i<command.length;i+=1){let ch=command[i];if(quote){if(ch===quote)quote=null;current+=ch;continue}if(ch==='"'||ch==="'"){quote=ch,current+=ch;continue}if(ch==="|"){segments.push(current),current="";continue}current+=ch}segments.push(current);for(let segment of segments){let tokens=unquotedWordTokens(segment.trim());if(tokens.length===0)return!1;if(!POWERSHELL_READ_ONLY_COMMANDS.has(tokens[0].toLowerCase()))return!1}return segments.length>0}function detectProcessSubstitutionWrites(command){let results=[],writeProcSubPattern=/>\s*\(([^)]+)\)/g;while(!0){let match=writeProcSubPattern.exec(command);if(match===null)break;let innerCommand=match[1].trim();if(!innerCommand)continue;let stages=innerCommand.split("|").map((s)=>s.trim());for(let stage of stages){let builtinResult=detectBuiltinWritesFromString(stage);if(builtinResult)results.push(builtinResult);let appendMatch=stage.match(/^\s*(.*?)\s*>>(\s*)(\S+)\s*$/);if(appendMatch){let path98=appendMatch[3];if(path98&&!isNullDevice(path98))results.push({category:"redirect",operator:">>",path:path98})}else{let writeMatch=stage.match(/^\s*(.*?)\s*>(?!>)(\s*)(\S+)\s*$/);if(writeMatch){let path98=writeMatch[3];if(path98&&!isNullDevice(path98))results.push({category:"redirect",operator:">",path:path98})}}}}return results}function detectBuiltinWritesFromString(cmd){let tokens=cmd.trim().split(/\s+/);if(tokens.length===0)return null;let name=tokens[0].toLowerCase();if(name==="rmdir"&&tokens.some((token)=>/^\/(?:s|q)$/i.test(token)))return null;if(BUILTIN_WRITE_COMMANDS.has(name)){for(let i=tokens.length-1;i>=1;i--)if(!tokens[i].startsWith("-"))return{category:"builtin_write",operator:name,path:tokens[i]}}return null}function wordText(node){if(!node||typeof node!=="object")return null;if(isBashWord(node))return node.text;return null}function isBashWord(node){return!!node&&typeof node==="object"&&node.type==="Word"&&typeof node.text==="string"}function annotateRawWordText(node,source){let unitIndex=null;if(/[\uD800-\uDFFF]/.test(source)){unitIndex=[];let u=0;for(let cp2 of source)unitIndex.push(u),u+=cp2.length;unitIndex.push(u)}let toUnit=(cp2)=>unitIndex===null?cp2:unitIndex[cp2],stack=[node],seen=new Set;while(stack.length>0){let n=stack.pop();if(!n||typeof n!=="object"||seen.has(n))continue;if(seen.add(n),isBashWord(n)){let loc=n.loc,start=loc?.start?.char,end=loc?.end?.char;if(typeof start==="number"&&typeof end==="number"&&end>=start){let from=toUnit(start),to=toUnit(end+1);if(from!==void 0&&to!==void 0)RAW_WORD_TEXT.set(n,source.slice(from,to))}}for(let value of Object.values(n))if(value&&typeof value==="object")stack.push(value)}}function hasUnquotedGlob(word){let projection=unquotedProjection(word);return projection===null||/[*?[]/.test(projection)}function hasUnquotedBraceExpansion(word,text){let projection=unquotedProjection(word);return BRACE_EXPANSION.test(projection===null?text:projection)}function unquotedProjection(word){if(!word||typeof word!=="object")return null;let raw=RAW_WORD_TEXT.get(word);if(raw===void 0)return null;let{projection,dequoted}=scanQuoting(raw),hasExpansion=Array.isArray(word.expansion)&&(word.expansion.length??0)>0,text=word.text;if(!hasExpansion&&dequoted!==text&&decodeParserEscapes(dequoted)!==text)return null;return projection}function scanQuoting(raw){let state2="none",projection="",dequoted="";for(let c=0;c<raw.length;c++){let ch=raw[c];if(state2==="single")if(ch==="'")state2="none";else dequoted+=ch,projection+="\x00";else if(ch==="\\"){let next=raw[c+1]??"";if(state2==="double"&&!/[$`"\\\n]/.test(next)){dequoted+=ch,projection+="\x00";continue}if(next!==`
|
|
1176
|
+
`)dequoted+=next,projection+="\x00";c++}else if(ch==='"')state2=state2==="double"?"none":"double";else if(state2==="none"&&ch==="'")state2="single";else dequoted+=ch,projection+=state2==="none"?ch:"\x00"}return{projection,dequoted}}function decodeParserEscapes(s){return s.replace(/\\(?:x([0-9A-Fa-f]{2})|u([0-9A-Fa-f]{4})|U([0-9A-Fa-f]{8})|([0-7]{1,3})|([\\tnrbfv"']))/g,(m,x,u,big,octal,c)=>{let hex5=x??u??big;if(hex5!==void 0){let cp2=Number.parseInt(hex5,16);return cp2<=1114111?String.fromCodePoint(cp2):m}if(octal!==void 0)return String.fromCodePoint(Number.parseInt(octal,8));return PARSER_CHAR_ESCAPES[c]??c})}function collectLeafCommands(node,out){if(!node||typeof node!=="object")return;switch(node.type){case"Script":if(Array.isArray(node.commands))for(let cmd of node.commands)collectLeafCommands(cmd,out);break;case"Pipeline":case"Sequence":if(Array.isArray(node.commands))for(let cmd of node.commands)collectLeafCommands(cmd,out);break;case"CompoundList":if(out.push(node),Array.isArray(node.commands))for(let cmd of node.commands)collectLeafCommands(cmd,out);break;case"LogicalExpression":if(node.left)collectLeafCommands(node.left,out);if(node.right)collectLeafCommands(node.right,out);break;case"And":case"Or":if(node.left)collectLeafCommands(node.left,out);if(node.right)collectLeafCommands(node.right,out);break;case"Subshell":if(out.push(node),node.list)collectLeafCommands(node.list,out);break;case"ProcessSubstitution":{let opNode=node.op;if(opNode&&typeof opNode==="object"){if(opNode.type?.toUpperCase()==="GREAT"){if(node.command)collectLeafCommands(node.command,out)}}}break;case"If":if(out.push(node),node.clause)collectLeafCommands(node.clause,out);if(node.then)collectLeafCommands(node.then,out);if(node.else)collectLeafCommands(node.else,out);break;case"While":case"Until":if(out.push(node),node.clause)collectLeafCommands(node.clause,out);if(node.do)collectLeafCommands(node.do,out);break;case"For":if(out.push(node),node.do)collectLeafCommands(node.do,out);break;case"Case":if(out.push(node),Array.isArray(node.cases)){for(let entry of node.cases)if(entry?.body)collectLeafCommands(entry.body,out)}break;case"Function":if(out.push(node),node.body)collectLeafCommands(node.body,out);break;default:out.push(node);break}}function getCommandName(cmd){if(!cmd||typeof cmd!=="object")return null;let c=cmd;if(typeof c.name==="string")return c.name;return wordText(c.name)}function basenameAnySep(word){return(word.split(/[\\/]/).filter(Boolean).pop()??word).replace(/\.exe$/i,"").toLowerCase()}function envFlagConsumesNextWord(token){if(token.startsWith("--")){if(ENV_FLAGS_WITH_ARG.has(token))return!0;if(token.length<3)return!1;return[...ENV_FLAGS_WITH_ARG].filter((flag)=>flag.startsWith("--")&&flag.startsWith(token)).length===1}if(token.startsWith("-")&&token.length>2){let chars=token.slice(1).split(""),argTaking=["u","U","C","S","a","P"];return chars.findIndex((c)=>argTaking.includes(c))===chars.length-1&&chars.slice(0,-1).every((c)=>!argTaking.includes(c))}return ENV_FLAGS_WITH_ARG.has(token)}function canonicalInterpreterName(cmd){let name=getCommandName(cmd);if(!name)return null;let words=[name,...getSuffixWords(cmd)],i=0;for(let hop=0;hop<words.length;hop++){let base=basenameAnySep(words[i]??"");if(base!=="env"&&base!=="command"&&base!=="exec")break;if(i+=1,base==="env")while(i<words.length){let token=words[i];if(token===void 0)break;if(envFlagConsumesNextWord(token)){i+=2;continue}if(token.startsWith("-")){i+=1;continue}if(/^[A-Za-z_][A-Za-z0-9_]*=/.test(token)){i+=1;continue}break}else while(i<words.length){let token=words[i];if(token===void 0)break;if(token==="-a"||token==="--arg0"){i+=2;continue}if(token.startsWith("-")){i+=1;continue}break}if(i>=words.length)return null}let word=words[i];if(word===void 0)return null;let full=basenameAnySep(word);if(INTERPRETER_EVAL_COMMANDS.has(full))return full;let stripped=full.replace(/\d+(\.\d+)*$/,"");if(stripped!==""&&stripped!==full&&INTERPRETER_EVAL_COMMANDS.has(stripped))return stripped;return null}function getSuffixWords(cmd){if(!cmd||typeof cmd!=="object")return[];let suffix=cmd.suffix;if(!Array.isArray(suffix))return[];let words=[];for(let s of suffix){let text=wordText(s);if(text!==null)words.push(text)}return words}function getSuffixWordExpansionFlags(cmd){if(!cmd||typeof cmd!=="object")return[];let suffix=cmd.suffix;if(!Array.isArray(suffix))return[];let flags=[];for(let s of suffix){if(!isBashWord(s))continue;let expansion=s.expansion;flags.push(Array.isArray(expansion)&&expansion.length>0)}return flags}function getSuffixWordUnquotedExpansionFlags(cmd){if(!cmd||typeof cmd!=="object")return[];let suffix=cmd.suffix;if(!Array.isArray(suffix))return[];let flags=[];for(let s of suffix){if(!isBashWord(s))continue;let expansion=s.expansion;if(!Array.isArray(expansion)||expansion.length===0){flags.push(!1);continue}let text=s.text,hasSubstitution=/\$\(|`/.test(text),hasListExpansion=/\$\{?[!#]?[A-Za-z0-9_]*(?:\[[@*]\]|@|\*)/.test(text)||/\$\{?[!#]?[@*]|\[[@*]\]/.test(text);if(hasSubstitution||hasListExpansion){flags.push(!0);continue}let quotedAt=[],state2="none";for(let c=0;c<text.length;c++){let ch=text[c];if(quotedAt[c]=state2!=="none",state2==="single"){if(ch==="'")state2="none"}else if(ch==="\\")quotedAt[c+1]=!0,c++;else if(ch==='"')state2=state2==="double"?"none":"double";else if(ch==="'"&&state2==="none")state2="single"}flags.push(expansion.some((e)=>{let start=e.loc?.start;return typeof start!=="number"||quotedAt[start]!==!0}))}return flags}function getRedirections(cmd){if(!cmd||typeof cmd!=="object")return[];let c=cmd;if(Array.isArray(c.redirections))return c.redirections;let results=[],suffix=c.suffix,prefix=c.prefix;if(Array.isArray(suffix)){for(let item of suffix)if(isRedirectNode(item))results.push(item)}if(Array.isArray(prefix)){for(let item of prefix)if(isRedirectNode(item))results.push(item)}return results}function isRedirectNode(node){return!!(node&&typeof node==="object"&&node.type==="Redirect")}function operatorLabel(op){if(!op||typeof op!=="object")return"unknown";let opType=op.type?.toUpperCase();switch(opType){case"GREAT":return">";case"DGREAT":return">>";case"CLOBBER":return">|";case"LESS":return"<";case"DLESS":return"<<";case"DLESSDASH":return"<<-";case"LESSAND":return"<&";case"GREATAND":return">&";case"LESSGREAT":return"<>";default:return opType||"unknown"}}function extractRedirectPath(fileNode){let text=wordText(fileNode);if(!text)return null;return text}function isNullDevice(path98){return path98==="/dev/null"||path98==="/dev/zero"||path98==="/dev/urandom"}function isNullDeviceWord(word,path98){if(!isNullDevice(path98)||!word||typeof word!=="object")return!1;let raw=RAW_WORD_TEXT.get(word);return raw!==void 0&&isNullDevice(scanQuoting(raw).dequoted)}function isNumeric(s){return/^\d+$/.test(s)}function isNonFileGreatAndTarget(path98){return path98!==null&&(isNumeric(path98)||path98==="-")}function detectRedirects(cmd){let results=[];results.push(...detectHereDocMarkers(cmd));let redirections=getRedirections(cmd);for(let redirect of redirections){if(!redirect||typeof redirect!=="object")continue;let r=redirect,opNode=r.op;if(!opNode||typeof opNode!=="object")continue;let opType=opNode.type?.toUpperCase();if(!opType||!REDIRECT_ALL_WRITE_TOKENS.has(opType))continue;let fileNode=r.file,path98=extractRedirectPath(fileNode),opLabel=operatorLabel(opNode);if(REDIRECT_WRITE_TOKENS.has(opType)||REDIRECT_GREATAND_TOKENS.has(opType)&&!isNonFileGreatAndTarget(path98)){if(path98!==null&&isNullDeviceWord(fileNode,path98))continue;results.push({category:"redirect",operator:opLabel,path:path98})}else if(REDIRECT_HERE_TOKENS.has(opType))results.push({category:"here_doc",operator:opLabel,path:path98})}return results}function detectHereDocMarkers(cmd){let results=[];if(!cmd||typeof cmd!=="object")return results;let suffix=cmd.suffix;if(!Array.isArray(suffix))return results;for(let item of suffix){if(!item||typeof item!=="object")continue;if(isHereDocMarker(item))results.push({category:"here_doc",operator:item.text==="<<-"?"<<-":"<<",path:null})}return results}function isHereDocMarker(node){if(!node||typeof node!=="object")return!1;let type=node.type?.toLowerCase();return type==="dless"||type==="dlessdash"}function detectBuiltinWrites(cmd){let results=[],name=getCommandName(cmd);if(!name)return results;let lowerName=name.toLowerCase();if(lowerName==="dd"){let suffixWords2=getSuffixWords(cmd);for(let word of suffixWords2)if(word.startsWith("of=")){let path98=word.slice(3);if(path98&&!isNullDevice(path98))results.push({category:"builtin_write",operator:"dd of=",path:path98})}return results}if(lowerName==="tee"){let suffixWords2=getSuffixWords(cmd),pastDoubleDash=!1;for(let word of suffixWords2){if(word==="--"){pastDoubleDash=!0;continue}if(!pastDoubleDash&&word.startsWith("-"))continue;if(word&&!isNullDevice(word))results.push({category:"builtin_write",operator:"tee",path:word})}return results}if(!BUILTIN_WRITE_COMMANDS.has(lowerName))return results;let suffixWords=getSuffixWords(cmd);if(lowerName==="rmdir"&&suffixWords.some((word)=>/^\/(?:s|q)$/i.test(word)))return results;if(lowerName==="rmdir"&&suffixWords.length===1&&isBareRmdirOperand(suffixWords[0]))return results.push({category:"builtin_write",operator:name,path:suffixWords[0],emptyDirectoryRemoval:!0}),results;if(lowerName==="truncate"){for(let word of suffixWords)if(!word.startsWith("-")&&!isNumeric(word)){results.push({category:"builtin_write",operator:"truncate",path:word});break}}else for(let i=suffixWords.length-1;i>=0;i--){let word=suffixWords[i];if(!word.startsWith("-")){results.push({category:"builtin_write",operator:name,path:word});break}}return results}function looksLikeSedScript(w){if(hasParentComponent(w)||/^[A-Za-z]:[\\/]/.test(w))return!1;return/^(?:(?:[0-9]+|\$)(?:,(?:[0-9]+|\$))?!?|!)[a-zA-Z=]$/.test(w)||/[;{}]/.test(w)&&!/[\\/:]/.test(w)&&!w.startsWith(".")||/^s([^A-Za-z0-9\s\\])(?:\\.|(?!\1)[^\\])*\1(?:\\.|(?!\1)[^\\])*\1[gpiImMe0-9]*$/.test(w)||/^y([^A-Za-z0-9\s\\])(?:\\.|(?!\1)[^\\])*\1(?:\\.|(?!\1)[^\\])*\1$/.test(w)}function hasParentComponent(w){return w.split(/[\\/]/).includes("..")}function detectInplaceEdit(cmd){let results=[],name=getCommandName(cmd);if(!name)return results;let lowerName=name.toLowerCase();if(!INPLACE_EDIT_COMMANDS.has(lowerName))return[];let suffixWords=getSuffixWords(cmd);if(!suffixWords.some((word)=>{if(lowerName==="sed")return word.startsWith("-i")&&word.length>1||/^--i(?:n(?:-(?:p(?:l(?:a(?:c(?:e)?)?)?)?)?)?)?(?:=|$)/.test(word);return word==="-i"||word.startsWith("-i")}))return[];let scriptPattern=/^[ssy]\/.*\/[gim]*$/,quotedScriptPattern=/^["'].*["']$/,isScriptShaped=(w)=>scriptPattern.test(w)&&!hasParentComponent(w),isScriptWord=(i)=>{let w=suffixWords[i];if(quotedScriptPattern.test(w))return unquotedExpansionFlags[i]!==!0&&isScriptShaped(w.slice(1,-1));return isScriptShaped(w)},flagArgs=lowerName==="sed"?new Set(["-e","-f","--expression","--file"]):lowerName==="perl"?new Set(["-e","-E"]):new Set(["-f","-e","-v","-F"]),combinedFlagArgs=/^-[0-9AacSlnpstTuUwWX]+[eE]$/,perlAttachedScript=/^-[0-9AacSlnpstTuUwWX]*[eE]./,sedScriptBundle=/^-[nrEszub]*[ef]$/,sedAttachedScript=/^-[nrEszub]*[ef]./,consumesNext=(w)=>flagArgs.has(w)||lowerName==="sed"&&sedScriptBundle.test(w)||lowerName==="perl"&&combinedFlagArgs.test(w),suppliesScript=(w)=>{if(lowerName==="awk")return w==="-f"||w==="-e"||/^-[fe]./.test(w)||w.startsWith("--file=")||w.startsWith("--source=");if(lowerName==="sed")return consumesNext(w)||sedAttachedScript.test(w)||/^--(?:expression|file)=/.test(w);return consumesNext(w)||perlAttachedScript.test(w)},expansionFlags=getSuffixWordExpansionFlags(cmd),unquotedExpansionFlags=getSuffixWordUnquotedExpansionFlags(cmd),suffixNodes=(Array.isArray(cmd.suffix)?cmd.suffix:[]).filter((s)=>wordText(s)!==null),mayExpandToSeveralWords=(i)=>unquotedExpansionFlags[i]===!0||hasUnquotedBraceExpansion(suffixNodes[i],suffixWords[i]),isKnownOption=(w)=>{if(w==="-"||w==="--")return!0;if(lowerName==="sed")return/^-[nrEszub]+$/.test(w)||/^-[nrEszub]*[ef]/.test(w)||/^-[nrEszub]*l/.test(w)||/^-i/.test(w)||SED_LONG_SWITCHES.has(w)||/^--(?:expression|file|line-length|in-place)(?:=|$)/.test(w);if(lowerName==="perl")return/^-[0-9AacSlnpstTuUwWX]*(?:[eE].*)?$/.test(w)||/^-i/.test(w)||/^-I./.test(w);return/^-[fevFil]/.test(w)||/^-[PcrSVh]$/.test(w)||AWK_LONG_SWITCHES.has(w)||/^--(?:file|source|lint)=/.test(w)},isOpaqueFlag=(i)=>suffixWords[i].startsWith("-")&&(mayExpandToSeveralWords(i)||!isKnownOption(suffixWords[i])),sedOptionArg=(w)=>lowerName==="sed"&&(/^-[nrEszub]*l$/.test(w)||w==="--line-length"),takesDetachedArg=(w)=>consumesNext(w)||sedOptionArg(w)||lowerName==="awk"&&w==="-i",fileArgOption=(w)=>lowerName==="sed"&&(/^-[nrEszub]*f$/.test(w)||w==="--file")||lowerName==="awk"&&(w==="-f"||w==="-i"),detachedArgMaySplit=(option,i)=>mayExpandToSeveralWords(i)||(fileArgOption(option)?/[*?[]/.test(suffixWords[i]):hasUnquotedGlob(suffixNodes[i])),permutes=lowerName==="sed",operandsFrom=suffixWords.length,optionArgs=new Set,expandingOptionArgs=new Set;for(let i=0;i<suffixWords.length;i++){let w=suffixWords[i];if(w==="--"){if(!permutes)operandsFrom=i+1;break}if(!w.startsWith("-")){if(!permutes){operandsFrom=i;break}continue}if(isOpaqueFlag(i)){if(!permutes){operandsFrom=i+1;break}continue}if(!takesDetachedArg(w))continue;if(i+1<suffixWords.length){if(optionArgs.add(i+1),detachedArgMaySplit(w,i+1)){if(expandingOptionArgs.add(i+1),!permutes){operandsFrom=i+2;break}}}i++}let inOptionArea=(i)=>i<operandsFrom,hasExplicitScript=!1;for(let i=0;i<suffixWords.length&&inOptionArea(i);i++){if(optionArgs.has(i))continue;let w=suffixWords[i];if(w==="--")break;if(!w.startsWith("-")||isOpaqueFlag(i))continue;if(expandingOptionArgs.has(i+1)){i++;continue}if(suppliesScript(w)){hasExplicitScript=!0;break}if(consumesNext(w)||lowerName==="awk"&&w==="-i")i++}let skipIndices=new Set,isDetachedSuffix=(w)=>lowerName==="sed"&&w!==void 0&&(w===""||w.startsWith(".")),isLiteralWord=(i)=>expansionFlags[i]!==!0&&!/[*?[]/.test(suffixWords[i])&&!/\{[^{}]*(?:,|\.\.)[^{}]*\}/.test(suffixWords[i]),isLiteralSedScript=(i)=>isLiteralWord(i)&&looksLikeSedScript(suffixWords[i]),isReportableWord=(i)=>suffixWords[i]!==""&&!isScriptWord(i)&&!isLiteralSedScript(i),firstPositionalFrom=(from)=>{let j=from;while(j<suffixWords.length&&(inOptionArea(j)&&suffixWords[j].startsWith("-")||optionArgs.has(j)))j++;return j},dashDash=suffixWords.findIndex((w,i)=>w==="--"&&!optionArgs.has(i)&&inOptionArea(i)),hasOpaqueFlag=suffixWords.some((_w,i)=>(dashDash<0||i<dashDash)&&inOptionArea(i)&&!optionArgs.has(i)&&isOpaqueFlag(i)),implicitScriptPlaced=hasOpaqueFlag||expandingOptionArgs.size>0;if(lowerName==="sed"&&!hasExplicitScript&&!implicitScriptPlaced)for(let i=0;i<suffixWords.length;i++){if(optionArgs.has(i))continue;let w=suffixWords[i];if(w==="--"||w.startsWith("-i")||w.startsWith("--in-place"))break;if(w.startsWith("-"))continue;if(!mayExpandToSeveralWords(i))skipIndices.add(i);implicitScriptPlaced=!0;break}let consumeImplicitScript=(from,bareInplace)=>{if(implicitScriptPlaced)return;implicitScriptPlaced=!0;let j=firstPositionalFrom(from);if(j>=suffixWords.length||mayExpandToSeveralWords(j))return;if(skipIndices.add(j),!bareInplace||!isDetachedSuffix(suffixWords[j]))return;let k=firstPositionalFrom(j+1);if(k>=suffixWords.length||!isLiteralSedScript(k))return;for(let m=firstPositionalFrom(k+1);m<suffixWords.length;){if(isReportableWord(m)){skipIndices.add(k);return}m=firstPositionalFrom(m+1)}},isConventionalBackupSuffix=(w)=>isDetachedSuffix(w)&&!w.includes("/")&&/^\.(?:bak|orig|old|save|backup|tmp|swp|~)$/i.test(w),dotWordAfterBareInplace=null,pastDoubleDash=!1,awkProgramSeen=!1;for(let i=0;i<suffixWords.length;i++){let word=suffixWords[i];if(optionArgs.has(i)){if(!expandingOptionArgs.has(i))skipIndices.add(i);continue}if(!pastDoubleDash&&word==="--"&&inOptionArea(i)){skipIndices.add(i),pastDoubleDash=!0;continue}if(!pastDoubleDash&&inOptionArea(i)&&word.startsWith("-")){if(isOpaqueFlag(i))continue;skipIndices.add(i);let next=suffixWords[i+1];if(lowerName==="sed"&&(word==="--in-place"||word.startsWith("--in-place="))){if(!hasExplicitScript)consumeImplicitScript(i+1,!1);continue}if(word==="-i"){if(next===void 0)continue;if(lowerName==="awk"){if(!expandingOptionArgs.has(i+1))skipIndices.add(i+1)}else if(!hasExplicitScript)consumeImplicitScript(i+1,!0);else if(isConventionalBackupSuffix(next))skipIndices.add(i+1),dotWordAfterBareInplace=next;continue}if(/^-i.+/.test(word)){if(lowerName!=="awk"&&!hasExplicitScript)consumeImplicitScript(i+1,!1);continue}if(consumesNext(word)||sedOptionArg(word)){if(next!==void 0&&!expandingOptionArgs.has(i+1))skipIndices.add(i+1)}continue}if(skipIndices.has(i))continue;if(lowerName==="awk"){if(!hasExplicitScript&&!hasOpaqueFlag&&expandingOptionArgs.size===0&&!awkProgramSeen)awkProgramSeen=!0,skipIndices.add(i);continue}if(isScriptWord(i))skipIndices.add(i)}let candidates=suffixWords.map((word,i)=>({word,i})).filter(({word,i})=>word!==""&&!skipIndices.has(i));if(candidates.length===0&&dotWordAfterBareInplace!==null)candidates.push({word:dotWordAfterBareInplace,i:-1});if(candidates.length>0)for(let{word}of candidates)results.push({category:"inplace_edit",operator:`${name} -i`,path:word});return results}function detectInterpreterEval(cmd){let results=[],name=getCommandName(cmd);if(!name)return results;let canonical=canonicalInterpreterName(cmd);if(!canonical)return[];let suffixWords=getSuffixWords(cmd),evalFlags={python:["-c"],python3:["-c"],python2:["-c"],node:["-e","-p","-pe"],bun:["-e","-p","-pe"],ruby:["-e"],perl:["-e","-E"],php:["-r","-R","-F"],bash:["-c"],sh:["-c"],dash:["-c"],zsh:["-c"],ksh:["-c"]};if(canonical==="eval")return results.push({category:"interpreter_eval",operator:"eval",path:null,capability:!0}),results;let relevantFlags=evalFlags[canonical]??[];if(!suffixWords.some((word)=>relevantFlags.some((f)=>word===f||word.startsWith(f)&&word.length>f.length)))return[];return results.push({category:"interpreter_eval",operator:`${name} [eval]`,path:null,capability:!0}),results}function detectNetworkDownloaders(cmd){let results=[],name=getCommandName(cmd);if(!name)return results;let lowerName=name.toLowerCase();if(!NETWORK_DOWNLOAD_COMMANDS.has(lowerName))return[];let suffixWords=getSuffixWords(cmd);if(lowerName==="curl")for(let i=0;i<suffixWords.length;i++){let word=suffixWords[i];if(word==="-o"&&i+1<suffixWords.length){let path98=suffixWords[i+1];if(!path98.startsWith("-"))results.push({category:"network_download",operator:"curl -o",path:path98})}else if(word.startsWith("-o")&&word.length>2)results.push({category:"network_download",operator:"curl -o",path:word.slice(2)})}else if(lowerName==="wget")for(let i=0;i<suffixWords.length;i++){let word=suffixWords[i];if(word==="-O"&&i+1<suffixWords.length){let path98=suffixWords[i+1];if(!path98.startsWith("-"))results.push({category:"network_download",operator:"wget -O",path:path98})}else if(word.startsWith("-O")&&word.length>2)results.push({category:"network_download",operator:"wget -O",path:word.slice(2)})}else if(lowerName==="scp")for(let i=suffixWords.length-1;i>=0;i--){let word=suffixWords[i];if(!word.startsWith("-")&&(word.includes(":")||word.startsWith("/")||word.startsWith("."))){results.push({category:"network_download",operator:"scp",path:word});break}}return results}function detectArchiveExtract(cmd){let results=[],name=getCommandName(cmd);if(!name)return results;let lowerName=name.toLowerCase();if(!ARCHIVE_EXTRACT_COMMANDS.has(lowerName))return[];let suffixWords=getSuffixWords(cmd);if(lowerName==="tar"){if(suffixWords.some((word)=>{if(word==="--extract"||word==="--get")return!0;if(word.startsWith("-")&&word.includes("x"))return!0;return!1}))for(let i=suffixWords.length-1;i>=0;i--){let word=suffixWords[i];if(!word.startsWith("-")){results.push({category:"archive_extract",operator:"tar -x",path:word});break}if(word.startsWith("--file=")&&word.length>7){results.push({category:"archive_extract",operator:"tar -x",path:word.slice(7)});break}}}else if(lowerName==="unzip")for(let i=suffixWords.length-1;i>=0;i--){let word=suffixWords[i];if(!word.startsWith("-")){results.push({category:"archive_extract",operator:"unzip",path:word});break}}else if(lowerName==="gunzip"||lowerName==="gzip"||lowerName==="bzip2"||lowerName==="xz"||lowerName==="7z"||lowerName==="rar"){if(suffixWords.includes("-d")||suffixWords.includes("--decompress")||lowerName==="gunzip")for(let i=suffixWords.length-1;i>=0;i--){let word=suffixWords[i];if(!word.startsWith("-")){results.push({category:"archive_extract",operator:`${name} [decompress]`,path:word});break}}}return results}function detectGitDestructive(cmd){let results=[],name=getCommandName(cmd);if(!name)return results;if(name.toLowerCase()!==GIT_COMMAND)return[];let suffixWords=getSuffixWords(cmd);if(suffixWords.length===0)return[];let first=suffixWords[0].toLowerCase();if(first==="checkout"){let dashDashIdx=suffixWords.indexOf("--");if(dashDashIdx!==-1&&dashDashIdx+1<suffixWords.length){let path98=suffixWords[dashDashIdx+1],op=path98==="."?"git checkout -- .":"git checkout --";results.push({category:"git_destructive",operator:op,path:path98})}}else if(first==="restore"){let hasHard=suffixWords.some((w)=>w==="--hard"||w==="-H"||w.startsWith("-")&&w.includes("H")),hasForce=suffixWords.some((w)=>w==="--force"||w==="-f"||w.startsWith("-")&&w.includes("f"));if(hasHard||hasForce){let dashDashIdx=suffixWords.indexOf("--");if(dashDashIdx!==-1&&dashDashIdx+1<suffixWords.length)results.push({category:"git_destructive",operator:"git restore",path:suffixWords[dashDashIdx+1]});else results.push({category:"git_destructive",operator:"git restore",path:null})}}else if(first==="reset"){if(suffixWords.some((w)=>w==="--hard"||w==="-H"||w.startsWith("-")&&w.includes("H")))results.push({category:"git_destructive",operator:"git reset --hard",path:null})}else if(first==="clean"){if(suffixWords.some((w)=>w==="-n"||w==="--dry-run"||w.startsWith("-")&&w.includes("n")))return results;let hasForce=suffixWords.some((w)=>w==="-f"||w==="--force"||w.startsWith("-")&&w.includes("f")),hasDir=suffixWords.some((w)=>w==="-d"||w==="--dir"||w.startsWith("-")&&w.includes("d"));if(hasForce&&hasDir)results.push({category:"git_destructive",operator:"git clean -fd",path:null})}return results}function splitWindowsCommands(command,shell){let commands=[],current="",inSingleQuote=!1,inDoubleQuote=!1,parenDepth=0;for(let i=0;i<command.length;i++){let ch=command[i];if(shell==="powershell"&&ch==="'"&&!inDoubleQuote)inSingleQuote=!inSingleQuote;else if(ch==='"'&&!inSingleQuote)inDoubleQuote=!inDoubleQuote;else if(ch==="("&&!inSingleQuote&&!inDoubleQuote)parenDepth++;else if(ch===")"&&!inSingleQuote&&!inDoubleQuote)parenDepth--;if(ch===`
|
|
1177
|
+
`&&!inSingleQuote&&!inDoubleQuote&&parenDepth===0){if(current.trim())commands.push(current.trim());current="";continue}if(shell==="powershell"&&(ch===";"||ch==="{"||ch==="}")&&!inSingleQuote&&!inDoubleQuote&&parenDepth===0){if(current.trim())commands.push(current.trim());current="";continue}if(ch==="|"&&!inSingleQuote&&!inDoubleQuote&&parenDepth===0){if(current.trim())commands.push(current.trim());current="";continue}if((ch==="&"||ch==="|")&&i+1<command.length&&command[i+1]===ch&&!inSingleQuote&&!inDoubleQuote&&parenDepth===0){if(current.trim())commands.push(current.trim());commands.push(ch==="&"?"&&":"||"),current="",i++;continue}if(ch==="&"&&!inSingleQuote&&!inDoubleQuote&&parenDepth===0){if(command[i-1]===">"){current+=ch;continue}if(!(i+1<command.length&&command[i+1]==="&")){if(current.trim())commands.push(current.trim());current="";continue}}current+=ch}if(current.trim())commands.push(current.trim());return commands.filter((c)=>c!=="&&"&&c!=="||")}function detectPowerShellRedirects(command){let results=[],inSingleQuote=!1,inDoubleQuote=!1,isBoundary=(character)=>character===void 0||/[\s;|&()]/.test(character);for(let index=0;index<command.length;index++){let character=command[index];if(inSingleQuote){if(character==="'")if(command[index+1]==="'")index++;else inSingleQuote=!1;continue}if(inDoubleQuote){if(character==="`"&&index+1<command.length){index++;continue}if(character==='"')inDoubleQuote=!1;continue}if(character==="'"){inSingleQuote=!0;continue}if(character==='"'){inDoubleQuote=!0;continue}if(character===">"&&command[index-1]==="^")continue;if(character!==">")continue;let operator=command[index+1]===">"?">>":">",cursor=index+operator.length;while(/\s/.test(command[cursor]??""))cursor++;if(command[cursor]==="&"){cursor++;while(/\s/.test(command[cursor]??""))cursor++;let descriptorStart=cursor;while(/\d/.test(command[cursor]??""))cursor++;if(command.slice(descriptorStart,cursor)&&isBoundary(command[cursor])){index=Math.max(index,cursor-1);continue}results.push({category:"redirect",operator,path:null}),index=Math.max(index,cursor-1);continue}let pathValue=null;if(cursor<command.length){let quote=command[cursor];if(quote==='"'||quote==="'"){cursor++;let pathStart=cursor,closed=!1;while(cursor<command.length){if(quote==='"'&&command[cursor]==="`"){cursor+=2;continue}if(command[cursor]===quote){if(quote==="'"&&command[cursor+1]==="'"){cursor+=2;continue}pathValue=command.slice(pathStart,cursor),cursor++,closed=!0;break}cursor++}if(!closed)pathValue=null}else{let pathStart=cursor;while(cursor<command.length&&!/\s|[;|&()<>]/.test(command[cursor]??""))cursor++;if(cursor>pathStart)pathValue=command.slice(pathStart,cursor)}}results.push({category:"redirect",operator,path:pathValue}),index=Math.max(index,cursor-1)}if(inSingleQuote||inDoubleQuote)results.push({category:"redirect",operator:">",path:null});return results}function detectPowerShellWrites(command){let results=[],trimmed=command.trim();if(!trimmed)return results;if(/^(?:powershell|pwsh)(?:\.exe)?\s+/i.test(trimmed)&&/(?:^|\s)-(?:e|ec|enc|encodedcommand)(?=\s|=|$)/i.test(trimmed))return results.push({category:"interpreter_eval",operator:"PowerShell -EncodedCommand",path:null}),results;let innerCommand=trimmed,cmdMatch=trimmed.match(new RegExp(`${PS_STRIP_PREFIX.source}(.*)$`,"i"));if(cmdMatch){if(innerCommand=cmdMatch[1].trim(),innerCommand.startsWith('"')&&innerCommand.endsWith('"')||innerCommand.startsWith("'")&&innerCommand.endsWith("'"))innerCommand=innerCommand.slice(1,-1)}if(/(?:^|[;{}|&])\s*(?:Set-Location|Push-Location|Pop-Location|cd|chdir|sl)\b/i.test(innerCommand))results.push({category:"builtin_write",operator:"working-directory mutation",path:null});if(/[({]\s*(?:Out-File|Set-Content|Add-Content|Clear-Content|Copy-Item|Move-Item|Remove-Item)\b/i.test(innerCommand))results.push({category:"interpreter_eval",operator:"nested PowerShell script block",path:null});if(/(?:^|[;|])\s*&\s*(?:['"$({]|\S+\s*\()/i.test(innerCommand)||/(?:^|[;|])\s*(?:Invoke-Expression|IEX)\b/i.test(innerCommand))results.push({category:"interpreter_eval",operator:"dynamic PowerShell invocation",path:null});results.push(...detectPowerShellRedirects(innerCommand));let iwrMatch=trimmed.match(/^(?:Invoke-WebRequest|curl)\s.*?(?:-OutFile\s+(\S+)|-o\s+(\S+))/i);if(iwrMatch){let path98=iwrMatch[1]||iwrMatch[2];if(path98)results.push({category:"network_download",operator:"Invoke-WebRequest -OutFile",path:path98})}function detectPsContentCmdlet(cmd){let cmdletMatch=cmd.match(/^(Out-File|Set-Content|Add-Content|Clear-Content)\b/i);if(!cmdletMatch)return[];let cmdletName=cmdletMatch[1],rest=cmd.slice(cmdletMatch[0].length).trim(),pathFlagMatch=rest.match(/(?:-Path|-FilePath|-LiteralPath)\s+((?:"[^"]*"|'[^']*'|[^,\s]+)(?:\s*,\s*(?:"[^"]*"|'[^']*'|[^,\s]+))*)/i);if(pathFlagMatch)return pathFlagMatch[1].split(/\s*,\s*/).map((value)=>value.replace(/^(["'])|(["'])$/g,"")).map((path98)=>({category:"redirect",operator:cmdletName,path:path98||null}));if(/(?:-Path|-FilePath|-LiteralPath)(?:\s|$)/i.test(rest))return[{category:"redirect",operator:cmdletName,path:null}];let tokens=rest.match(/(?:[^\s"-]+|"[^"]*"|'[^']*'|-[^\s]+)/g)??[];for(let token of tokens){if(token.startsWith("-"))continue;let path98=token.replace(/^["']|["']$/g,"");return[{category:"redirect",operator:cmdletName,path:path98}]}return[]}results.push(...detectPsContentCmdlet(innerCommand));let pipeContentMatch=innerCommand.match(/\|\s*(Out-File|Set-Content|Add-Content|Clear-Content)\b\s*(.*)$/i);if(pipeContentMatch){let cmdletName=pipeContentMatch[1],tokens=pipeContentMatch[2].trim().match(/(?:[^\s"-]+|"[^"]*"|'[^']*'|-[^\s]+)/g)??[];for(let token of tokens){if(token.startsWith("-"))continue;let path98=token.replace(/^["']|["']$/g,"");if(path98){results.push({category:"redirect",operator:cmdletName,path:path98});break}}}function detectPsFileOp(cmd){let opMatch=cmd.match(/^(Copy-Item|Move-Item|Remove-Item)\b/i);if(!opMatch)return null;let cmdletName=opMatch[1],rest=cmd.slice(opMatch[0].length).trim(),destFlagMatch=rest.match(/-Destination\s+(\S+|"[^"]+"|'[^']+')/i);if(destFlagMatch){let path98=destFlagMatch[1].replace(/^["']|["']$/g,"");return{category:"builtin_write",operator:cmdletName,path:path98}}let tokens=[],flagTakingValue=new Set(["-Path","-LiteralPath","-Exclude","-Include","-Filter"]),switchFlags=new Set(["-Recurse","-Force","-Confirm","-WhatIf","-PassThru","-Verbose","-Debug"]),parts=rest.match(/(?:[^\s"-]+|"[^"]*"|'[^']*'|-[^\s]+)/g)??[],i=0;while(i<parts.length){let part=parts[i];if(flagTakingValue.has(part)&&i+1<parts.length){let value=parts[i+1];if(!value.startsWith("-"))tokens.push(value);i+=2}else if(switchFlags.has(part))i++;else if(part.startsWith("-"))i++;else tokens.push(part),i++}if(tokens.length>=2){let path98=tokens[tokens.length-1].replace(/^["']|["']$/g,"");return{category:"builtin_write",operator:cmdletName,path:path98}}else if(tokens.length===1){let path98=tokens[0].replace(/^["']|["']$/g,"");return{category:"builtin_write",operator:cmdletName,path:path98}}return null}function detectPsNewItem(cmd){let opMatch=cmd.match(/^(?:New-Item|ni)\b/i);if(!opMatch)return null;let rest=cmd.slice(opMatch[0].length).trim(),SWITCH_FLAGS=new Set(["-force","-confirm","-whatif"]),VALUE_FLAGS=new Set(["-itemtype","-value","-description"]),PATH_FLAGS=new Set(["-path","-literalpath"]),tokens=rest.match(/"[^"]*"|'[^']*'|\S+/g)??[],unquote=(value)=>value.replace(/^["']|["']$/g,""),pathValue=null,nameValue=null,positional=null;for(let i=0;i<tokens.length;i+=1){let token=tokens[i],flag=token.toLowerCase();if(PATH_FLAGS.has(flag)){pathValue=unquote(tokens[i+1]??""),i+=1;continue}if(flag==="-name"){nameValue=unquote(tokens[i+1]??""),i+=1;continue}if(VALUE_FLAGS.has(flag)){i+=1;continue}if(SWITCH_FLAGS.has(flag))continue;if(flag.startsWith("-"))continue;if(positional===null)positional=unquote(token)}let basePath=(pathValue??positional)?.replace(/\/+$/,"")??null;if(basePath!==null&&nameValue){let base=basePath;return{category:"builtin_write",operator:"New-Item",path:base?`${base}/${nameValue}`:nameValue}}if(pathValue)return{category:"builtin_write",operator:"New-Item",path:pathValue};if(positional)return{category:"builtin_write",operator:"New-Item",path:positional};if(nameValue)return{category:"builtin_write",operator:"New-Item",path:nameValue};return{category:"builtin_write",operator:"New-Item",path:null}}let fileOp=detectPsFileOp(innerCommand)??detectPsNewItem(innerCommand);if(fileOp)results.push(fileOp);let pipeFileOpMatch=innerCommand.match(/\|\s*(Copy-Item|Move-Item)\b\s*(.*)$/i);if(pipeFileOpMatch){let cmdletName=pipeFileOpMatch[1],afterCmdlet=pipeFileOpMatch[2].trim(),destFlagMatch=afterCmdlet.match(/-Destination\s+(\S+|"[^"]+"|'[^']+')/i);if(destFlagMatch){let path98=destFlagMatch[1].replace(/^["']|["']$/g,"");results.push({category:"builtin_write",operator:cmdletName,path:path98})}else{let nonFlagTokens=(afterCmdlet.match(/(?:[^\s"-]+|"[^"]*"|'[^']*'|-[^\s]+)/g)??[]).filter((t)=>!t.startsWith("-")&&t.length>0);if(nonFlagTokens.length>0){let path98=nonFlagTokens[nonFlagTokens.length-1].replace(/^["']|["']$/g,"");results.push({category:"builtin_write",operator:cmdletName,path:path98})}}}return results}function tokenizeCmdArguments(command){let tokens=[],current="",inDoubleQuote=!1;for(let index=0;index<command.length;index++){let character=command[index];if(character==="^"&&!inDoubleQuote){if(index+1<command.length)current+=command[++index];continue}if(character==='"'){inDoubleQuote=!inDoubleQuote;continue}if(/\s/.test(character)&&!inDoubleQuote){if(current)tokens.push(current),current="";continue}current+=character}if(current)tokens.push(current);return tokens}function detectCmdRedirects(command){let results=[],inDoubleQuote=!1,isTokenBoundary=(character)=>character===void 0||/[;\s&|()]/.test(character);for(let index=0;index<command.length;index++){let character=command[index];if(character==="^"&&!inDoubleQuote){index++;continue}if(character==='"'){inDoubleQuote=!inDoubleQuote;continue}if(inDoubleQuote||character!==">")continue;let operator=command[index+1]===">"?">>":">",cursor=index+operator.length;while(/\s/.test(command[cursor]??""))cursor++;if(command[cursor]==="&"){cursor++;while(/\s/.test(command[cursor]??""))cursor++;let descriptorStart=cursor;while(/\d/.test(command[cursor]??""))cursor++;if(command.slice(descriptorStart,cursor)&&isTokenBoundary(command[cursor])){index=Math.max(index,cursor-1);continue}results.push({category:"redirect",operator,path:null}),index=Math.max(index,cursor-1);continue}let pathValue=null;if(cursor<command.length){let quote=command[cursor];if(quote==='"'){let closingQuote=command.indexOf(quote,cursor+1);if(closingQuote!==-1)pathValue=command.slice(cursor+1,closingQuote),cursor=closingQuote+1}else{let pathStart=cursor;while(cursor<command.length&&!/[\s&|()<>]/.test(command[cursor]??""))cursor++;if(cursor>pathStart)pathValue=command.slice(pathStart,cursor)}}results.push({category:"redirect",operator,path:pathValue}),index=Math.max(index,cursor-1)}if(inDoubleQuote)results.push({category:"redirect",operator:">",path:null});return results}function detectCmdWrites(command){let results=[],trimmed=command.trim();if(!trimmed)return results;let innerCommand=trimmed,cmdWrapperMatch=trimmed.match(new RegExp(`${CMD_STRIP_PREFIX.source}(.*)$`,"i"));if(cmdWrapperMatch){if(innerCommand=cmdWrapperMatch[1].trim(),innerCommand.startsWith('"')&&innerCommand.endsWith('"')||innerCommand.startsWith("'")&&innerCommand.endsWith("'"))innerCommand=innerCommand.slice(1,-1)}if(/^(?:powershell|pwsh)(?:\.exe)?\s+/i.test(innerCommand))results.push(...detectPowerShellWrites(innerCommand));results.push(...detectCmdRedirects(innerCommand));function detectCmdCopy(cmd){let commandMatch=cmd.match(new RegExp(`^${CMD_BUILTIN_PREFIX.source}copy(?=\\s|$)`,"i"));if(commandMatch){let start=(commandMatch.index??0)+commandMatch[0].length,positional=tokenizeCmdArguments(cmd.slice(start)).filter((token)=>!_CMD_COPY_MOVE_SWITCHES.has(token.toLowerCase()));if(positional.length<2)return null;return{category:"builtin_write",operator:"copy",path:positional[positional.length-1]}}return null}function detectCmdMove(cmd){let commandMatch=cmd.match(new RegExp(`^${CMD_BUILTIN_PREFIX.source}move(?=\\s|$)`,"i"));if(commandMatch){let start=(commandMatch.index??0)+commandMatch[0].length,positional=tokenizeCmdArguments(cmd.slice(start)).filter((token)=>!_CMD_COPY_MOVE_SWITCHES.has(token.toLowerCase()));if(positional.length<2)return null;return{category:"builtin_write",operator:"move",path:positional[positional.length-1]}}return null}let copyResult=detectCmdCopy(innerCommand);if(copyResult)results.push(copyResult);let moveResult=detectCmdMove(innerCommand);if(moveResult)results.push(moveResult);let renMatch=innerCommand.match(/^ren\s+(\S+|"[^"]+"|'[^']+')\s+(\S+|"[^"]+"|'[^']+')/i);if(renMatch){let dest=(renMatch[2]||"").replace(/^["']|["']$/g,"");if(dest)results.push({category:"builtin_write",operator:"ren",path:dest})}function detectCmdDel(cmd){let delMatch=cmd.match(/^del\s+/i);if(!delMatch)return null;let tokens=(cmd.slice(delMatch[0].length).trim().match(/(\/?[^\s]+|"[^"]*"|'[^']*')/g)??[]).filter((t)=>!t.startsWith("/"));if(tokens.length>0)return{category:"builtin_write",operator:"del",path:tokens[0].replace(/^["']|["']$/g,"")};return null}let delResult=detectCmdDel(innerCommand);if(delResult)results.push(delResult);let rdMatch=innerCommand.match(/^rd\s+(?:\/s\s+|\/q\s+)*(\S+)/i);if(rdMatch){let path98=rdMatch[1].replace(/^["']|["']$/g,"");if(!path98.startsWith("/"))results.push({category:"builtin_write",operator:"rd",path:path98})}let mdMatch=trimmed.match(/^md\s+(\S+)/i);if(mdMatch){let path98=mdMatch[1].replace(/^["']|["']$/g,"");if(!path98.startsWith("/"))results.push({category:"builtin_write",operator:"md",path:path98})}return results}function detectInteractiveSession(command,shell){if(!command||typeof command!=="string")return!1;let trimmed=command.trim();if(shell==="posix"){let lower=trimmed.toLowerCase();if(/^watch(\s|$)/.test(lower))return!0;if(/^screen(\s|$)/.test(lower))return!0;if(/^tmux(\s+new-session(\s+.*)?)?$/.test(lower))return!0}else if(shell==="powershell"){if(/^Start-Process\s/i.test(trimmed))return!0}return!1}function detectPosixWrites(command){if(!command||typeof command!=="string")return{writes:[],hasWrites:!1};if(unsafeShellCommandTextReason(command))return{writes:[{category:"interpreter_eval",operator:"unsafe command text",path:null}],hasWrites:!0,parseError:!0};let ast,parseFailed=!1;try{ast=import_bash_parser.default(command,{mode:"posix",insertLOC:!0}),annotateRawWordText(ast,command)}catch{parseFailed=!0}let allWrites=[],cwdNeutral=!1;if(!parseFailed&&ast&&typeof ast==="object"){let leafCommands=[];collectLeafCommands(ast,leafCommands),cwdNeutral=leafCommands.every(isCwdNeutralLeaf);for(let cmd of leafCommands)allWrites.push(...detectRedirects(cmd)),allWrites.push(...detectBuiltinWrites(cmd)),allWrites.push(...detectInplaceEdit(cmd)),allWrites.push(...detectInterpreterEval(cmd)),allWrites.push(...detectNetworkDownloaders(cmd)),allWrites.push(...detectArchiveExtract(cmd)),allWrites.push(...detectGitDestructive(cmd))}if(parseFailed){let procSubWrites=detectProcessSubstitutionWrites(command);allWrites.push(...procSubWrites)}let seen=new Set,occurrence=new Map,collidingKeys=new Set,writes=[];for(let wt of allWrites){let key2=buildDedupeKey(wt.category,wt.operator,wt.path);if(seen.has(key2)){if(collidingKeys.add(key2),wt.capability!==!0||wt.category!=="interpreter_eval")continue;let n=(occurrence.get(key2)??1)+1;occurrence.set(key2,n),writes.push({...wt,operator:`${wt.operator} #${n}`});continue}seen.add(key2),writes.push(wt)}if(writes=writes.map((wt)=>wt.emptyDirectoryRemoval===!0&&collidingKeys.has(buildDedupeKey(wt.category,wt.operator,wt.path))?withoutEmptyDirectoryRemoval(wt):wt),!PLAIN_COMMAND_LINE.test(command))writes=writes.map(withoutEmptyDirectoryRemoval);if(!cwdNeutral)writes=writes.map(withoutEmptyDirectoryRemoval);return{writes,hasWrites:writes.length>0,parseError:parseFailed&&writes.length===0?!0:void 0}}function isCwdNeutralLeaf(node){if(node.type!=="Command")return CWD_TRANSPARENT_NODE_TYPES.has(node.type);let name=getCommandName(node);if(name!==null)return CWD_NEUTRAL_COMMANDS.has(name);let prefix=node.prefix??[];return Array.isArray(prefix)&&prefix.every((entry)=>{if(!entry||typeof entry!=="object")return!1;let type=entry.type;return type==="AssignmentWord"||type==="Redirect"})}function detectWindowsWrites(command,shell){if(!command||typeof command!=="string")return{writes:[],hasWrites:!1};if(unsafeShellCommandTextReason(command))return{writes:[{category:"interpreter_eval",operator:"unsafe command text",path:null}],hasWrites:!0,parseError:!0};try{let subCommands=splitWindowsCommands(command,shell),allWrites=[];for(let subCmd of subCommands){let psWrites=detectPowerShellWrites(subCmd),psFiltered=shell==="powershell"?psWrites:psWrites.filter((w)=>w.operator!=="working-directory mutation");allWrites.push(...psFiltered);let cmdWrites=detectCmdWrites(subCmd),cmdFiltered=shell==="powershell"?cmdWrites.filter((w)=>w.category!=="redirect"):cmdWrites;allWrites.push(...cmdFiltered)}let stripQuotes2=(p)=>p===null||p===void 0?p:p.replace(/^['"]+/,"").replace(/['"]+$/,""),seen=new Set,seenStripped=[],writes=allWrites.filter((wt)=>{let key2=buildDedupeKey(wt.category,wt.operator,wt.path);if(seen.has(key2))return!1;let stripped=stripQuotes2(wt.path);if(stripped!==wt.path){if(seenStripped.some((other)=>other.category===wt.category&&other.operator===wt.operator&&stripQuotes2(other.path)===stripped))return!1}return seen.add(key2),seenStripped.push({category:wt.category,operator:wt.operator,path:wt.path}),!0});return{writes,hasWrites:writes.length>0}}catch{return{writes:[],hasWrites:!1,parseError:!0}}}function isDynamicPath(pathText){if(pathText===null||pathText===void 0)return!1;if(/\$[A-Za-z_][A-Za-z0-9_]*/.test(pathText))return!0;if(/\$\{[^}]+\}/.test(pathText))return!0;if(/%[A-Za-z_][A-Za-z0-9_]*%/.test(pathText))return!0;if(/\$\([^)]+\)/.test(pathText))return!0;if(/`[^`]+`/.test(pathText))return!0;if(/^~(?:[^/\\\s]*)?(?:[/\\]|$)/.test(pathText))return!0;if(/%~[A-Za-z]*(?:\d+|\*)/.test(pathText))return!0;if(/%(?:\d+|\*)/.test(pathText))return!0;return!1}function resolvePath(pathText,cwd){if(pathText===null)return null;if(isDynamicPath(pathText))return null;if(/^[a-zA-Z]:[\\\\/]/.test(cwd)||cwd.includes("\\"))return path97.win32.resolve(cwd,pathText);let normalizedRelativeWindowsPath=!path97.posix.isAbsolute(pathText)&&!/^[a-zA-Z]:[\\/]/.test(pathText)?pathText.replace(/\\/g,"/"):pathText;return path97.posix.resolve(cwd,normalizedRelativeWindowsPath)}function getCdTarget(cmd){if(!cmd||typeof cmd!=="object")return null;let c=cmd;if(c.type!=="SimpleCommand"&&c.type!=="Command")return null;let name=c.name;if(!name||typeof name!=="object")return null;let n=name;if(n.type!=="Word")return null;if(n.text!=="cd")return null;let suffix=c.suffix;if(!Array.isArray(suffix)||suffix.length===0)return null;let first=suffix[0];if(!first||typeof first!=="object")return null;let firstWord=first;if(firstWord.type!=="Word")return null;let target=firstWord.text;if(target==="-"||target==="~"||target==="~/")return null;return target}function collectWritesWithNodes(node,out,cwdStack){if(!node||typeof node!=="object")return;switch(node.type){case"Script":{let _globalCwd=cwdStack[0]??"/";if(Array.isArray(node.commands))for(let cmd of node.commands)collectWritesWithNodes(cmd,out,cwdStack);break}case"Subshell":{let effectiveCwd=cwdStack[0]??"/",subshellRedirs=node.redirections;if(Array.isArray(subshellRedirs))for(let redirect of subshellRedirs){let writesFromRedirect=getWritesFromRedirectNode(redirect,effectiveCwd);for(let w of writesFromRedirect)out.push({write:w,context:effectiveCwd})}if(node.list){let subStack=[...cwdStack];collectWritesWithNodes(node.list,out,subStack)}break}case"CompoundList":{if(Array.isArray(node.commands)){let currentStack=cwdStack;for(let cmd of node.commands){let cdTarget=getCdTarget(cmd);if(cdTarget)currentStack[0]=resolvePath(cdTarget,currentStack[0]??"/")??path97.posix.resolve(currentStack[0]??"/",cdTarget);else collectWritesWithNodes(cmd,out,currentStack)}}break}case"Pipeline":case"Sequence":{if(Array.isArray(node.commands))for(let cmd of node.commands)collectWritesWithNodes(cmd,out,cwdStack);break}case"LogicalExpression":{if(node.left){collectWritesWithNodes(node.left,out,cwdStack);let leftContext=cwdStack[0]??"/";if(node.right){let rightStack=[leftContext];collectWritesWithNodes(node.right,out,rightStack)}}break}case"And":case"Or":{if(node.left){collectWritesWithNodes(node.left,out,cwdStack);let leftContext=cwdStack[0]??"/";if(node.right){let rightStack=[leftContext];collectWritesWithNodes(node.right,out,rightStack)}}break}case"If":{let effectiveCwd=cwdStack[0]??"/";if(Array.isArray(node.redirections))for(let redirect of node.redirections)for(let w of getWritesFromRedirectNode(redirect,effectiveCwd))out.push({write:w,context:effectiveCwd});for(let body of[node.clause,node.then,node.else])if(body)collectWritesWithNodes(body,out,[...cwdStack]);break}case"While":case"Until":{let effectiveCwd=cwdStack[0]??"/";if(Array.isArray(node.redirections))for(let redirect of node.redirections)for(let w of getWritesFromRedirectNode(redirect,effectiveCwd))out.push({write:w,context:effectiveCwd});if(node.clause)collectWritesWithNodes(node.clause,out,[...cwdStack]);if(node.do)collectWritesWithNodes(node.do,out,[...cwdStack]);break}case"For":{let effectiveCwd=cwdStack[0]??"/";if(Array.isArray(node.redirections))for(let redirect of node.redirections)for(let w of getWritesFromRedirectNode(redirect,effectiveCwd))out.push({write:w,context:effectiveCwd});if(node.do)collectWritesWithNodes(node.do,out,[...cwdStack]);break}case"Case":{let effectiveCwd=cwdStack[0]??"/";if(Array.isArray(node.redirections))for(let redirect of node.redirections)for(let w of getWritesFromRedirectNode(redirect,effectiveCwd))out.push({write:w,context:effectiveCwd});if(Array.isArray(node.cases)){for(let entry of node.cases)if(entry?.body)collectWritesWithNodes(entry.body,out,[...cwdStack])}break}case"Function":{let effectiveCwd=cwdStack[0]??"/";if(Array.isArray(node.redirections))for(let redirect of node.redirections)for(let w of getWritesFromRedirectNode(redirect,effectiveCwd))out.push({write:w,context:effectiveCwd});if(node.body)collectWritesWithNodes(node.body,out,[...cwdStack]);break}case"Command":case"SimpleCommand":{let effectiveCwd=cwdStack[0]??"/",cdTarget=getCdTarget(node);if(cdTarget){cwdStack[0]=resolvePath(cdTarget,cwdStack[0]??"/")??path97.posix.resolve(cwdStack[0]??"/",cdTarget);return}let writesFromRedirs=getWritesFromCommandRedirs(node,effectiveCwd);for(let w of writesFromRedirs)out.push({write:w,context:effectiveCwd});let builtinWrites=detectBuiltinWrites(node);for(let w of builtinWrites)out.push({write:w,context:effectiveCwd});let inplaceWrites=detectInplaceEdit(node);for(let w of inplaceWrites)out.push({write:w,context:effectiveCwd});let interpreterWrites=detectInterpreterEval(node);for(let w of interpreterWrites)out.push({write:w,context:effectiveCwd});let networkWrites=detectNetworkDownloaders(node);for(let w of networkWrites)out.push({write:w,context:effectiveCwd});let archiveWrites=detectArchiveExtract(node);for(let w of archiveWrites)out.push({write:w,context:effectiveCwd});let gitWrites=detectGitDestructive(node);for(let w of gitWrites)out.push({write:w,context:effectiveCwd});break}}}function getWritesFromRedirectNode(redirect,_context){if(!redirect||typeof redirect!=="object")return[];let r=redirect,opNode=r.op;if(!opNode||typeof opNode!=="object")return[];let opType=opNode.type?.toUpperCase();if(!opType||!REDIRECT_ALL_WRITE_TOKENS.has(opType))return[];let fileNode=r.file,path98=extractRedirectPath(fileNode),opLabel=operatorLabel(opNode);if(REDIRECT_WRITE_TOKENS.has(opType)||REDIRECT_GREATAND_TOKENS.has(opType)&&!isNonFileGreatAndTarget(path98)){if(path98!==null&&isNullDevice(path98))return[];return[{category:"redirect",operator:opLabel,path:path98}]}else if(REDIRECT_HERE_TOKENS.has(opType))return[{category:"here_doc",operator:opLabel,path:path98}];return[]}function getWritesFromCommandRedirs(cmd,context){if(!cmd||typeof cmd!=="object")return[];let c=cmd,results=[];results.push(...detectHereDocMarkers(cmd));let{suffix,prefix}=c;if(Array.isArray(suffix)){for(let item of suffix)if(isRedirectNode(item)){let writes=getWritesFromRedirectNode(item,context);results.push(...writes)}}if(Array.isArray(prefix)){for(let item of prefix)if(isRedirectNode(item)){let writes=getWritesFromRedirectNode(item,context);results.push(...writes)}}return results}function resolveWriteTargets(command,writes,cwd){if(!writes||writes.length===0)return[];if(!command||typeof command!=="string")return writes.map((original)=>({original,resolvedPath:resolvePath(original.path,cwd),resolved:original.path!==null&&!isDynamicPath(original.path),...original.capability===!0&&original.category==="interpreter_eval"?{evalDirectory:cwd}:{}}));let ast;try{ast=import_bash_parser.default(command,{mode:"posix",insertLOC:!0}),annotateRawWordText(ast,command)}catch{ast=null}if(!ast||typeof ast!=="object")return writes.map((original)=>({original,resolvedPath:resolvePath(original.path,cwd),resolved:original.path!==null&&!isDynamicPath(original.path),...original.capability===!0&&original.category==="interpreter_eval"?{evalDirectory:cwd}:{}}));let cwdStack=[cwd],writesWithNodes=[];collectWritesWithNodes(ast,writesWithNodes,cwdStack);let seen=new Set,occurrence=new Map,collidingKeys=new Set,deduplicated=[];for(let wwn of writesWithNodes){let key2=buildDedupeKey(wwn.write.category,wwn.write.operator,wwn.write.path);if(seen.has(key2)){if(collidingKeys.add(key2),wwn.write.capability!==!0||wwn.write.category!=="interpreter_eval")continue;let n=(occurrence.get(key2)??1)+1;occurrence.set(key2,n),deduplicated.push({write:{...wwn.write,operator:`${wwn.write.operator} #${n}`},context:wwn.context});continue}seen.add(key2),deduplicated.push(wwn)}let inputKeys=new Set;for(let write of writes){let key2=buildDedupeKey(write.category,write.operator,write.path);if(inputKeys.has(key2))collidingKeys.add(key2);inputKeys.add(key2)}let resolvedMap=new Map;for(let{write,context}of deduplicated){let resolvedPath=resolvePath(write.path,context),resolved=write.path!==null&&!isDynamicPath(write.path),key2=buildDedupeKey(write.category,write.operator,write.path),evalDirectory=write.capability===!0&&write.category==="interpreter_eval"?context:void 0;resolvedMap.set(key2,{resolvedPath,resolved,evalDirectory})}return writes.map((input)=>{let key2=buildDedupeKey(input.category,input.operator,input.path),original=collidingKeys.has(key2)?withoutEmptyDirectoryRemoval(input):input,resolved=resolvedMap.get(key2);if(resolved)return{original,resolvedPath:resolved.resolvedPath,resolved:resolved.resolved,...resolved.evalDirectory!==void 0?{evalDirectory:resolved.evalDirectory}:{}};return{original,resolvedPath:resolvePath(original.path,cwd),resolved:original.path!==null&&!isDynamicPath(original.path),...original.capability===!0&&original.category==="interpreter_eval"?{evalDirectory:cwd}:{}}})}var import_bash_parser,REDIRECT_WRITE_TOKENS,REDIRECT_HERE_TOKENS,REDIRECT_GREATAND_TOKENS,REDIRECT_ALL_WRITE_TOKENS,BUILTIN_WRITE_COMMANDS,BARE_RMDIR_OPERAND,INPLACE_EDIT_COMMANDS,SED_LONG_SWITCHES,AWK_LONG_SWITCHES,INTERPRETER_EVAL_COMMANDS,NETWORK_DOWNLOAD_COMMANDS,ARCHIVE_EXTRACT_COMMANDS,GIT_COMMAND="git",POWERSHELL_WRITE_CMDLETS,AMBIGUOUS_WRITE_ALIASES,POWERSHELL_READ_ONLY_COMMANDS,POSIX_WRITE_TOKENS,READ_ONLY_SCRIPT_BLOCK_OPERATORS,RAW_WORD_TEXT,BRACE_EXPANSION,PARSER_CHAR_ESCAPES,ENV_FLAGS_WITH_ARG,_CMD_COPY_MOVE_SWITCHES,PLAIN_COMMAND_LINE,CWD_NEUTRAL_COMMANDS,CWD_TRANSPARENT_NODE_TYPES;var init_shell_write_detect=__esm(()=>{init_path_identity();init_shell_executor_context();import_bash_parser=__toESM(require_src(),1);REDIRECT_WRITE_TOKENS=new Set(["GREAT","DGREAT","CLOBBER","LESSGREAT"]),REDIRECT_HERE_TOKENS=new Set(["DLESS","DLESSDASH"]),REDIRECT_GREATAND_TOKENS=new Set(["GREATAND"]),REDIRECT_ALL_WRITE_TOKENS=new Set([...REDIRECT_WRITE_TOKENS,...REDIRECT_HERE_TOKENS,...REDIRECT_GREATAND_TOKENS]),BUILTIN_WRITE_COMMANDS=new Set(["cp","mv","install","ln","truncate","unlink","rmdir"]),BARE_RMDIR_OPERAND=/^[^-*?[\]{}$`~"'\\#\s][^*?[\]{}$`~"'\\#\s]*$/;INPLACE_EDIT_COMMANDS=new Set(["sed","perl","awk"]),SED_LONG_SWITCHES=new Set(["--quiet","--silent","--debug","--follow-symlinks","--binary","--posix","--regexp-extended","--separate","--sandbox","--unbuffered","--null-data","--zero-terminated","--help","--version"]),AWK_LONG_SWITCHES=new Set(["--posix","--traditional","--lint","--re-interval","--sandbox","--version","--help"]),INTERPRETER_EVAL_COMMANDS=new Set(["python","python3","python2","node","bun","ruby","perl","php","bash","sh","dash","zsh","ksh","eval"]),NETWORK_DOWNLOAD_COMMANDS=new Set(["curl","wget","scp"]),ARCHIVE_EXTRACT_COMMANDS=new Set(["tar","unzip","gunzip","gzip","bzip2","xz","7z","rar"]),POWERSHELL_WRITE_CMDLETS=new Set(["set-content","add-content","out-file","clear-content","copy-item","move-item","remove-item","new-item","ni","ac","sc","epcsv"]),AMBIGUOUS_WRITE_ALIASES=new Set(["cp","cpi","mv","rm","del","ren","rd","md","type"]),POWERSHELL_READ_ONLY_COMMANDS=new Set(["get-content","gc","get-item","gi","get-childitem","gci","get-location","pwd","get-command","get-member","get-date","get-help","get-itemproperty","select-string","select-object","where-object","foreach-object","sort-object","group-object","measure-object","compare-object","resolve-path","test-path","format-table","out-string","write-output","write-host","write-verbose","write-warning"]),POSIX_WRITE_TOKENS=new Set(["cp","mv","rm","rmdir","tee","dd","ln","touch","truncate","unlink","install"]);READ_ONLY_SCRIPT_BLOCK_OPERATORS=new Set(["-gt","-ge","-lt","-le","-eq","-ne","-match","-notmatch","-like","-notlike","-replace","-contains","-notcontains","-in","-notin","-is","-isnot","-join","-split","-f","-band","-bor","-bnot","-shl","-shr","-and","-or","-not","-xor"].map((op)=>op.toLowerCase()));RAW_WORD_TEXT=new WeakMap;BRACE_EXPANSION=/\{[^{}]*(?:,|\.\.)[^{}]*\}/;PARSER_CHAR_ESCAPES={t:"\t",n:`
|
|
1178
|
+
`,r:"\r",b:"\b",f:"\f",v:"\v"};ENV_FLAGS_WITH_ARG=new Set(["-u","-U","-C","-S","-a","-P","--split-string","--unset","--chdir","--argv0","--env0-from"]);_CMD_COPY_MOVE_SWITCHES=new Set(["/a","/b","/d","/f","/n","/v","/y","/-y","/z"]);PLAIN_COMMAND_LINE=/^[A-Za-z0-9 \t\n_./=&|;<>-]*$/,CWD_NEUTRAL_COMMANDS=new Set(["rmdir","mkdir","echo","true","false","test"]),CWD_TRANSPARENT_NODE_TYPES=new Set(["CompoundList","If","While","Until","For"])});import*as fs61 from"node:fs";import*as path98 from"node:path";function extractFilename(code,language,index){let lines=code.trim().split(`
|
|
1179
1179
|
`),ext=EXT_MAP[language.toLowerCase()]??".txt",firstLine=lines[0]?.trim()??"",filenameMatch=firstLine.match(/^[#/]+\s*filename[:\s]+(\S+\.\w+)/i);if(filenameMatch?.[1])return filenameMatch[1];let bareMatch=firstLine.match(/^[#/]+\s*(\w+\.\w+)\s*$/);if(bareMatch?.[1])return bareMatch[1];for(let line of lines.slice(0,5)){let defMatch=line.match(/^(?:def\s+|class\s+)(\w+)/);if(defMatch?.[1]&&!defMatch[1].startsWith("_"))return`${defMatch[1]}${ext}`;let psMatch=line.match(/^function\s+([\w-]+)/i);if(psMatch?.[1])return`${psMatch[1]}${ext}`}return`output_${index+1}${ext}`}function lstatIfPresent(filePath){try{return fs61.lstatSync(filePath)}catch(error93){if(error93.code==="ENOENT")return null;throw error93}}function reservationKey(filename){return path98.normalize(filename).toLowerCase()}function planExtractCodeBlocks(args2,directory){let{content,output_dir:outputDir,prefix}=args2;if(!content)return{status:"noop",reason:"content-required"};let matches=[...content.matchAll(/```(\w*)\n([\s\S]*?)```/g)];if(matches.length===0)return{status:"noop",reason:"no-code-blocks"};if(matches.length>MAX_EXTRACTED_FILES)return{status:"invalid",reason:`Too many code blocks (${matches.length}; maximum ${MAX_EXTRACTED_FILES})`};let targetDir=directory;if(outputDir!==void 0&&outputDir.trim()!==""){let reason=validateTargetWithinRoot(outputDir,directory);if(reason)return{status:"invalid",reason:`output_dir rejected — ${reason}`};targetDir=path98.resolve(directory,outputDir)}let reserved=new Set,files=[];for(let index=0;index<matches.length;index++){let language=matches[index]?.[1]??"",code=matches[index]?.[2]??"",filename=extractFilename(code,language,index);if(prefix)filename=`${prefix}_${filename}`;if(filename.includes("/")||filename.includes("\\"))return{status:"invalid",reason:`Rejected unsafe filename (must be a bare name): ${filename}`};let requestedPath=path98.join(targetDir,filename);if(lstatIfPresent(requestedPath)?.isSymbolicLink())return{status:"invalid",reason:`Rejected write through symlink: ${requestedPath}`};let base=path98.basename(filename,path98.extname(filename)),ext=path98.extname(filename),candidate=filename,counter=1;while(reserved.has(reservationKey(candidate))||lstatIfPresent(path98.join(targetDir,candidate))!==null){if(counter>MAX_COLLISION_ATTEMPTS)return{status:"invalid",reason:`Too many filename collisions for ${filename}`};candidate=`${base}_${counter}${ext}`,counter++}let absolutePath=path98.join(targetDir,candidate),relativePath=path98.relative(directory,absolutePath)||candidate,reason=validateTargetWithinRoot(relativePath,directory);if(reason)return{status:"invalid",reason:`Rejected write outside workspace: ${absolutePath} — ${reason}`};reserved.add(reservationKey(candidate)),files.push({filename:candidate,absolutePath,relativePath,code:code.trim()})}return{status:"ready",targetDir,files}}function getOrPlanExtractCodeBlocks(args2,directory){if(typeof args2==="object"&&args2!==null){let cached3=cachedPlans.get(args2);if(cached3?.directory===directory)return cached3.plan;let plan=planExtractCodeBlocks(args2,directory);return cachedPlans.set(args2,{directory,plan}),plan}return planExtractCodeBlocks(args2,directory)}function consumeExtractCodeBlocksPlan(args2,directory){let plan=getOrPlanExtractCodeBlocks(args2,directory);if(typeof args2==="object"&&args2!==null)cachedPlans.delete(args2);return plan}var EXT_MAP,MAX_EXTRACTED_FILES=256,MAX_COLLISION_ATTEMPTS=1e4,cachedPlans;var init_file_extractor_planner=__esm(()=>{init_path_security();EXT_MAP={python:".py",py:".py",powershell:".ps1",ps1:".ps1",pwsh:".ps1",javascript:".js",js:".js",typescript:".ts",ts:".ts",bash:".sh",sh:".sh",json:".json",yaml:".yaml",yml:".yaml",xml:".xml",html:".html",css:".css",sql:".sql",pester:".Tests.ps1",test:".Tests.ps1","":".txt"},cachedPlans=new WeakMap});import{Buffer as Buffer3}from"node:buffer";function unverifiable(reason){return{status:"unverifiable",reason}}function dedupe(paths){return[...new Set(paths)]}function genericResolver(args2){let paths=[],observedTargetField=!1;for(let key2 of SCALAR_PATH_KEYS){if(!(key2 in args2))continue;observedTargetField=!0;let value=args2[key2];if(typeof value!=="string"||value.trim()===""||containsControlCharacter(value))return unverifiable(`Malformed ${key2} target`);paths.push(value)}for(let key2 of ARRAY_PATH_KEYS){if(!(key2 in args2))continue;observedTargetField=!0;let value=args2[key2];if(!Array.isArray(value)||value.some((item)=>typeof item!=="string"||item.trim()===""||containsControlCharacter(item)))return unverifiable(`Malformed ${key2} targets`);paths.push(...value)}if(!observedTargetField||paths.length===0)return unverifiable("No write target was provided");return{status:"resolved",paths:dedupe(paths)}}function normalizeComparisonPath(filePath){return filePath.replace(/\\/g,"/").replace(/^\.\//,"")}function containsControlCharacter(value){for(let index=0;index<value.length;index++){let code=value.charCodeAt(index);if(code<=31||code===127)return!0}return!1}function parseTarget(raw,stripGitPrefix){let value=raw.replace(/\r$/,"").split("\t",1)[0]?.trim()??"";if(!value)return{error:"Empty patch target"};if(value==="/dev/null")return{};if(value.startsWith('"')||value.startsWith("'")||value.endsWith('"')||value.endsWith("'"))return{error:`Quoted patch path is unsupported: ${value}`};if(stripGitPrefix&&/\s/.test(value))return{error:`Ambiguous whitespace in diff path: ${value}`};if(stripGitPrefix&&(value.startsWith("a/")||value.startsWith("b/")))value=value.slice(2);if(!value||containsControlCharacter(value))return{error:"Malformed patch target"};return{path:value}}function parsePatchPayload(payload){let paths=[],operations=new Map,add=(raw,operation,stripGitPrefix=!1)=>{let parsed=parseTarget(raw,stripGitPrefix);if(parsed.error)return parsed.error;if(!parsed.path)return null;paths.push(parsed.path);let key2=normalizeComparisonPath(parsed.path),existing=operations.get(key2)??new Set;return existing.add(operation),operations.set(key2,existing),null},lines=normalizePatchIndentation(payload).split(/\r?\n/),beginIndices=[],endIndices=[],nativeOperationIndices=[];for(let index=0;index<lines.length;index++){let trimmed=(lines[index]??"").trim();if(trimmed==="*** Begin Patch")beginIndices.push(index);if(trimmed==="*** End Patch")endIndices.push(index);if(/^\*\*\* (?:Update|Add|Delete) File:/i.test(trimmed)||/^\*\*\* Move (?:to|from):/i.test(trimmed))nativeOperationIndices.push(index)}let hasUnifiedHeaders=lines.some((l)=>/^(---|\+\+\+)\s+/.test(l));if(beginIndices.length>0||nativeOperationIndices.length>0||!hasUnifiedHeaders&&endIndices.length>0){if(beginIndices.length===0)return"Native patch is missing *** Begin Patch";if(endIndices.length===0)return"Native patch is missing *** End Patch";if(beginIndices.length!==1||endIndices.length!==1)return"Native patch framing must contain exactly one begin and end marker";let beginIndex=beginIndices[0]??-1,endIndex=endIndices[0]??-1;if(beginIndex>=endIndex)return"Native patch has invalid begin/end marker ordering";if(nativeOperationIndices.some((index)=>index<=beginIndex||index>=endIndex))return"Native patch contains an operation outside begin/end markers";for(let index=beginIndex+1;index<endIndex;index++){let line=(lines[index]??"").trim(),match=line.match(/^\*\*\* (Update|Add|Delete) File:\s*(.*)$/);if(match){let error93=add(match[2]??"",(match[1]??"").toLowerCase());if(error93)return error93;continue}let move=line.match(/^\*\*\* Move (?:to|from):\s*(.*)$/i);if(move){let error93=add(move[1]??"","move");if(error93)return error93}}}else for(let line of lines){let git=line.match(/^diff --git\s+(.+)$/);if(git){let remainder=git[1]?.trim()??"";if(remainder.startsWith('"')||remainder.startsWith("'"))return"Quoted diff --git paths are unsupported";let parts=remainder.split(/\s+/);if(parts.length!==2)return"Malformed diff --git header";for(let part of parts){let error93=add(part,"diff",!0);if(error93)return error93}continue}let unified=line.match(/^(---|\+\+\+)\s+(.+)$/);if(unified){let error93=add(unified[2]??"","diff",!0);if(error93)return error93;continue}let rename8=line.match(/^rename (from|to)\s+(.+)$/);if(rename8){let error93=add(rename8[2]??"","rename");if(error93)return error93}}if(paths.length===0)return"Patch contains no recognizable write targets";for(let[filePath,fileOperations]of operations)if(fileOperations.has("add")&&fileOperations.has("delete"))return`Contradictory add/delete operations for ${filePath}`;return{paths:dedupe(paths),operations}}function patchResolver(args2,_context,toolName){let payloadGroups=[],aggregateBytes=0;for(let field of PATCH_PAYLOAD_KEYS){if(!(field in args2))continue;let value=args2[field];if(typeof value!=="string")return unverifiable(`Malformed ${field} payload`);payloadGroups.push({field,payloads:[value]})}if("cmd"in args2){let cmd=args2.cmd;if(typeof cmd==="string")payloadGroups.push({field:"cmd",payloads:[cmd]});else if(Array.isArray(cmd)&&cmd.every((item)=>typeof item==="string")){let payloads=cmd.filter((item,index)=>{if(index===0&&/(?:^|[/\\])(?:apply_patch|patch)(?:\.exe)?$/i.test(item))return!1;return!(item.startsWith("-")&&!item.includes(`
|
|
1180
1180
|
`)&&!item.includes("*** Begin Patch"))});payloadGroups.push({field:"cmd",payloads})}else return unverifiable("Malformed cmd payload")}if(payloadGroups.length===0)return unverifiable("No patch payload was provided");let resolvedGroups=[];for(let group of payloadGroups){if(group.payloads.length===0)return unverifiable(`Empty ${group.field} payload`);let groupPaths=[];for(let payload of group.payloads){let bytes=Buffer3.byteLength(payload,"utf8");if(bytes>MAX_PATCH_FIELD_BYTES)return unverifiable(`Patch payload exceeds 1 MB (${group.field} field)`);if(aggregateBytes+=bytes,aggregateBytes>MAX_PATCH_AGGREGATE_BYTES)return unverifiable("Aggregate patch payload exceeds size limit");let parsed=parsePatchPayload(payload);if(typeof parsed==="string")return unverifiable(`${group.field}: ${parsed}`);groupPaths.push(...parsed.paths)}resolvedGroups.push({field:group.field,paths:dedupe(groupPaths)})}let canonical=(paths2)=>paths2.map(normalizeComparisonPath).sort().join(`
|
|
1181
1181
|
`),expected=canonical(resolvedGroups[0]?.paths??[]);if(resolvedGroups.some((group)=>canonical(group.paths)!==expected))return unverifiable("Conflicting targets across patch payload fields");let paths=resolvedGroups[0]?.paths??[];if(toolName==="swarm_apply_patch"){let declared=args2.files;if(!Array.isArray(declared)||declared.some((item)=>typeof item!=="string"||item.trim()===""))return unverifiable("swarm_apply_patch requires a valid files array");let declaredSet=new Set(declared.map(normalizeComparisonPath));if(paths.some((filePath)=>!declaredSet.has(normalizeComparisonPath(filePath))))return unverifiable("Parsed patch target is missing from declared files")}return{status:"resolved",paths}}function extractResolver(args2,context){let plan=getOrPlanExtractCodeBlocks(args2,context.directory);if(plan.status==="invalid")return unverifiable(plan.reason);if(plan.status==="noop")return plan.reason==="no-code-blocks"?{status:"resolved",paths:[]}:unverifiable("content is required");return{status:"resolved",paths:plan.files.map((file3)=>file3.relativePath)}}function resolveWriteTargets2(toolName,args2,context){if(!WRITE_TOOL_NAMES.includes(toolName))return unverifiable(`Unknown write tool: ${toolName}`);if(typeof args2!=="object"||args2===null||Array.isArray(args2))return unverifiable("Write tool arguments must be an object");try{return WRITE_TARGET_RESOLVERS[toolName](args2,context)}catch(error93){return unverifiable(`Target resolution failed: ${error93 instanceof Error?error93.message:String(error93)}`)}}var MAX_PATCH_FIELD_BYTES=1e6,MAX_PATCH_AGGREGATE_BYTES=2000000,SCALAR_PATH_KEYS,ARRAY_PATH_KEYS,PATCH_PAYLOAD_KEYS,patch=(args2,context)=>patchResolver(args2,context,"patch"),applyPatch=(args2,context)=>patchResolver(args2,context,"apply_patch"),swarmApplyPatch=(args2,context)=>patchResolver(args2,context,"swarm_apply_patch"),WRITE_TARGET_RESOLVERS;var init_write_target_resolver=__esm(()=>{init_constants();init_file_extractor_planner();SCALAR_PATH_KEYS=["path","filePath","file","target"],ARRAY_PATH_KEYS=["files","paths","targetFiles"],PATCH_PAYLOAD_KEYS=["patch","input","diff","patchText","patch_text","patchPayload","text","content"];WRITE_TARGET_RESOLVERS={write:genericResolver,edit:genericResolver,patch,apply_patch:applyPatch,swarm_apply_patch:swarmApplyPatch,create_file:genericResolver,insert:genericResolver,replace:genericResolver,append:genericResolver,prepend:genericResolver,extract_code_blocks:extractResolver}});import*as fs62 from"node:fs";import*as path99 from"node:path";import{StringDecoder as StringDecoder2}from"node:string_decoder";function decisionClassOf(event){return typeof event.type==="string"&&event.type.length>0?"security":"allowed"}function decisionDiscriminator(event){if(typeof event.type==="string"&&event.type.length>0)return event.type.slice(0,64);return"shell"}function decisionTimestamp(event){if(typeof event.ts!=="string")return null;let ts=Date.parse(event.ts);return Number.isNaN(ts)?null:event.ts}function emptyFolded2(){return{totalDecisions:0,byType:{},corrupt:0,dropped:0,oldestTimestamp:null,newestTimestamp:null}}function emptyManifest2(){return{v:1,type:MANIFEST_TYPE2,schemaVersion:MANIFEST_SCHEMA2,folded:emptyFolded2(),updatedAt:new Date().toISOString()}}function parseManifestLine2(line){let trimmed=line.trim();if(!trimmed)return null;try{let obj=JSON.parse(trimmed);if(typeof obj!=="object"||obj===null)return null;let rec=obj;if(rec.type!==MANIFEST_TYPE2||rec.v!==1||rec.schemaVersion!==MANIFEST_SCHEMA2||typeof rec.folded!=="object"||rec.folded===null)return null;let f=rec.folded,manifest=emptyManifest2(),num=(v)=>typeof v==="number"&&Number.isFinite(v)&&v>=0?v:0;if(manifest.folded.totalDecisions=num(f.totalDecisions),manifest.folded.corrupt=num(f.corrupt),manifest.folded.dropped=num(f.dropped),typeof f.byType==="object"&&f.byType!==null){for(let[k,v]of Object.entries(f.byType))if(typeof v==="number"&&Number.isFinite(v)&&v>=0)manifest.folded.byType[k]=v}if(typeof f.oldestTimestamp==="string")manifest.folded.oldestTimestamp=f.oldestTimestamp;if(typeof f.newestTimestamp==="string")manifest.folded.newestTimestamp=f.newestTimestamp;return manifest.updatedAt=typeof rec.updatedAt==="string"?rec.updatedAt:new Date().toISOString(),manifest}catch{return null}}function shellAuditFilePath(directory){return path99.join(directory,".swarm","session","shell-audit.jsonl")}function lockFilePath2(directory){return path99.join(directory,".swarm","session","shell-audit.lock")}function tmpPathFor2(finalPath){return`${finalPath}.${process.pid}.tmp`}function readBoundedChunk2(filePath,maxBytes,offset=0){try{if(!_internals90.existsSync(filePath))return{text:"",truncated:!1};let fd=_internals90.openSync(filePath,"r");try{let size=_internals90.statSync(filePath).size,readable=Math.max(0,size-offset),truncated=readable>maxBytes,len=Math.min(readable,maxBytes),buf=Buffer.alloc(len),read=0;while(read<len){let n=_internals90.readSync(fd,buf,read,len-read,offset+read);if(n<=0)break;read+=n}return{text:buf.toString("utf-8",0,read),truncated}}finally{_internals90.closeSync(fd)}}catch{return warnThrottled2("bounded read failed (transient I/O)"),{text:"",truncated:!1}}}function fileSizeOrZero2(filePath){try{if(!_internals90.existsSync(filePath))return 0;return _internals90.statSync(filePath).size}catch{return 0}}function fileEndsWithNewline2(filePath){try{if(!_internals90.existsSync(filePath))return!0;let size=_internals90.statSync(filePath).size;if(size===0)return!0;let fd=_internals90.openSync(filePath,"r");try{let buf=Buffer.alloc(1);return _internals90.readSync(fd,buf,0,1,size-1)<=0||buf[0]===10}finally{_internals90.closeSync(fd)}}catch{return!0}}function foldLineInto2(folded,event){folded.totalDecisions+=1;let key2=decisionDiscriminator(event),keys=Object.keys(folded.byType);if(folded.byType[key2]!==void 0||keys.length<BY_TYPE_MAX_KEYS2)folded.byType[key2]=(folded.byType[key2]??0)+1;else folded.byType[BY_TYPE_OTHER2]=(folded.byType[BY_TYPE_OTHER2]??0)+1;let ts=decisionTimestamp(event);if(ts!==null){if(folded.oldestTimestamp===null||ts<folded.oldestTimestamp)folded.oldestTimestamp=ts;if(folded.newestTimestamp===null||ts>folded.newestTimestamp)folded.newestTimestamp=ts}}function cloneFolded2(folded){return{totalDecisions:folded.totalDecisions,byType:{...folded.byType},corrupt:folded.corrupt,dropped:folded.dropped,oldestTimestamp:folded.oldestTimestamp,newestTimestamp:folded.newestTimestamp}}function atomicReplace2(directory,content){let lines=content.split(`
|
|
@@ -1197,8 +1197,8 @@ ${line}`)}else{let prefix=fileEndsWithNewline2(filePath)?"":`
|
|
|
1197
1197
|
`;break;case"destructive_block":case"sandbox_wrap":case"sandbox_skip":{let command=truncateUtf8Safe(redactShellCommand(entry.command),maxCommand);line=`${JSON.stringify({...entry,command,commandHash:hashRedactedCommand(command)})}
|
|
1198
1198
|
`;break}case"file_write":line=`${JSON.stringify({...entry,path:redactPath(entry.path),reason:truncateUtf8Safe(redactEmbeddedPaths(entry.reason),maxReason),resolvedScope:redactPath(entry.resolvedScope)})}
|
|
1199
1199
|
`;break;case"scope_violation":line=`${JSON.stringify({...entry,path:redactPath(entry.path),declaredScope:redactPath(entry.declaredScope),resolvedScope:redactPath(entry.resolvedScope)})}
|
|
1200
|
-
`;break}try{appendShellAuditLineSync(ctx.directory,line)}catch(error93){log("guardrail audit: append failed",{directory:ctx.directory,error:error93})}}var SHELL_AUDIT_FIELD_CLASSES,REQUIRED_STRING_FIELDS;var init_audit_log=__esm(()=>{init_logger();init_helpers();init_shell_audit_store();SHELL_AUDIT_FIELD_CLASSES=Object.freeze({ts:"timestamp",sessionID:"identifier",agent:"identifier",tool:"identifier",type:"decision-type",command:"redacted-command",commandHash:"content-hash",path:"redacted-path",reason:"free-text-redacted",resolvedScope:"redacted-path",declaredScope:"redacted-path",action:"enum",destructiveCategory:"enum",executorMechanism:"enum",skipReason:"enum"}),REQUIRED_STRING_FIELDS=["ts","sessionID","agent","tool","type"]});import*as fsSync10 from"node:fs";import*as os14 from"node:os";import*as path101 from"node:path";import{fileURLToPath as fileURLToPath3}from"node:url";function readPackageName(dir){try{let manifestPath=path101.join(dir,"package.json");if(!_internals91.existsSync(manifestPath))return null;let name=JSON.parse(_internals91.readFileSync(manifestPath,"utf-8"))?.name;return typeof name==="string"?name:null}catch{return null}}function resolvePackageRoot(){if(cachedPackageRoot!==void 0)return cachedPackageRoot.root;let root=null;try{let dir=path101.dirname(fileURLToPath3(_internals91.moduleUrl()));for(let depth=0;depth<MAX_PACKAGE_ROOT_WALK_DEPTH;depth++){if(readPackageName(dir)==="opencode-swarm"){root=dir;break}let parent=path101.dirname(dir);if(parent===dir)break;dir=parent}}catch{root=null}return cachedPackageRoot={root},root}function isSelfDevelopmentWorkspace(directory){if(!directory)return!1;let resolved;try{resolved=canonicalRootKeyFresh(directory)}catch{return!1}let cached3=selfDevelopmentWorkspaces.get(resolved);if(cached3!==void 0)return cached3;let isSelfDev=readPackageName(resolved)==="opencode-swarm";if(selfDevelopmentWorkspaces.size>=MAX_CACHED_WORKSPACE_ROOTS){let oldest=selfDevelopmentWorkspaces.keys().next().value;if(oldest!==void 0)selfDevelopmentWorkspaces.delete(oldest)}return selfDevelopmentWorkspaces.set(resolved,isSelfDev),isSelfDev}function comparablePath(value){return process.platform==="win32"?value.toLowerCase():value}function isInsidePackageRoot(root,target){try{let rel=path101.relative(comparablePath(root),comparablePath(target));if(rel==="")return!0;if(rel.startsWith(".."))return!1;return!path101.isAbsolute(rel)}catch{return!1}}function expandHome(candidate){if(!candidate.startsWith("~"))return candidate;let home=_internals91.homedir();if(!home)return null;let rest=candidate.slice(1).replace(/^[\\/]/,"");return rest?path101.join(home,rest):home}function extractGuardedPathCandidates(normalizedTool,args2){let argsObj=args2??{},raw=[];if(normalizedTool==="bash"||normalizedTool==="shell"){let command=typeof argsObj.command==="string"?argsObj.command.slice(0,MAX_SCANNED_COMMAND_LENGTH):void 0;if(command){let matcher=new RegExp(SHELL_PATH_CANDIDATE_PATTERN.source,SHELL_PATH_CANDIDATE_PATTERN.flags);for(let match of command.matchAll(matcher)){let token=match[1];if(token&&token.length>1)raw.push(token);if(raw.length>=MAX_SHELL_PATH_CANDIDATES)break}}}else for(let key2 of SCALAR_PATH_KEYS2){let value=argsObj[key2];if(typeof value==="string"&&value.length>0)raw.push(value)}let resolved=[];for(let candidate of raw){let expanded=expandHome(candidate);if(!expanded)continue;if(!path101.isAbsolute(expanded))continue;try{resolved.push(path101.resolve(expanded))}catch{}}return resolved}function enforceInternalsGuard(params){let{sessionID,tool:tool3,args:args2,directory,options}=params;if(options?.enabled===!1)return;let normalizedTool=normalizeToolNameLowerCase(tool3??"");if(!GUARDED_TOOLS.has(normalizedTool))return;let match=null,relativeTarget="";try{let packageRoot=_internals91.resolvePackageRoot();if(!packageRoot)return;if(_internals91.isSelfDevelopmentWorkspace(directory))return;if(directory&&isInsidePackageRoot(packageRoot,path101.resolve(directory)))return;for(let candidate of extractGuardedPathCandidates(normalizedTool,args2))if(isInsidePackageRoot(packageRoot,candidate)){match=candidate,relativeTarget=path101.relative(packageRoot,candidate).replace(/\\/g,"/")||"<package root>";break}}catch{return}if(!match)return;try{telemetry.swarmInternalsReadDenied(sessionID,normalizedTool,relativeTarget)}catch{}throw Error(SWARM_INTERNALS_DENIAL_MESSAGE)}var SWARM_INTERNALS_DENIAL_MESSAGE="SWARM_INTERNALS_OFF_LIMITS: the swarm plugin's installed files are never the fix for a gate error. Fix the dispatch/state the error names, or report the blocker to the user.",GUARDED_TOOLS,SCALAR_PATH_KEYS2,MAX_PACKAGE_ROOT_WALK_DEPTH=12,MAX_CACHED_WORKSPACE_ROOTS=32,SHELL_PATH_CANDIDATE_PATTERN,MAX_SHELL_PATH_CANDIDATES=64,MAX_SCANNED_COMMAND_LENGTH=8192,cachedPackageRoot,selfDevelopmentWorkspaces,_internals91;var init_internals_guard=__esm(()=>{init_telemetry();init_canonical_root();init_normalize_tool_name();GUARDED_TOOLS=new Set(["read","glob","grep","bash","shell"]),SCALAR_PATH_KEYS2=["filePath","file_path","path","file","target"],SHELL_PATH_CANDIDATE_PATTERN=/(?:^|[\s'"`;|&<>()=,])((?:~|[A-Za-z]:)?[\\/][^\s'"`;|&<>()]*)/g,selfDevelopmentWorkspaces=new Map;_internals91={moduleUrl:()=>import.meta.url,existsSync:(p)=>fsSync10.existsSync(p),readFileSync:(p,enc)=>fsSync10.readFileSync(p,enc),homedir:()=>os14.homedir(),resolvePackageRoot,isSelfDevelopmentWorkspace,resetCaches:()=>{cachedPackageRoot=void 0,selfDevelopmentWorkspaces.clear()}}});import*as fs63 from"node:fs";import*as path102 from"node:path";function normalizeSandboxMechanism2(mechanism){return mechanism.toLowerCase().replace(/[^a-z0-9]+/g,"")}function pluginOwnsExecutorEnv(mechanism){if(mechanism.startsWith("native-runner/"))return!0;switch(mechanism){case"sandbox-exec":case"powershell-wrapper":case"Bubblewrap":return!0;default:return!1}}function throwDestructiveBlock(destructiveCategory,message){throw new DestructiveCommandBlockedError(message,destructiveCategory)}function isPosixRmdirExecutor(tool3,windowsShell,detectionCommand,platform=process.platform){if(windowsShell!==null)return!1;if(tool3!=="bash"&&platform==="win32")return!1;return!declaresWindowsWrapperLoose(detectionCommand)&&!CMD_WRAPPER_DECLARATION.test(detectionCommand)}function isControlStateRelativePath(relative31){return isPolicyProtectedPath(relative31.toLowerCase(),{includeDefaults:!1,additional:RMDIR_EXEMPTION_CONTROL_STATE})}function isEmptyDirectoryRemovalWithinWorkspace(targetPath,workspace){try{let lexicalRoot=path102.resolve(workspace);if(isControlStateRelativePath(path102.relative(lexicalRoot,path102.resolve(lexicalRoot,targetPath))))return!1;let root=fs63.realpathSync.native(lexicalRoot),absolute=path102.resolve(root,targetPath),parent=fs63.realpathSync.native(path102.dirname(absolute)),canonical=path102.join(parent,path102.basename(absolute));if(isControlStateRelativePath(path102.relative(root,canonical)))return!1;let stat10;try{stat10=fs63.lstatSync(canonical)}catch(error93){if(error93.code!=="ENOENT")return!1}if(stat10&&(!stat10.isDirectory()||stat10.isSymbolicLink()))return!1;return!pathIdentitiesEqual(canonical,root)&&isPathIdentityWithin(canonical,root)}catch{return!1}}function resolveWindowsWriteAuthority(tool3,command,detectedShellType,shaped,platform=process.platform){let cmdWrapper=CMD_WRAPPER_DECLARATION.test(command),psWrapper=declaresWindowsWrapperLoose(command),inheritedWindows=detectedShellType==="powershell"||detectedShellType==="cmd";if(cmdWrapper)return"cmd";if(psWrapper||shaped)return"powershell";if(inheritedWindows&&!(tool3==="bash"||tool3==="shell"&&platform!=="win32"))return detectedShellType;return null}function createToolBeforeHandler(ctx){let{effectiveDirectory,cfg,precomputedAuthorityRules,universalDenyPrefixes,shellAuditEnabled,interpreterAllowedAgents,authorityConfig,consecutiveNoToolTurns,worktreeBaseDirOverrides,getSandboxExecutor,assessSandboxEnforcement:assessSandboxEnforcement2,rememberReviewerScopeWrite,rememberScopeLeaseCandidate}=ctx,enforcePolicy=ctx.enforcePolicy!==!1;setMacOSSandboxPolicy(cfg.sandbox_macos_enabled??!1);let executionStallOptions={enabled:cfg.enabled,warnCalls:cfg.execution_stall_warn_calls,stopCalls:cfg.execution_stall_stop_calls,episodeMinutes:cfg.execution_stall_episode_minutes},internalsGuardOptions={enabled:cfg.enabled},sessionWorkspaceDirectory=(sessionID)=>resolveSessionWorkspaceDirectory(sessionID,effectiveDirectory);function resolveActiveScopeBinding(sessionID){let session=swarmState.agentSessions.get(sessionID),taskId=session?.currentTaskId??null,bindingDirectory=sessionWorkspaceDirectory(sessionID),resolution=taskId?resolveAuthorizedScopeBindingDetailed({directory:bindingDirectory,taskId,activeSessionId:sessionID}):resolveAuthorizedScopeBindingForSessionDetailed({directory:bindingDirectory,activeSessionId:sessionID}),binding=resolution.status==="found"?resolution.binding:null;if(!binding){let diagnostic=formatScopeResolutionDiagnostic({resolution,taskId,sessionId:sessionID});if(diagnostic)throw Error(diagnostic)}if(!taskId&&binding&&session)session.currentTaskId=binding.taskId,session.declaredCoderScope=[...binding.files];return binding}function resolveActiveScopeBindingObserving(sessionID){try{return resolveActiveScopeBinding(sessionID)}catch{return null}}function resolveDeclaredScope(sessionID,observing=!1){let session=swarmState.agentSessions.get(sessionID);if(!session?.currentTaskId)return session?.declaredCoderScope?.length?[...session.declaredCoderScope]:null;return(observing?resolveActiveScopeBindingObserving(sessionID):resolveActiveScopeBinding(sessionID))?.files??null}function isArchitect(sessionId){let activeAgent=swarmState.activeAgent.get(sessionId);if(activeAgent){if(stripKnownSwarmPrefix(activeAgent)===ORCHESTRATOR_NAME)return!0}let session=swarmState.agentSessions.get(sessionId);if(session){if(stripKnownSwarmPrefix(session.agentName)===ORCHESTRATOR_NAME)return!0}return!1}function handleInterpreterGating(sessionID,tool3){let normalizedTool=normalizeToolName(tool3).toLowerCase();if(normalizedTool!=="bash"&&normalizedTool!=="shell")return;if(!interpreterAllowedAgents)return;let rawAgent=swarmState.activeAgent.get(sessionID),agentRole=rawAgent?stripKnownSwarmPrefix(rawAgent).toLowerCase():"unknown";if(!interpreterAllowedAgents.some((a)=>a.toLowerCase()===agentRole))throw Error(`BLOCKED: Agent "${agentRole}" is not permitted to use the bash/shell interpreter. Allowed agents: [${interpreterAllowedAgents.map((a)=>`"${a}"`).join(", ")}]`)}function checkDestructiveCommand(sessionID,tool3,args2){if(tool3!=="bash"&&tool3!=="shell")return;if(cfg.block_destructive_commands===!1)return;let rawAgent=swarmState.activeAgent.get(sessionID),isCoder=(rawAgent?stripKnownSwarmPrefix(rawAgent).toLowerCase():"unknown")==="coder",session=swarmState.agentSessions.get(sessionID),activeBinding=isCoder&&session?.currentTaskId?resolveActiveScopeBinding(sessionID):null,bindingIdentity=activeBinding,verifiedScope=bindingIdentity&&typeof bindingIdentity.bindingId==="string"&&typeof bindingIdentity.generationId==="string"?{bindingId:bindingIdentity.bindingId,generationId:bindingIdentity.generationId,files:bindingIdentity.files}:void 0,declaredScope=activeBinding?.files??(session?.declaredCoderScope?.length?[...session.declaredCoderScope]:null),toolArgs=args2,rawCommand=typeof toolArgs?.command==="string"?toolArgs.command.trim():"";if(!rawCommand)return;let sharedClassification=classifyCommand(rawCommand),sharedGuardrailBlock=getSharedClassifierGuardrailBlock(sharedClassification);if(sharedGuardrailBlock)throwDestructiveBlock(sharedGuardrailBlock.destructiveCategory,sharedGuardrailBlock.message);let cwd=sessionWorkspaceDirectory(sessionID),command=dcNormalizeCommand(rawCommand),unwrapped=dcUnwrapWrappers(command),outerSegments=dcSplitSegments(command),innerSegments=dcSplitSegments(unwrapped),perSegmentUnwrapped=outerSegments.map((s)=>dcUnwrapWrappers(s)),allSegments=[...new Set([...outerSegments,...innerSegments,...perSegmentUnwrapped])],swarmShellVars=new Map;for(let segment of allSegments){let seg=segment.trim();if(!seg)continue;for(let m of seg.matchAll(/(?:^|[\s;&|(])([A-Za-z_][A-Za-z0-9_]*)=(?:"([^"]*)"|'([^']*)'|([^\s;&|()]+))/g)){let value=m[2]??m[3]??m[4]??"";if(m[1])swarmShellVars.set(m[1],value)}let junctionBlock=dcCheckJunctionCreation(seg,cwd);if(junctionBlock)throwDestructiveBlock("junction/symlink creation",junctionBlock);let rmTargets=dcExtractRecursiveRmTargets(seg);if(rmTargets){let decision=dcEvaluateRecursiveDeleteTargets({targets:rmTargets,cwd,verifiedScope});if(!decision.allowed)throwDestructiveBlock("recursive delete",decision.reason)}if(/^(?:rmdir|rd)(?:\.exe)?\s+.*\/[sS]/i.test(seg)){let targets=dcExtractWindowsCmdTargets(seg);if(targets.length===0)throwDestructiveBlock("recursive directory delete","BLOCKED: Windows recursive directory delete (rmdir /s or rd /s) detected. Verify the target is not a junction/symlink.");let decision=dcEvaluateRecursiveDeleteTargets({targets,cwd,verifiedScope});if(!decision.allowed)throwDestructiveBlock("recursive directory delete",decision.reason)}if(/^del(?:\.exe)?\s+.*\/[sS]/i.test(seg)){let targets=dcExtractWindowsCmdTargets(seg);if(targets.length>0){let decision=dcEvaluateRecursiveDeleteTargets({targets,cwd,verifiedScope});if(!decision.allowed)throwDestructiveBlock("recursive file delete",decision.reason)}}if(/^(?:Remove-Item|ri|rm|rmdir|del|erase|rd)\b.*-[Rr]ecurse\b/i.test(seg)||/^(?:Remove-Item|ri|rm|rmdir|del|erase|rd)\b.*-[Rr]\b/i.test(seg)){let targets=dcExtractPowerShellTargets(seg);if(targets.length>0){let decision=dcEvaluateRecursiveDeleteTargets({targets,cwd,verifiedScope});if(!decision.allowed)throwDestructiveBlock("recursive remove",decision.reason)}else throwDestructiveBlock("recursive remove","BLOCKED: PowerShell Remove-Item with -Recurse detected — cannot verify target safety")}if(/Get-ChildItem\b.*\|\s*Remove-Item\b.*-[Rr]ecurse/i.test(seg)||/gci\b.*\|\s*ri\b.*-[Rr]ecurse/i.test(seg))throwDestructiveBlock("recursive remove",'BLOCKED: PowerShell pipeline "Get-ChildItem | Remove-Item -Recurse" detected — verify target safety and avoid recursive deletion through symlinks/junctions');let worktreeRemoveMatch=/^git\s+worktree\s+remove\s+(.+)$/i.exec(seg);if(worktreeRemoveMatch){let normalizedArgs=worktreeRemoveMatch[1].trim().split(/\s+/).filter(Boolean).map((a)=>a.replace(/^["']|["']$/g,"")),isForceToken=(a)=>{let lower=a.toLowerCase();return/^-f+$/.test(lower)||lower.length>2&&"--force".startsWith(lower)};if(normalizedArgs.some(isForceToken)){let pathArgs=normalizedArgs.filter((a)=>!a.startsWith("-")),target=pathArgs.length===1?pathArgs[0].trim():null;if(!(target!=null&&target.length>0&&(declaredScope!=null&&declaredScope.length>0&&isInDeclaredScope(target,declaredScope,cwd)||isPathUnderSwarmWorktreeBase(target,cwd,worktreeBaseDirOverrides??[]))))throwDestructiveBlock("git worktree remove",'BLOCKED: "git worktree remove --force" detected — can delete working tree contents')}}if(/^rsync\b.*--delete(?:-after|-before|-during|-delay)?\b/.test(seg)){let rsyncTarget=seg.split(/\s+/).slice(1).filter((a)=>!a.startsWith("-")&&!a.includes("@")).pop();if(!(rsyncTarget!=null&&declaredScope!=null&&declaredScope.length>0&&isInDeclaredScope(rsyncTarget,declaredScope,cwd)))throwDestructiveBlock("rsync delete",'BLOCKED: "rsync --delete" detected — can delete files in the destination. Verify source is not empty.')}if(/^\\?mv\s/i.test(seg)){let mvMatch=seg.match(/^\\?mv\s+(.+)$/i);if(mvMatch){let argsStr=mvMatch[1].replace(/["']/g,"");if(/\.swarm(?:[\x5c/\s]|$)/.test(argsStr))throwDestructiveBlock("swarm path move",'BLOCKED: "mv" targeting .swarm/ detected — move operations under .swarm/ are not allowed from shell commands')}}if(/^\\?(?:move|ren)(?:\.exe)?\s/i.test(seg)){let moveMatch=seg.match(/^\\?(?:move|ren)(?:\.exe)?\s+(.+)$/i);if(moveMatch){let argsStr=moveMatch[1].replace(/["']/g,"");if(/\.swarm(?:[\x5c/\s]|$)/i.test(argsStr))throwDestructiveBlock("move/rename",'BLOCKED: "move" or "ren" targeting .swarm/ detected — move/rename operations under .swarm/ are not allowed from shell commands')}}if(/^\\?(?:Move-Item|Rename-Item|move|mi|mv|ren|rni)\b.*\.swarm(?:[\x5c/\s]|$)/i.test(seg))throwDestructiveBlock("move/rename","BLOCKED: PowerShell Move-Item or Rename-Item targeting .swarm/ detected — move/rename operations under .swarm/ are not allowed from shell commands");if(/^\\?rm\b/i.test(seg)&&!/^\\?rm\s+(?:-[a-zA-Z]*[rR][a-zA-Z]*|--recursive)\b/i.test(seg)&&/\.swarm(?:[\x5c/\s]|$)/i.test(seg))throwDestructiveBlock("swarm path delete",'BLOCKED: "rm" targeting .swarm/ detected — deleting files under .swarm/ is not allowed from shell commands');if(/\bcp\b.*\.swarm(?:[\x5c/\s]|$)/i.test(seg)&&/\brm\b.*\.swarm(?:[\x5c/\s]|$)/i.test(seg))throwDestructiveBlock("copy-and-delete bypass",'BLOCKED: "cp" of .swarm/ file followed by "rm" of .swarm/ source detected — copy-and-delete bypass is not allowed');if(/^rsync\b.*--remove-source-files\b/i.test(seg)&&/\.swarm(?:[\x5c/\s]|$)/i.test(seg))throwDestructiveBlock("archive delete source",'BLOCKED: "rsync" with delete-source flag targeting .swarm/ detected — archive with source deletion under .swarm/ is not allowed');if(/^tar\b.*--remove-files\b/i.test(seg)&&/\.swarm(?:[\x5c/\s]|$)/i.test(seg))throwDestructiveBlock("archive delete source",'BLOCKED: "tar" with delete-source flag targeting .swarm/ detected — archive with source deletion under .swarm/ is not allowed');if(/^zip\b.*\s-m\b/i.test(seg)&&/\.swarm(?:[\x5c/\s]|$)/i.test(seg))throwDestructiveBlock("archive delete source",'BLOCKED: "zip" with delete-source flag targeting .swarm/ detected — archive with source deletion under .swarm/ is not allowed');if(/^7z\b.*\s-sdel\b/i.test(seg)&&/\.swarm(?:[\x5c/\s]|$)/i.test(seg))throwDestructiveBlock("archive delete source",'BLOCKED: "7z" with delete-source flag targeting .swarm/ detected — archive with source deletion under .swarm/ is not allowed');{let HUMAN_ONLY_SWARM_SUBCOMMANDS=HUMAN_ONLY_SWARM_COMMANDS,probe2=seg.replace(/^(?:[A-Za-z_][A-Za-z0-9_]*(?:="[^"]*"|='[^']*'|=\S+)\s+)+/,"").replace(/^eval(?:\s+--)?\s+["']?/,"").replace(/["']\s*$/,"").replace(/^\$\(\s*/,"").replace(/^\(\s*/,"").replace(/\s*\)$/,"").replace(/^`/,"").replace(/`$/,"").trim();for(let i=0;i<4;i++){let before=probe2;if(probe2=probe2.replace(/^env\s+(?:-i\b|--ignore-environment\b|-u\s+\S+|-[a-zA-Z]+\s+)*\s*/,"").replace(/^command\s+(?:-[pvV]\s+)*/,"").replace(/^(?:[A-Za-z_][A-Za-z0-9_]*(?:="[^"]*"|='[^']*'|=\S+)\s+)+/,"").trim(),probe2===before)break}let dequote=(input)=>input.replace(/["']/g,""),resolveVars=(input)=>input.replace(/\$\{?([A-Za-z_][A-Za-z0-9_]*)\}?/g,(full,name)=>swarmShellVars.has(name)?swarmShellVars.get(name):full),RUNNER_SHAPE=/^(?:\\|\/?(?:[\w.:%@=+-]+[/\\])*)?(?:bunx|npx|pnpx|npm|pnpm|yarn|bun|node|deno|tsx|ts-node|opencode-swarm)\b[^|;&]*?\brun\s+\$/i;for(let variant of[resolveVars(probe2),dequote(resolveVars(probe2))])if(RUNNER_SHAPE.test(variant))throwDestructiveBlock("human-only swarm command",'BLOCKED: "opencode-swarm run" invoked with an unresolvable shell variable or command substitution in the subcommand position. Re-run with the literal subcommand name so the human-only policy can be evaluated.');let probeVariants=[probe2,dequote(probe2),resolveVars(probe2),dequote(resolveVars(probe2))],matchCaptures=(re)=>{let captures=[];for(let variant of probeVariants){let m=variant.match(re);if(m?.[1])captures.push(m[1])}return captures},blockIfHumanOnly=(captures)=>{for(let captured of captures){let normalized=captured.trim().split(/\s+/).join(" "),firstToken=normalized.includes(" ")?normalized.split(" ")[0]:normalized,cmdName=HUMAN_ONLY_SWARM_SUBCOMMANDS.has(normalized)?normalized:firstToken;if(HUMAN_ONLY_SWARM_SUBCOMMANDS.has(normalized)||HUMAN_ONLY_SWARM_SUBCOMMANDS.has(firstToken))throwDestructiveBlock("human-only swarm command",`BLOCKED: "${cmdName}" is a human-only swarm command and may not be invoked from shell by an agent. Present the situation to the user and ask them to run \`/swarm ${cmdName}\` themselves.`)}};blockIfHumanOnly(matchCaptures(/^(?:\\|\/?(?:[\w.:%@=+-]+[/\\])*)?(?:bunx|npx|pnpx|npm(?:\s+(?:exec|x)(?:\s+--)?)?|pnpm(?:\s+(?:dlx|exec))?|yarn(?:\s+(?:dlx|exec))?|bun(?:\s+x)?|node|deno\s+run|tsx|ts-node)\b[^|;&]*?\bopencode-swarm\b[^|;&]*?\brun\s+([A-Za-z0-9_-]+(?:\s+(?!-)[A-Za-z0-9_-]+)?)/i)),blockIfHumanOnly(matchCaptures(/^(?:\\|\/?(?:[\w.:%@=+-]+[/\\])*)?opencode-swarm\b[^|;&]*?\brun\s+([A-Za-z0-9_-]+(?:\s+(?!-)[A-Za-z0-9_-]+)?)/i)),blockIfHumanOnly(matchCaptures(/\bcli[/\\]+index\.[mc]?(?:js|ts)\b[^|;&]*?\brun\s+([A-Za-z0-9_-]+(?:\s+(?!-)[A-Za-z0-9_-]+)?)/i))}{let normForPathCheck=seg.replace(/\\/g,"/").replace(/\/(?:\.\/+)+/g,"/").replace(/\/{2,}/g,"/");if(/\.swarm\/spec-staleness\.json\b/i.test(normForPathCheck)){let trimmed=seg.trim(),looksReadOnly=/^(?:cat|less|more|head|tail|file|stat|ls|dir|Get-Content|gc|Get-Item|gi|type)\b/i.test(trimmed),hasWriteRedirect=/>{1,2}\s*[^\s>]/.test(trimmed);if(!looksReadOnly||hasWriteRedirect)throwDestructiveBlock("system file tampering","BLOCKED: shell command targeting .swarm/spec-staleness.json detected. This file is system-managed and gates plan-mutating tools while spec drift is unresolved. Present the drift to the user and ask them to run /swarm acknowledge-spec-drift.")}}}}function detectShellType(command){if(/^(powershell|ps1|\.\s*\\|Remove-Item|Copy-Item|Move-Item|Start-Process|New-Object|Get-ChildItem|Set-Content|Add-Content|Out-File|Invoke-WebRequest|Invoke-RestMethod|IEX|iex)\b/i.test(command)||command.includes("$PSVersionTable")||command.includes("$env:")||/-EncodedCommand|-ExecutionPolicy|Enable-PSRemoting/i.test(command))return"powershell";if(/^(cmd|c:\/|set \w+=|\.\d+|del \/|rd \/|mkdir|chdir|echo |copy |move |ren |fc |diskpart)/i.test(command)||/%[^%\s]+%/.test(command)||/\b(set|echo|if|exist)\s+/i.test(command))return"cmd";if(/^(bash|sh|zsh|ksh|ash|dash|fish|ruby|python|perl|npm|yarn|node|cargo|go|rustc|mv|cp|rm|chmod|chown|mkdir|ln|tar|gzip|gunzip|ssh|scp|rsync|sudo|su -|export |source |\.\s+)/i.test(command)||command.includes("|")||command.includes("&&")||command.includes(">>")||/\$\{?\w+\}?/.test(command))return"bash";return"unix"}function checkShellWriteScope(sessionID,callID,tool3,args2,commandOverride,options){let enforce=options?.enforce!==!1;if(tool3!=="bash"&&tool3!=="shell")return;let session=swarmState.agentSessions.get(sessionID),toolArgs=args2,command=typeof commandOverride==="string"?commandOverride.trim():typeof toolArgs?.command==="string"?toolArgs.command.trim():"";if(!command)return;let normalizedTool=tool3,detectedShellType=detectShellType(command),shaped=isPowerShellShaped(command),shellType=detectedShellType;if(enforce&&(shellType==="powershell"||shellType==="cmd"?[shellType,"posix"]:["posix"]).some((candidate)=>detectInteractiveSession(command,candidate)))throw Error("BLOCKED: interactive/session tool detected — rejecting for safety");let windowsShell=resolveWindowsWriteAuthority(normalizedTool,command,detectedShellType,shaped),wrapperDeclaredHere=declaresWindowsWrapperLoose(command),windowsAuthoritative=wrapperDeclaredHere||normalizedTool!=="bash",detect=(c)=>{let posix15=detectPosixWrites(c);if(windowsShell===null)return posix15;return mergeWriteAnalyses(posix15,detectWindowsWrites(c,windowsShell),windowsAuthoritative,wrapperDeclaredHere)},suppressParseError=(c)=>enforce&&isPowerShellReadOnlyPipeline(c),primaryAnalysis=detect(command);if(enforce&&primaryAnalysis.parseError&&!suppressParseError(command))throw Error("BLOCKED: bash write detection failed to parse command — rejecting for safety");let commandSegments=dcSplitSegments(command),unwrappedSegments=commandSegments.map((s)=>dcUnwrapWrappers(s)),didUnwrap=commandSegments.some((s,i)=>unwrappedSegments[i]!==s),detectionCommand=didUnwrap?unwrappedSegments.join(`
|
|
1201
|
-
`):command,analysis=didUnwrap?detect(detectionCommand):primaryAnalysis;if(enforce&&analysis.parseError&&!suppressParseError(detectionCommand))throw Error("BLOCKED: bash write detection failed to parse command — rejecting for safety");if(!analysis.hasWrites||analysis.writes.length===0)return;let declaredScope=resolveDeclaredScope(sessionID,!enforce),shellWriteAgent=swarmState.activeAgent.get(sessionID);if(!shellWriteAgent){if(enforce)throw Error(`WRITE BLOCKED: No active agent registered for session "${sessionID}". Agent identity must be established (e.g. via a chat message or Task delegation) before shell writes can be authorized.`);return}let shellWriteRole=stripKnownSwarmPrefix(shellWriteAgent).toLowerCase(),isArch=shellWriteRole==="architect",isCoder=shellWriteRole==="coder",shellRoleCapability=AUTHORITY_ROLE_CAPABILITIES[shellWriteRole],isImmutableNonWriter=shellRoleCapability==="read-only"||shellRoleCapability==="dedicated-tool-only";if(enforce&&isCoder&&(!declaredScope||declaredScope.length===0))throw Error(`SCOPE_NOT_DECLARED: ${shellWriteAgent} cannot perform shell writes without an active Task-correlated scope binding. ACTION[architect]: call declare_scope with the exact workspace-relative paths and replace_existing=true, then dispatch a new Task call.`);let noScopeLenient=!isArch&&!isCoder&&!isImmutableNonWriter&&(!declaredScope||declaredScope.length===0),shellDirectory=sessionWorkspaceDirectory(sessionID),resolvedWrites=resolveWriteTargets(detectionCommand,analysis.writes,shellDirectory);for(let write of resolvedWrites){if(write.resolvedPath===null){if(write.original.category==="here_doc"&&write.original.path===null)continue;if(enforce&&write.original.category==="interpreter_eval")throw Error(`BLOCKED: ${write.original.operator} evaluates inline code whose write targets cannot be verified against the declared scope — rejecting for safety. Write files with the write/edit tools or a checked-in script, and invoke installed tools directly (e.g. \`pytest\`, \`ruff\`) instead of an inline \`python -c\` / \`node -e\` eval.`);if(enforce)throw Error(`BLOCKED: bash/shell write to a dynamic path target${write.original.path?` "${write.original.path}"`:""} that cannot be statically resolved (shell variable or command substitution) — rejecting for safety.`);continue}if(enforce&&noScopeLenient&&universalDenyPrefixes.length>0){for(let prefix of universalDenyPrefixes)if(matchesAuthorityDenyPrefix(write.resolvedPath,prefix,shellDirectory))throw Error(`WRITE BLOCKED: Agent "${shellWriteAgent}" is not authorised to write "${write.resolvedPath}" (via shell). Reason: Path is under universal deny prefix "${prefix}"`)}if(noScopeLenient)continue;let authorityCheck=checkFileAuthorityWithRules(shellWriteAgent,write.resolvedPath,shellDirectory,precomputedAuthorityRules,{declaredScope,authorityEnabled:authorityConfig?.enabled,universalDenyPrefixes,verifierConfigPaths:authorityConfig?.verifier_config_paths});if(enforce&&!authorityCheck.allowed){let evidenceEventID=authorityCheck.layer==="protected-path"?recordFullAutoSevereEvidenceEvent({sessionID,childSessionID:sessionID,category:"protected_state_mutation",paths:[write.resolvedPath]}):void 0;throw Error(`WRITE BLOCKED: Agent "${shellWriteAgent}" is not authorised to write "${write.resolvedPath}" (via shell). Reason: ${authorityCheck.reason}${evidenceEventID?` Evidence event: ${evidenceEventID}.`:""}`)}if(enforce&&declaredScope&&declaredScope.length>0&&!isInDeclaredScope(write.resolvedPath,declaredScope,shellDirectory)&&!(write.original.emptyDirectoryRemoval===!0&&isPosixRmdirExecutor(normalizedTool,windowsShell,detectionCommand)&&isEmptyDirectoryRemovalWithinWorkspace(write.resolvedPath,shellDirectory))){let safeTarget=sanitizeDiagnosticText(write.resolvedPath,320),scopeSummary=declaredScope.slice(0,10).map((entry)=>sanitizeDiagnosticText(entry,160)).join(", "),omitted=Math.max(0,declaredScope.length-10);throw Error(`WRITE BLOCKED: SCOPE_VIOLATION: shell write target "${safeTarget}" is outside the active scope [${scopeSummary}${omitted>0?`, ... (+${omitted} more)`:""}]. ACTION[architect]: if the target is intended, call declare_scope for the exact workspace-relative path and redispatch; otherwise correct the command.`)}if(isCoder&&session?.currentTaskId){let writeBinding=enforce?resolveActiveScopeBinding(sessionID):resolveActiveScopeBindingObserving(sessionID);if(writeBinding?.activation==="active"&&writeBinding.parentOwnerSessionId&&writeBinding.parentCallId){let relativeTarget=path102.relative(path102.resolve(shellDirectory),path102.resolve(shellDirectory,write.resolvedPath)).replace(/\\/g,"/");if(recordReviewerScopeGenerationFile({parentSessionID:writeBinding.parentOwnerSessionId,taskId:writeBinding.taskId,coderCallID:writeBinding.parentCallId,file:relativeTarget}))rememberReviewerScopeWrite?.({callID,parentSessionID:writeBinding.parentOwnerSessionId,taskId:writeBinding.taskId,coderCallID:writeBinding.parentCallId,file:relativeTarget})}}}if(isCoder&&session?.currentTaskId){let binding=enforce?resolveActiveScopeBinding(sessionID):resolveActiveScopeBindingObserving(sessionID);if(binding)rememberScopeLeaseCandidate?.({callID,sessionID,tool:tool3,directory:shellDirectory,binding,targets:resolvedWrites.flatMap((write)=>write.resolvedPath===null?[]:[path102.resolve(shellDirectory,write.resolvedPath)]),args:args2})}}function isSandboxWrapperInvocation(raw){let head=raw.replace(/^\s*(?:(?:exec|(?:\/(?:usr\/)?bin\/)?env)(?:\s+(?:-\S+|[A-Za-z_]\w*=\S*))*\s+)*/,"");return/^(?:\/(?:usr\/(?:local\/)?)?bin\/)?bwrap(?:\s|$)/.test(head)}async function applySandboxExecution(sessionID,callID,tool3,args2,agent,command,auditEnabled){if(tool3!=="bash"&&tool3!=="shell")return;let toolArgs=args2,rawCommand=typeof toolArgs?.command==="string"?toolArgs.command.trim():"";if(!rawCommand||!toolArgs)return;let executor=await getSandboxExecutor(),sandboxConfig=cfg.sandbox,originalCommandHash=hashArgs({command:rawCommand}),commandIdentity=`cmd=${originalCommandHash}`,assessment=await assessSandboxEnforcement2(sandboxConfig?{mode:sandboxConfig.mode,require_filesystem:sandboxConfig.require_filesystem,require_network:sandboxConfig.require_network,require_process:sandboxConfig.require_process,network_mode:sandboxConfig.network_mode,network_allowlist:sandboxConfig.network_allowlist,writable_roots:sandboxConfig.writable_roots}:void 0),capabilityIdentity=`cap=${assessment.capability.identity}`,recordOutcome2=(outcome)=>recordSandboxWrapOutcome({...outcome,sessionID,callID,originalCommandHash,originalCommand:rawCommand,assessmentCacheKey:assessment.cacheKey,executorMechanism:executor?.mechanism??"none",capabilityMechanism:assessment.capability.mechanism}),clearRecordedOutcome=()=>{clearSandboxWrapOutcome(sessionID,callID)};if(sandboxConfig?.mode==="required"){let assessmentSupported=assessment.supported!==!1,assessmentUnsupported=assessment.unsupported??[],missing=!executor||!executor.isAvailable()?["executor"]:assessment.missing;if(!executor||!executor.isAvailable()||!assessmentSupported||!assessment.satisfied){let missingOrUnsupported=assessmentSupported?missing.join(", "):assessmentUnsupported.join(", "),skipReason=missing[0]==="executor"?`required sandbox executor unavailable [${commandIdentity} ${capabilityIdentity}]`:!assessmentSupported?`required sandbox policy unsupported (${missingOrUnsupported}) [${commandIdentity} ${capabilityIdentity}]`:`required sandbox capability unsatisfied (${missingOrUnsupported}) [${commandIdentity} ${capabilityIdentity}]`;throw recordOutcome2({finalCommandHash:originalCommandHash,wrapped:!1,capabilityIdentity:assessment.capability.identity,reason:skipReason}),clearRecordedOutcome(),appendGuardrailDecision({type:"sandbox_skip",ts:new Date().toISOString(),sessionID,agent,tool:tool3,command,executorMechanism:executor?.mechanism??"none",skipReason},{directory:effectiveDirectory,enabled:auditEnabled}),Error(`[sandbox] BLOCKED: Required sandbox policy unsatisfied (${missingOrUnsupported}). [${commandIdentity} ${capabilityIdentity}] Command will not be executed unsandboxed.`)}}if(!executor||!executor.isAvailable()){if(recordOutcome2({finalCommandHash:originalCommandHash,wrapped:!1,capabilityIdentity:assessment.capability.identity,reason:"executor not available"}),!hasWarnedSandboxUnavailable)hasWarnedSandboxUnavailable=!0,criticalWarn("[guardrails] sandbox executor unavailable; shell commands will run unsandboxed. Run /swarm diagnose for details.");appendGuardrailDecision({type:"sandbox_skip",ts:new Date().toISOString(),sessionID,agent,tool:tool3,command,executorMechanism:executor?.mechanism??"none",skipReason:"executor not available"},{directory:effectiveDirectory,enabled:auditEnabled});return}let declaredPaths=resolveDeclaredScope(sessionID,!enforcePolicy);if(!declaredPaths||declaredPaths.length===0){if(recordOutcome2({finalCommandHash:originalCommandHash,wrapped:!1,capabilityIdentity:assessment.capability.identity,reason:"no declared scope"}),sandboxConfig?.mode==="required")throw clearRecordedOutcome(),Error("[sandbox] BLOCKED: Required sandbox policy needs a declared writable scope; command will not execute unsandboxed.");return}let resolved=resolveScopePaths(declaredPaths,sessionWorkspaceDirectory(sessionID)),configuredWritableRoots=resolveScopePaths(sandboxConfig?.writable_roots??[],sessionWorkspaceDirectory(sessionID));if(configuredWritableRoots.rejected.length>0){if(recordOutcome2({finalCommandHash:originalCommandHash,wrapped:!1,capabilityIdentity:assessment.capability.identity,reason:`configured writable_roots rejected (${configuredWritableRoots.rejected.map((item)=>item.path).join(", ")})`}),sandboxConfig?.mode==="required")throw clearRecordedOutcome(),Error("[sandbox] BLOCKED: Required sandbox policy contains writable_roots outside the session workspace; command will not execute unsandboxed.");return}if(resolved.paths.length===0){if(recordOutcome2({finalCommandHash:originalCommandHash,wrapped:!1,capabilityIdentity:assessment.capability.identity,reason:"resolved scope empty"}),sandboxConfig?.mode==="required")throw clearRecordedOutcome(),Error("[sandbox] BLOCKED: Required sandbox policy resolved no writable scope; command will not execute unsandboxed.");return}let writablePaths=[...new Set([...resolved.paths,...configuredWritableRoots.paths])];if(normalizeSandboxMechanism2(executor.mechanism)==="bubblewrap"&&isSandboxWrapperInvocation(rawCommand))throw recordOutcome2({finalCommandHash:originalCommandHash,wrapped:!1,capabilityIdentity:assessment.capability.identity,reason:"command already invokes the sandbox wrapper"}),clearRecordedOutcome(),Error(`[sandbox] BLOCKED: the command already invokes bwrap. Every bash call is sandboxed by the harness (${executor.mechanism}); a nested wrapper fails with "No permissions to create new namespace". Re-issue the plain command without the bwrap prefix.`);let workspaceRoot=sessionWorkspaceDirectory(sessionID),readonlyWorkspaceRoot=workspaceRoot;try{readonlyWorkspaceRoot=fs63.realpathSync(workspaceRoot)}catch{}try{let envOverrides=pluginOwnsExecutorEnv(executor.mechanism)?executor.getEnvOverrides():void 0,wrappedCommand=executor.wrapCommand(rawCommand,writablePaths,void 0,envOverrides,{network_mode:sandboxConfig?.network_mode??"off",network_allowlist:sandboxConfig?.network_allowlist??[],writable_roots:configuredWritableRoots.paths,readonly_roots:[readonlyWorkspaceRoot]});if(wrappedCommand.trim()===rawCommand)throw recordOutcome2({finalCommandHash:originalCommandHash,wrapped:!1,capabilityIdentity:assessment.capability.identity,reason:"sandbox wrapper returned the original command unchanged"}),clearRecordedOutcome(),Error(`[sandbox] BLOCKED: ${executor.mechanism} returned the original command unchanged. [${commandIdentity} ${capabilityIdentity}] Command will not be executed unsandboxed.`);if(normalizeSandboxMechanism2(executor.mechanism)!==normalizeSandboxMechanism2(assessment.capability.mechanism))throw recordOutcome2({finalCommandHash:originalCommandHash,wrapped:!1,capabilityIdentity:assessment.capability.identity,reason:"sandbox executor mechanism no longer matches the assessed capability"}),clearRecordedOutcome(),Error(`[sandbox] BLOCKED: sandbox executor mechanism drifted from the assessed capability (${executor.mechanism} != ${assessment.capability.mechanism}). [${commandIdentity} ${capabilityIdentity}]`);toolArgs.command=wrappedCommand,recordOutcome2({finalCommandHash:hashArgs({command:wrappedCommand}),wrapped:!0,capabilityIdentity:assessment.capability.identity,reason:"wrapped"}),markToolExecutionSandboxWrapped(sessionID,callID),appendGuardrailDecision({type:"sandbox_wrap",ts:new Date().toISOString(),sessionID,agent,tool:tool3,command:rawCommand,executorMechanism:executor.mechanism},{directory:effectiveDirectory,enabled:auditEnabled})}catch(err){recordOutcome2({finalCommandHash:originalCommandHash,wrapped:!1,capabilityIdentity:assessment.capability.identity,reason:err instanceof Error?err.message:String(err)}),clearRecordedOutcome(),forgetToolExecution(sessionID,callID);let message=`[sandbox] BLOCKED: Failed to wrap command with ${executor.mechanism}: ${err}. Command will not be executed unsandboxed.`,circuit=recordNonTransientFailure(sessionID,"sandbox_wrapper_failure",message,{tool:tool3,args:{command:rawCommand},armAttempt:!0});if(circuit?.hardStop)throw Error(nonTransientHardStopMessage(circuit));throw Error(message)}}async function checkGateLimits(params){let{sessionID,window:window2,agentConfig,elapsedMinutes,repetitionCount}=params;if(agentConfig.max_tool_calls>0&&window2.toolCalls>=agentConfig.max_tool_calls)throw window2.hardLimitHit=!0,telemetry.hardLimitHit(sessionID,window2.agentName,"tool_calls",window2.toolCalls),warn("Circuit breaker: tool call limit hit",{sessionID,agentName:window2.agentName,invocationId:window2.id,windowKey:`${window2.agentName}:${window2.id}`,resolvedMaxCalls:agentConfig.max_tool_calls,currentCalls:window2.toolCalls}),Error(`\uD83D\uDED1 LIMIT REACHED: Tool calls exhausted (${window2.toolCalls}/${agentConfig.max_tool_calls}). Finish the current operation and return your progress summary.`);if(agentConfig.max_duration_minutes>0&&elapsedMinutes>=agentConfig.max_duration_minutes)throw window2.hardLimitHit=!0,telemetry.hardLimitHit(sessionID,window2.agentName,"duration",elapsedMinutes),warn("Circuit breaker: duration limit hit",{sessionID,agentName:window2.agentName,invocationId:window2.id,windowKey:`${window2.agentName}:${window2.id}`,resolvedMaxMinutes:agentConfig.max_duration_minutes,elapsedMinutes:Math.floor(elapsedMinutes)}),Error(`\uD83D\uDED1 LIMIT REACHED: Duration exhausted (${Math.floor(elapsedMinutes)}/${agentConfig.max_duration_minutes} min). Finish the current operation and return your progress summary.`);if(repetitionCount>=agentConfig.max_repetitions)throw window2.hardLimitHit=!0,telemetry.hardLimitHit(sessionID,window2.agentName,"repetition",repetitionCount),Error(`\uD83D\uDED1 LIMIT REACHED: Repeated the same tool call ${repetitionCount} times. This suggests a loop. Return your progress summary.`);if(window2.consecutiveErrors>=agentConfig.max_consecutive_errors)throw window2.hardLimitHit=!0,telemetry.hardLimitHit(sessionID,window2.agentName,"consecutive_errors",window2.consecutiveErrors),Error(`\uD83D\uDED1 LIMIT REACHED: ${window2.consecutiveErrors} consecutive tool errors detected. Return your progress summary with details of what went wrong. Run /swarm reset-session to clear the circuit breaker without restarting your session.`);let idleMinutes=(Date.now()-window2.lastSuccessTimeMs)/60000;if(idleMinutes>=agentConfig.idle_timeout_minutes)throw window2.hardLimitHit=!0,telemetry.hardLimitHit(sessionID,window2.agentName,"idle_timeout",idleMinutes),warn("Circuit breaker: idle timeout hit",{sessionID,agentName:window2.agentName,invocationId:window2.id,windowKey:`${window2.agentName}:${window2.id}`,idleTimeoutMinutes:agentConfig.idle_timeout_minutes,idleMinutes:Math.floor(idleMinutes)}),Error(`\uD83D\uDED1 LIMIT REACHED: No successful tool call for ${Math.floor(idleMinutes)} minutes (idle timeout: ${agentConfig.idle_timeout_minutes} min). This suggests the agent may be stuck. Return your progress summary.`);if(!window2.warningIssued){let toolPct=agentConfig.max_tool_calls>0?window2.toolCalls/agentConfig.max_tool_calls:0,durationPct=agentConfig.max_duration_minutes>0?elapsedMinutes/agentConfig.max_duration_minutes:0,repPct=repetitionCount/agentConfig.max_repetitions,errorPct=window2.consecutiveErrors/agentConfig.max_consecutive_errors,reasons=[];if(agentConfig.max_tool_calls>0&&toolPct>=agentConfig.warning_threshold)reasons.push(`tool calls ${window2.toolCalls}/${agentConfig.max_tool_calls}`);if(durationPct>=agentConfig.warning_threshold)reasons.push(`duration ${Math.floor(elapsedMinutes)}/${agentConfig.max_duration_minutes} min`);if(repPct>=agentConfig.warning_threshold)reasons.push(`repetitions ${repetitionCount}/${agentConfig.max_repetitions}`);if(errorPct>=agentConfig.warning_threshold)reasons.push(`errors ${window2.consecutiveErrors}/${agentConfig.max_consecutive_errors}`);if(reasons.length>0)window2.warningIssued=!0,window2.warningReason=reasons.join(", ")}}function handleDelegatedWriteTracking(sessionID,tool3,args2){if(!swarmState.agentSessions.get(sessionID)?.delegationActive&&isArchitect(sessionID)){let coderDeleg=isAgentDelegation(tool3,args2);if(coderDeleg.isDelegation&&coderDeleg.targetAgent==="coder"){let coderSession=swarmState.agentSessions.get(sessionID);if(coderSession){let taskId=coderSession.currentTaskId??coderSession.lastCoderDelegationTaskId??`${sessionID}:unknown`;if(coderSession.currentTaskId=taskId,resetModifiedFilesForTask(coderSession,taskId),!coderSession.revisionLimitHit)coderSession.coderRevisions=0}}}}function isAgentDelegation(toolName,args2){if(!isTaskToolId(toolName))return{isDelegation:!1,targetAgent:null};let argsObj=args2;if(!argsObj)return{isDelegation:!1,targetAgent:null};let subagentType=argsObj.subagent_type;if(typeof subagentType==="string")return{isDelegation:!0,targetAgent:stripKnownSwarmPrefix(subagentType)};return{isDelegation:!1,targetAgent:null}}function handleLoopDetection(sessionID,tool3,args2){if(!isTaskToolId(tool3))return;let loopArgs=args2,loopResult=detectLoop(sessionID,tool3,loopArgs);if(loopResult.count>=5)throw Error(`CIRCUIT BREAKER: Delegation loop detected (${loopResult.count} identical patterns). Further identical delegations are blocked. Diagnose or rescope the task before retrying.`);else if(loopResult.count>=3&&loopResult.count<5){let agentName=typeof loopArgs?.subagent_type==="string"?loopArgs.subagent_type:"agent",loopSession=swarmState.agentSessions.get(sessionID);if(loopSession){let loopPattern=loopResult.pattern,modifiedFiles=loopSession.currentTaskId?getModifiedFilesForTask(loopSession,loopSession.currentTaskId):[],accomplishmentSummary=modifiedFiles.length>0?`Modified ${modifiedFiles.length} file(s): ${modifiedFiles.slice(0,3).join(", ")}${modifiedFiles.length>3?"...":""}`:"No files modified yet",alternativeSuggestions={coder:"Try a different task spec, simplify the constraint, or escalate to user",reviewer:"Try a different review dimension or escalate to user",test_engineer:"Run a specific test file with targeted scope",explorer:"Narrow the search scope or check a specific file directly"},cleanAgent=stripKnownSwarmPrefix(agentName).toLowerCase(),suggestion=alternativeSuggestions[cleanAgent]??"Try a different agent, different instructions, or escalate to the user";loopSession.loopWarningPending={agent:agentName,message:[`LOOP DETECTED: Pattern "${loopPattern}" repeated 3 times.`,`Agent: ${agentName}`,`Accomplished: ${accomplishmentSummary}`,`Suggested action: ${suggestion}`,"If still stuck after trying alternatives, escalate to the user."].join(`
|
|
1200
|
+
`;break}try{appendShellAuditLineSync(ctx.directory,line)}catch(error93){log("guardrail audit: append failed",{directory:ctx.directory,error:error93})}}var SHELL_AUDIT_FIELD_CLASSES,REQUIRED_STRING_FIELDS;var init_audit_log=__esm(()=>{init_logger();init_helpers();init_shell_audit_store();SHELL_AUDIT_FIELD_CLASSES=Object.freeze({ts:"timestamp",sessionID:"identifier",agent:"identifier",tool:"identifier",type:"decision-type",command:"redacted-command",commandHash:"content-hash",path:"redacted-path",reason:"free-text-redacted",resolvedScope:"redacted-path",declaredScope:"redacted-path",action:"enum",destructiveCategory:"enum",executorMechanism:"enum",skipReason:"enum"}),REQUIRED_STRING_FIELDS=["ts","sessionID","agent","tool","type"]});import*as fsSync10 from"node:fs";import*as os14 from"node:os";import*as path101 from"node:path";import{fileURLToPath as fileURLToPath3}from"node:url";function readPackageName(dir){try{let manifestPath=path101.join(dir,"package.json");if(!_internals91.existsSync(manifestPath))return null;let name=JSON.parse(_internals91.readFileSync(manifestPath,"utf-8"))?.name;return typeof name==="string"?name:null}catch{return null}}function resolvePackageRoot(){if(cachedPackageRoot!==void 0)return cachedPackageRoot.root;let root=null;try{let dir=path101.dirname(fileURLToPath3(_internals91.moduleUrl()));for(let depth=0;depth<MAX_PACKAGE_ROOT_WALK_DEPTH;depth++){if(readPackageName(dir)==="opencode-swarm"){root=dir;break}let parent=path101.dirname(dir);if(parent===dir)break;dir=parent}}catch{root=null}return cachedPackageRoot={root},root}function isSelfDevelopmentWorkspace(directory){if(!directory)return!1;let resolved;try{resolved=canonicalRootKeyFresh(directory)}catch{return!1}let cached3=selfDevelopmentWorkspaces.get(resolved);if(cached3!==void 0)return cached3;let isSelfDev=readPackageName(resolved)==="opencode-swarm";if(selfDevelopmentWorkspaces.size>=MAX_CACHED_WORKSPACE_ROOTS){let oldest=selfDevelopmentWorkspaces.keys().next().value;if(oldest!==void 0)selfDevelopmentWorkspaces.delete(oldest)}return selfDevelopmentWorkspaces.set(resolved,isSelfDev),isSelfDev}function comparablePath(value){return process.platform==="win32"?value.toLowerCase():value}function isInsidePackageRoot(root,target){try{let rel=path101.relative(comparablePath(root),comparablePath(target));if(rel==="")return!0;if(rel.startsWith(".."))return!1;return!path101.isAbsolute(rel)}catch{return!1}}function expandHome(candidate){if(!candidate.startsWith("~"))return candidate;let home=_internals91.homedir();if(!home)return null;let rest=candidate.slice(1).replace(/^[\\/]/,"");return rest?path101.join(home,rest):home}function extractGuardedPathCandidates(normalizedTool,args2){let argsObj=args2??{},raw=[];if(normalizedTool==="bash"||normalizedTool==="shell"){let command=typeof argsObj.command==="string"?argsObj.command.slice(0,MAX_SCANNED_COMMAND_LENGTH):void 0;if(command){let matcher=new RegExp(SHELL_PATH_CANDIDATE_PATTERN.source,SHELL_PATH_CANDIDATE_PATTERN.flags);for(let match of command.matchAll(matcher)){let token=match[1];if(token&&token.length>1)raw.push(token);if(raw.length>=MAX_SHELL_PATH_CANDIDATES)break}}}else for(let key2 of SCALAR_PATH_KEYS2){let value=argsObj[key2];if(typeof value==="string"&&value.length>0)raw.push(value)}let resolved=[];for(let candidate of raw){let expanded=expandHome(candidate);if(!expanded)continue;if(!path101.isAbsolute(expanded))continue;try{resolved.push(path101.resolve(expanded))}catch{}}return resolved}function enforceInternalsGuard(params){let{sessionID,tool:tool3,args:args2,directory,options}=params;if(options?.enabled===!1)return;let normalizedTool=normalizeToolNameLowerCase(tool3??"");if(!GUARDED_TOOLS.has(normalizedTool))return;let match=null,relativeTarget="";try{let packageRoot=_internals91.resolvePackageRoot();if(!packageRoot)return;if(_internals91.isSelfDevelopmentWorkspace(directory))return;if(directory&&isInsidePackageRoot(packageRoot,path101.resolve(directory)))return;for(let candidate of extractGuardedPathCandidates(normalizedTool,args2))if(isInsidePackageRoot(packageRoot,candidate)){match=candidate,relativeTarget=path101.relative(packageRoot,candidate).replace(/\\/g,"/")||"<package root>";break}}catch{return}if(!match)return;try{telemetry.swarmInternalsReadDenied(sessionID,normalizedTool,relativeTarget)}catch{}throw Error(SWARM_INTERNALS_DENIAL_MESSAGE)}var SWARM_INTERNALS_DENIAL_MESSAGE="SWARM_INTERNALS_OFF_LIMITS: the swarm plugin's installed files are never the fix for a gate error. Fix the dispatch/state the error names, or report the blocker to the user.",GUARDED_TOOLS,SCALAR_PATH_KEYS2,MAX_PACKAGE_ROOT_WALK_DEPTH=12,MAX_CACHED_WORKSPACE_ROOTS=32,SHELL_PATH_CANDIDATE_PATTERN,MAX_SHELL_PATH_CANDIDATES=64,MAX_SCANNED_COMMAND_LENGTH=8192,cachedPackageRoot,selfDevelopmentWorkspaces,_internals91;var init_internals_guard=__esm(()=>{init_telemetry();init_canonical_root();init_normalize_tool_name();GUARDED_TOOLS=new Set(["read","glob","grep","bash","shell"]),SCALAR_PATH_KEYS2=["filePath","file_path","path","file","target"],SHELL_PATH_CANDIDATE_PATTERN=/(?:^|[\s'"`;|&<>()=,])((?:~|[A-Za-z]:)?[\\/][^\s'"`;|&<>()]*)/g,selfDevelopmentWorkspaces=new Map;_internals91={moduleUrl:()=>import.meta.url,existsSync:(p)=>fsSync10.existsSync(p),readFileSync:(p,enc)=>fsSync10.readFileSync(p,enc),homedir:()=>os14.homedir(),resolvePackageRoot,isSelfDevelopmentWorkspace,resetCaches:()=>{cachedPackageRoot=void 0,selfDevelopmentWorkspaces.clear()}}});import*as fs63 from"node:fs";import*as path102 from"node:path";function normalizeSandboxMechanism2(mechanism){return mechanism.toLowerCase().replace(/[^a-z0-9]+/g,"")}function pluginOwnsExecutorEnv(mechanism){if(mechanism.startsWith("native-runner/"))return!0;switch(mechanism){case"sandbox-exec":case"powershell-wrapper":case"Bubblewrap":return!0;default:return!1}}function throwDestructiveBlock(destructiveCategory,message){throw new DestructiveCommandBlockedError(message,destructiveCategory)}function isPosixRmdirExecutor(tool3,windowsShell,detectionCommand,platform=process.platform){if(windowsShell!==null)return!1;if(tool3!=="bash"&&platform==="win32")return!1;return!declaresWindowsWrapperLoose(detectionCommand)&&!CMD_WRAPPER_DECLARATION.test(detectionCommand)}function isControlStateRelativePath(relative31){return isPolicyProtectedPath(relative31.toLowerCase(),{includeDefaults:!1,additional:RMDIR_EXEMPTION_CONTROL_STATE})}function isEmptyDirectoryRemovalWithinWorkspace(targetPath,workspace){try{let lexicalRoot=path102.resolve(workspace);if(isControlStateRelativePath(path102.relative(lexicalRoot,path102.resolve(lexicalRoot,targetPath))))return!1;let root=fs63.realpathSync.native(lexicalRoot),absolute=path102.resolve(root,targetPath),parent=fs63.realpathSync.native(path102.dirname(absolute)),canonical=path102.join(parent,path102.basename(absolute));if(isControlStateRelativePath(path102.relative(root,canonical)))return!1;let stat10;try{stat10=fs63.lstatSync(canonical)}catch(error93){if(error93.code!=="ENOENT")return!1}if(stat10&&(!stat10.isDirectory()||stat10.isSymbolicLink()))return!1;return!pathIdentitiesEqual(canonical,root)&&isPathIdentityWithin(canonical,root)}catch{return!1}}function resolveWindowsWriteAuthority(tool3,command,detectedShellType,shaped,platform=process.platform,hostShell){let cmdWrapper=CMD_WRAPPER_DECLARATION.test(command),psWrapper=declaresWindowsWrapperLoose(command),inheritedWindows=detectedShellType==="powershell"||detectedShellType==="cmd";if(cmdWrapper)return"cmd";if(psWrapper||shaped)return"powershell";if(tool3==="bash")return null;if(tool3==="shell"&&hostShell!==void 0&&hostShell!=="")return hostShellGrammarFamily(hostShell)==="windows"&&inheritedWindows?detectedShellType:null;let posixShellTool=tool3==="bash"||tool3==="shell";if(inheritedWindows&&!posixShellTool)return detectedShellType;if(inheritedWindows&&posixShellTool&&platform==="win32")return detectedShellType;return null}function createToolBeforeHandler(ctx){let{effectiveDirectory,cfg,precomputedAuthorityRules,universalDenyPrefixes,shellAuditEnabled,interpreterAllowedAgents,authorityConfig,consecutiveNoToolTurns,worktreeBaseDirOverrides,getSandboxExecutor,assessSandboxEnforcement:assessSandboxEnforcement2,rememberReviewerScopeWrite,rememberScopeLeaseCandidate}=ctx,enforcePolicy=ctx.enforcePolicy!==!1;setMacOSSandboxPolicy(cfg.sandbox_macos_enabled??!1);let executionStallOptions={enabled:cfg.enabled,warnCalls:cfg.execution_stall_warn_calls,stopCalls:cfg.execution_stall_stop_calls,episodeMinutes:cfg.execution_stall_episode_minutes},internalsGuardOptions={enabled:cfg.enabled},sessionWorkspaceDirectory=(sessionID)=>resolveSessionWorkspaceDirectory(sessionID,effectiveDirectory);function resolveActiveScopeBinding(sessionID){let session=swarmState.agentSessions.get(sessionID),taskId=session?.currentTaskId??null,bindingDirectory=sessionWorkspaceDirectory(sessionID),resolution=taskId?resolveAuthorizedScopeBindingDetailed({directory:bindingDirectory,taskId,activeSessionId:sessionID}):resolveAuthorizedScopeBindingForSessionDetailed({directory:bindingDirectory,activeSessionId:sessionID}),binding=resolution.status==="found"?resolution.binding:null;if(!binding){let diagnostic=formatScopeResolutionDiagnostic({resolution,taskId,sessionId:sessionID});if(diagnostic)throw Error(diagnostic)}if(!taskId&&binding&&session)session.currentTaskId=binding.taskId,session.declaredCoderScope=[...binding.files];return binding}function resolveActiveScopeBindingObserving(sessionID){try{return resolveActiveScopeBinding(sessionID)}catch{return null}}function resolveDeclaredScope(sessionID,observing=!1){let session=swarmState.agentSessions.get(sessionID);if(!session?.currentTaskId)return session?.declaredCoderScope?.length?[...session.declaredCoderScope]:null;return(observing?resolveActiveScopeBindingObserving(sessionID):resolveActiveScopeBinding(sessionID))?.files??null}function isArchitect(sessionId){let activeAgent=swarmState.activeAgent.get(sessionId);if(activeAgent){if(stripKnownSwarmPrefix(activeAgent)===ORCHESTRATOR_NAME)return!0}let session=swarmState.agentSessions.get(sessionId);if(session){if(stripKnownSwarmPrefix(session.agentName)===ORCHESTRATOR_NAME)return!0}return!1}function handleInterpreterGating(sessionID,tool3){let normalizedTool=normalizeToolName(tool3).toLowerCase();if(normalizedTool!=="bash"&&normalizedTool!=="shell")return;if(!interpreterAllowedAgents)return;let rawAgent=swarmState.activeAgent.get(sessionID),agentRole=rawAgent?stripKnownSwarmPrefix(rawAgent).toLowerCase():"unknown";if(!interpreterAllowedAgents.some((a)=>a.toLowerCase()===agentRole))throw Error(`BLOCKED: Agent "${agentRole}" is not permitted to use the bash/shell interpreter. Allowed agents: [${interpreterAllowedAgents.map((a)=>`"${a}"`).join(", ")}]`)}function checkDestructiveCommand(sessionID,tool3,args2){if(tool3!=="bash"&&tool3!=="shell")return;if(cfg.block_destructive_commands===!1)return;let rawAgent=swarmState.activeAgent.get(sessionID),isCoder=(rawAgent?stripKnownSwarmPrefix(rawAgent).toLowerCase():"unknown")==="coder",session=swarmState.agentSessions.get(sessionID),activeBinding=isCoder&&session?.currentTaskId?resolveActiveScopeBinding(sessionID):null,bindingIdentity=activeBinding,verifiedScope=bindingIdentity&&typeof bindingIdentity.bindingId==="string"&&typeof bindingIdentity.generationId==="string"?{bindingId:bindingIdentity.bindingId,generationId:bindingIdentity.generationId,files:bindingIdentity.files}:void 0,declaredScope=activeBinding?.files??(session?.declaredCoderScope?.length?[...session.declaredCoderScope]:null),toolArgs=args2,rawCommand=typeof toolArgs?.command==="string"?toolArgs.command.trim():"";if(!rawCommand)return;let sharedClassification=classifyCommand(rawCommand),sharedGuardrailBlock=getSharedClassifierGuardrailBlock(sharedClassification);if(sharedGuardrailBlock)throwDestructiveBlock(sharedGuardrailBlock.destructiveCategory,sharedGuardrailBlock.message);let cwd=sessionWorkspaceDirectory(sessionID),command=dcNormalizeCommand(rawCommand),unwrapped=dcUnwrapWrappers(command),outerSegments=dcSplitSegments(command),innerSegments=dcSplitSegments(unwrapped),perSegmentUnwrapped=outerSegments.map((s)=>dcUnwrapWrappers(s)),allSegments=[...new Set([...outerSegments,...innerSegments,...perSegmentUnwrapped])],swarmShellVars=new Map;for(let segment of allSegments){let seg=segment.trim();if(!seg)continue;for(let m of seg.matchAll(/(?:^|[\s;&|(])([A-Za-z_][A-Za-z0-9_]*)=(?:"([^"]*)"|'([^']*)'|([^\s;&|()]+))/g)){let value=m[2]??m[3]??m[4]??"";if(m[1])swarmShellVars.set(m[1],value)}let junctionBlock=dcCheckJunctionCreation(seg,cwd);if(junctionBlock)throwDestructiveBlock("junction/symlink creation",junctionBlock);let rmTargets=dcExtractRecursiveRmTargets(seg);if(rmTargets){let decision=dcEvaluateRecursiveDeleteTargets({targets:rmTargets,cwd,verifiedScope});if(!decision.allowed)throwDestructiveBlock("recursive delete",decision.reason)}if(/^(?:rmdir|rd)(?:\.exe)?\s+.*\/[sS]/i.test(seg)){let targets=dcExtractWindowsCmdTargets(seg);if(targets.length===0)throwDestructiveBlock("recursive directory delete","BLOCKED: Windows recursive directory delete (rmdir /s or rd /s) detected. Verify the target is not a junction/symlink.");let decision=dcEvaluateRecursiveDeleteTargets({targets,cwd,verifiedScope});if(!decision.allowed)throwDestructiveBlock("recursive directory delete",decision.reason)}if(/^del(?:\.exe)?\s+.*\/[sS]/i.test(seg)){let targets=dcExtractWindowsCmdTargets(seg);if(targets.length>0){let decision=dcEvaluateRecursiveDeleteTargets({targets,cwd,verifiedScope});if(!decision.allowed)throwDestructiveBlock("recursive file delete",decision.reason)}}if(/^(?:Remove-Item|ri|rm|rmdir|del|erase|rd)\b.*-[Rr]ecurse\b/i.test(seg)||/^(?:Remove-Item|ri|rm|rmdir|del|erase|rd)\b.*-[Rr]\b/i.test(seg)){let targets=dcExtractPowerShellTargets(seg);if(targets.length>0){let decision=dcEvaluateRecursiveDeleteTargets({targets,cwd,verifiedScope});if(!decision.allowed)throwDestructiveBlock("recursive remove",decision.reason)}else throwDestructiveBlock("recursive remove","BLOCKED: PowerShell Remove-Item with -Recurse detected — cannot verify target safety")}if(/Get-ChildItem\b.*\|\s*Remove-Item\b.*-[Rr]ecurse/i.test(seg)||/gci\b.*\|\s*ri\b.*-[Rr]ecurse/i.test(seg))throwDestructiveBlock("recursive remove",'BLOCKED: PowerShell pipeline "Get-ChildItem | Remove-Item -Recurse" detected — verify target safety and avoid recursive deletion through symlinks/junctions');let worktreeRemoveMatch=/^git\s+worktree\s+remove\s+(.+)$/i.exec(seg);if(worktreeRemoveMatch){let normalizedArgs=worktreeRemoveMatch[1].trim().split(/\s+/).filter(Boolean).map((a)=>a.replace(/^["']|["']$/g,"")),isForceToken=(a)=>{let lower=a.toLowerCase();return/^-f+$/.test(lower)||lower.length>2&&"--force".startsWith(lower)};if(normalizedArgs.some(isForceToken)){let pathArgs=normalizedArgs.filter((a)=>!a.startsWith("-")),target=pathArgs.length===1?pathArgs[0].trim():null;if(!(target!=null&&target.length>0&&(declaredScope!=null&&declaredScope.length>0&&isInDeclaredScope(target,declaredScope,cwd)||isPathUnderSwarmWorktreeBase(target,cwd,worktreeBaseDirOverrides??[]))))throwDestructiveBlock("git worktree remove",'BLOCKED: "git worktree remove --force" detected — can delete working tree contents')}}if(/^rsync\b.*--delete(?:-after|-before|-during|-delay)?\b/.test(seg)){let rsyncTarget=seg.split(/\s+/).slice(1).filter((a)=>!a.startsWith("-")&&!a.includes("@")).pop();if(!(rsyncTarget!=null&&declaredScope!=null&&declaredScope.length>0&&isInDeclaredScope(rsyncTarget,declaredScope,cwd)))throwDestructiveBlock("rsync delete",'BLOCKED: "rsync --delete" detected — can delete files in the destination. Verify source is not empty.')}if(/^\\?mv\s/i.test(seg)){let mvMatch=seg.match(/^\\?mv\s+(.+)$/i);if(mvMatch){let argsStr=mvMatch[1].replace(/["']/g,"");if(/\.swarm(?:[\x5c/\s]|$)/.test(argsStr))throwDestructiveBlock("swarm path move",'BLOCKED: "mv" targeting .swarm/ detected — move operations under .swarm/ are not allowed from shell commands')}}if(/^\\?(?:move|ren)(?:\.exe)?\s/i.test(seg)){let moveMatch=seg.match(/^\\?(?:move|ren)(?:\.exe)?\s+(.+)$/i);if(moveMatch){let argsStr=moveMatch[1].replace(/["']/g,"");if(/\.swarm(?:[\x5c/\s]|$)/i.test(argsStr))throwDestructiveBlock("move/rename",'BLOCKED: "move" or "ren" targeting .swarm/ detected — move/rename operations under .swarm/ are not allowed from shell commands')}}if(/^\\?(?:Move-Item|Rename-Item|move|mi|mv|ren|rni)\b.*\.swarm(?:[\x5c/\s]|$)/i.test(seg))throwDestructiveBlock("move/rename","BLOCKED: PowerShell Move-Item or Rename-Item targeting .swarm/ detected — move/rename operations under .swarm/ are not allowed from shell commands");if(/^\\?rm\b/i.test(seg)&&!/^\\?rm\s+(?:-[a-zA-Z]*[rR][a-zA-Z]*|--recursive)\b/i.test(seg)&&/\.swarm(?:[\x5c/\s]|$)/i.test(seg))throwDestructiveBlock("swarm path delete",'BLOCKED: "rm" targeting .swarm/ detected — deleting files under .swarm/ is not allowed from shell commands');if(/\bcp\b.*\.swarm(?:[\x5c/\s]|$)/i.test(seg)&&/\brm\b.*\.swarm(?:[\x5c/\s]|$)/i.test(seg))throwDestructiveBlock("copy-and-delete bypass",'BLOCKED: "cp" of .swarm/ file followed by "rm" of .swarm/ source detected — copy-and-delete bypass is not allowed');if(/^rsync\b.*--remove-source-files\b/i.test(seg)&&/\.swarm(?:[\x5c/\s]|$)/i.test(seg))throwDestructiveBlock("archive delete source",'BLOCKED: "rsync" with delete-source flag targeting .swarm/ detected — archive with source deletion under .swarm/ is not allowed');if(/^tar\b.*--remove-files\b/i.test(seg)&&/\.swarm(?:[\x5c/\s]|$)/i.test(seg))throwDestructiveBlock("archive delete source",'BLOCKED: "tar" with delete-source flag targeting .swarm/ detected — archive with source deletion under .swarm/ is not allowed');if(/^zip\b.*\s-m\b/i.test(seg)&&/\.swarm(?:[\x5c/\s]|$)/i.test(seg))throwDestructiveBlock("archive delete source",'BLOCKED: "zip" with delete-source flag targeting .swarm/ detected — archive with source deletion under .swarm/ is not allowed');if(/^7z\b.*\s-sdel\b/i.test(seg)&&/\.swarm(?:[\x5c/\s]|$)/i.test(seg))throwDestructiveBlock("archive delete source",'BLOCKED: "7z" with delete-source flag targeting .swarm/ detected — archive with source deletion under .swarm/ is not allowed');{let HUMAN_ONLY_SWARM_SUBCOMMANDS=HUMAN_ONLY_SWARM_COMMANDS,probe2=seg.replace(/^(?:[A-Za-z_][A-Za-z0-9_]*(?:="[^"]*"|='[^']*'|=\S+)\s+)+/,"").replace(/^eval(?:\s+--)?\s+["']?/,"").replace(/["']\s*$/,"").replace(/^\$\(\s*/,"").replace(/^\(\s*/,"").replace(/\s*\)$/,"").replace(/^`/,"").replace(/`$/,"").trim();for(let i=0;i<4;i++){let before=probe2;if(probe2=probe2.replace(/^env\s+(?:-i\b|--ignore-environment\b|-u\s+\S+|-[a-zA-Z]+\s+)*\s*/,"").replace(/^command\s+(?:-[pvV]\s+)*/,"").replace(/^(?:[A-Za-z_][A-Za-z0-9_]*(?:="[^"]*"|='[^']*'|=\S+)\s+)+/,"").trim(),probe2===before)break}let dequote=(input)=>input.replace(/["']/g,""),resolveVars=(input)=>input.replace(/\$\{?([A-Za-z_][A-Za-z0-9_]*)\}?/g,(full,name)=>swarmShellVars.has(name)?swarmShellVars.get(name):full),RUNNER_SHAPE=/^(?:\\|\/?(?:[\w.:%@=+-]+[/\\])*)?(?:bunx|npx|pnpx|npm|pnpm|yarn|bun|node|deno|tsx|ts-node|opencode-swarm)\b[^|;&]*?\brun\s+\$/i;for(let variant of[resolveVars(probe2),dequote(resolveVars(probe2))])if(RUNNER_SHAPE.test(variant))throwDestructiveBlock("human-only swarm command",'BLOCKED: "opencode-swarm run" invoked with an unresolvable shell variable or command substitution in the subcommand position. Re-run with the literal subcommand name so the human-only policy can be evaluated.');let probeVariants=[probe2,dequote(probe2),resolveVars(probe2),dequote(resolveVars(probe2))],matchCaptures=(re)=>{let captures=[];for(let variant of probeVariants){let m=variant.match(re);if(m?.[1])captures.push(m[1])}return captures},blockIfHumanOnly=(captures)=>{for(let captured of captures){let normalized=captured.trim().split(/\s+/).join(" "),firstToken=normalized.includes(" ")?normalized.split(" ")[0]:normalized,cmdName=HUMAN_ONLY_SWARM_SUBCOMMANDS.has(normalized)?normalized:firstToken;if(HUMAN_ONLY_SWARM_SUBCOMMANDS.has(normalized)||HUMAN_ONLY_SWARM_SUBCOMMANDS.has(firstToken))throwDestructiveBlock("human-only swarm command",`BLOCKED: "${cmdName}" is a human-only swarm command and may not be invoked from shell by an agent. Present the situation to the user and ask them to run \`/swarm ${cmdName}\` themselves.`)}};blockIfHumanOnly(matchCaptures(/^(?:\\|\/?(?:[\w.:%@=+-]+[/\\])*)?(?:bunx|npx|pnpx|npm(?:\s+(?:exec|x)(?:\s+--)?)?|pnpm(?:\s+(?:dlx|exec))?|yarn(?:\s+(?:dlx|exec))?|bun(?:\s+x)?|node|deno\s+run|tsx|ts-node)\b[^|;&]*?\bopencode-swarm\b[^|;&]*?\brun\s+([A-Za-z0-9_-]+(?:\s+(?!-)[A-Za-z0-9_-]+)?)/i)),blockIfHumanOnly(matchCaptures(/^(?:\\|\/?(?:[\w.:%@=+-]+[/\\])*)?opencode-swarm\b[^|;&]*?\brun\s+([A-Za-z0-9_-]+(?:\s+(?!-)[A-Za-z0-9_-]+)?)/i)),blockIfHumanOnly(matchCaptures(/\bcli[/\\]+index\.[mc]?(?:js|ts)\b[^|;&]*?\brun\s+([A-Za-z0-9_-]+(?:\s+(?!-)[A-Za-z0-9_-]+)?)/i))}{let normForPathCheck=seg.replace(/\\/g,"/").replace(/\/(?:\.\/+)+/g,"/").replace(/\/{2,}/g,"/");if(/\.swarm\/spec-staleness\.json\b/i.test(normForPathCheck)){let trimmed=seg.trim(),looksReadOnly=/^(?:cat|less|more|head|tail|file|stat|ls|dir|Get-Content|gc|Get-Item|gi|type)\b/i.test(trimmed),hasWriteRedirect=/>{1,2}\s*[^\s>]/.test(trimmed);if(!looksReadOnly||hasWriteRedirect)throwDestructiveBlock("system file tampering","BLOCKED: shell command targeting .swarm/spec-staleness.json detected. This file is system-managed and gates plan-mutating tools while spec drift is unresolved. Present the drift to the user and ask them to run /swarm acknowledge-spec-drift.")}}}}function detectShellType(command){if(/^(powershell|ps1|\.\s*\\|Remove-Item|Copy-Item|Move-Item|Start-Process|New-Object|Get-ChildItem|Set-Content|Add-Content|Out-File|Invoke-WebRequest|Invoke-RestMethod|IEX|iex)\b/i.test(command)||command.includes("$PSVersionTable")||command.includes("$env:")||/-EncodedCommand|-ExecutionPolicy|Enable-PSRemoting/i.test(command))return"powershell";if(/^(cmd|c:\/|set \w+=|\.\d+|del \/|rd \/|mkdir|chdir|echo |copy |move |ren |fc |diskpart)/i.test(command)||/%[^%\s]+%/.test(command)||/\b(set|echo|if|exist)\s+/i.test(command))return"cmd";if(/^(bash|sh|zsh|ksh|ash|dash|fish|ruby|python|perl|npm|yarn|node|cargo|go|rustc|mv|cp|rm|chmod|chown|mkdir|ln|tar|gzip|gunzip|ssh|scp|rsync|sudo|su -|export |source |\.\s+)/i.test(command)||command.includes("|")||command.includes("&&")||command.includes(">>")||/\$\{?\w+\}?/.test(command))return"bash";return"unix"}function checkShellWriteScope(sessionID,callID,tool3,args2,commandOverride,options){let enforce=options?.enforce!==!1;if(tool3!=="bash"&&tool3!=="shell")return;let session=swarmState.agentSessions.get(sessionID),toolArgs=args2,command=typeof commandOverride==="string"?commandOverride.trim():typeof toolArgs?.command==="string"?toolArgs.command.trim():"";if(!command)return;let normalizedTool=tool3,detectedShellType=detectShellType(command),shaped=isPowerShellShaped(command),shellType=detectedShellType;if(enforce&&(shellType==="powershell"||shellType==="cmd"?[shellType,"posix"]:["posix"]).some((candidate)=>detectInteractiveSession(command,candidate)))throw Error("BLOCKED: interactive/session tool detected — rejecting for safety");let windowsShell=resolveWindowsWriteAuthority(normalizedTool,command,detectedShellType,shaped,process.platform,normalizedTool==="shell"?getObservedHostShell():void 0),wrapperDeclaredHere=declaresWindowsWrapperLoose(command),windowsAuthoritative=wrapperDeclaredHere||normalizedTool!=="bash",detect=(c)=>{let posix15=detectPosixWrites(c);if(windowsShell===null)return posix15;return mergeWriteAnalyses(posix15,detectWindowsWrites(c,windowsShell),windowsAuthoritative,wrapperDeclaredHere)},suppressParseError=(c)=>enforce&&isPowerShellReadOnlyPipeline(c),primaryAnalysis=detect(command);if(enforce&&primaryAnalysis.parseError&&!suppressParseError(command))throw Error("BLOCKED: bash write detection failed to parse command — rejecting for safety");let commandSegments=dcSplitSegments(command),unwrappedSegments=commandSegments.map((s)=>dcUnwrapWrappers(s)),didUnwrap=commandSegments.some((s,i)=>unwrappedSegments[i]!==s),detectionCommand=didUnwrap?unwrappedSegments.join(`
|
|
1201
|
+
`):command,analysis=didUnwrap?detect(detectionCommand):primaryAnalysis;if(enforce&&analysis.parseError&&!suppressParseError(detectionCommand))throw Error("BLOCKED: bash write detection failed to parse command — rejecting for safety");if(!analysis.hasWrites||analysis.writes.length===0)return;let declaredScope=resolveDeclaredScope(sessionID,!enforce),shellWriteAgent=swarmState.activeAgent.get(sessionID);if(!shellWriteAgent){if(enforce)throw Error(`WRITE BLOCKED: No active agent registered for session "${sessionID}". Agent identity must be established (e.g. via a chat message or Task delegation) before shell writes can be authorized.`);return}let shellWriteRole=stripKnownSwarmPrefix(shellWriteAgent).toLowerCase(),isArch=shellWriteRole==="architect",isCoder=shellWriteRole==="coder",shellRoleCapability=AUTHORITY_ROLE_CAPABILITIES[shellWriteRole],isImmutableNonWriter=shellRoleCapability==="read-only"||shellRoleCapability==="dedicated-tool-only";if(enforce&&isCoder&&(!declaredScope||declaredScope.length===0))throw Error(`SCOPE_NOT_DECLARED: ${shellWriteAgent} cannot perform shell writes without an active Task-correlated scope binding. ACTION[architect]: call declare_scope with the exact workspace-relative paths and replace_existing=true, then dispatch a new Task call.`);let noScopeLenient=!isArch&&!isCoder&&!isImmutableNonWriter&&(!declaredScope||declaredScope.length===0),shellDirectory=sessionWorkspaceDirectory(sessionID),resolvedWrites=resolveWriteTargets(detectionCommand,analysis.writes,shellDirectory),enforceWriteAuthorization=(target,opts)=>{if(enforce&&noScopeLenient&&universalDenyPrefixes.length>0){for(let prefix of universalDenyPrefixes)if(matchesAuthorityDenyPrefix(target,prefix,shellDirectory))throw Error(`WRITE BLOCKED: Agent "${shellWriteAgent}" is not authorised to write "${target}" (via shell). Reason: Path is under universal deny prefix "${prefix}"`)}if(noScopeLenient)return"lenient";let authorityCheck=checkFileAuthorityWithRules(shellWriteAgent,target,shellDirectory,precomputedAuthorityRules,{declaredScope,authorityEnabled:authorityConfig?.enabled,universalDenyPrefixes,verifierConfigPaths:authorityConfig?.verifier_config_paths});if(enforce&&!authorityCheck.allowed){let evidenceEventID=authorityCheck.layer==="protected-path"?recordFullAutoSevereEvidenceEvent({sessionID,childSessionID:sessionID,category:"protected_state_mutation",paths:[target]}):void 0;throw Error(`WRITE BLOCKED: Agent "${shellWriteAgent}" is not authorised to write "${target}" (via shell). Reason: ${authorityCheck.reason}${evidenceEventID?` Evidence event: ${evidenceEventID}.`:""}`)}if(enforce&&declaredScope&&declaredScope.length>0&&!isInDeclaredScope(target,declaredScope,shellDirectory)&&!(opts?.exemptEmptyDirectoryRemoval===!0&&isPosixRmdirExecutor(normalizedTool,windowsShell,detectionCommand)&&isEmptyDirectoryRemovalWithinWorkspace(target,shellDirectory))){let safeTarget=sanitizeDiagnosticText(target,320),scopeSummary=declaredScope.slice(0,10).map((entry)=>sanitizeDiagnosticText(entry,160)).join(", "),omitted=Math.max(0,declaredScope.length-10);throw Error(`WRITE BLOCKED: SCOPE_VIOLATION: shell write target "${safeTarget}" is outside the active scope [${scopeSummary}${omitted>0?`, ... (+${omitted} more)`:""}]. ACTION[architect]: if the target is intended, call declare_scope for the exact workspace-relative path and redispatch; otherwise correct the command.`)}return"enforced"};for(let write of resolvedWrites){if(write.resolvedPath===null){if(write.original.category==="here_doc"&&write.original.path===null)continue;if(enforce&&write.original.category==="interpreter_eval"){if(write.original.capability===!0&&(isImmutableNonWriter||declaredScope!==null&&declaredScope!==void 0&&declaredScope.length>0)){enforceWriteAuthorization(write.evalDirectory??shellDirectory);continue}throw Error(`BLOCKED: ${write.original.operator} evaluates inline code whose write targets cannot be verified against the declared scope — rejecting for safety. Write files with the write/edit tools or a checked-in script, and invoke installed tools directly (e.g. \`pytest\`, \`ruff\`) instead of an inline \`python -c\` / \`node -e\` eval.`)}if(enforce)throw Error(`BLOCKED: bash/shell write to a dynamic path target${write.original.path?` "${write.original.path}"`:""} that cannot be statically resolved (shell variable or command substitution) — rejecting for safety.`);continue}if(enforceWriteAuthorization(write.resolvedPath,{exemptEmptyDirectoryRemoval:write.original.emptyDirectoryRemoval===!0})==="lenient")continue;if(isCoder&&session?.currentTaskId){let writeBinding=enforce?resolveActiveScopeBinding(sessionID):resolveActiveScopeBindingObserving(sessionID);if(writeBinding?.activation==="active"&&writeBinding.parentOwnerSessionId&&writeBinding.parentCallId){let relativeTarget=path102.relative(path102.resolve(shellDirectory),path102.resolve(shellDirectory,write.resolvedPath)).replace(/\\/g,"/");if(recordReviewerScopeGenerationFile({parentSessionID:writeBinding.parentOwnerSessionId,taskId:writeBinding.taskId,coderCallID:writeBinding.parentCallId,file:relativeTarget}))rememberReviewerScopeWrite?.({callID,parentSessionID:writeBinding.parentOwnerSessionId,taskId:writeBinding.taskId,coderCallID:writeBinding.parentCallId,file:relativeTarget})}}}if(isCoder&&session?.currentTaskId){let binding=enforce?resolveActiveScopeBinding(sessionID):resolveActiveScopeBindingObserving(sessionID);if(binding)rememberScopeLeaseCandidate?.({callID,sessionID,tool:tool3,directory:shellDirectory,binding,targets:resolvedWrites.flatMap((write)=>write.resolvedPath===null?[]:[path102.resolve(shellDirectory,write.resolvedPath)]),args:args2})}}function isSandboxWrapperInvocation(raw){let head=raw.replace(/^\s*(?:(?:exec|(?:\/(?:usr\/)?bin\/)?env)(?:\s+(?:-\S+|[A-Za-z_]\w*=\S*))*\s+)*/,"");return/^(?:\/(?:usr\/(?:local\/)?)?bin\/)?bwrap(?:\s|$)/.test(head)}async function applySandboxExecution(sessionID,callID,tool3,args2,agent,command,auditEnabled){if(tool3!=="bash"&&tool3!=="shell")return;let toolArgs=args2,rawCommand=typeof toolArgs?.command==="string"?toolArgs.command.trim():"";if(!rawCommand||!toolArgs)return;let executor=await getSandboxExecutor(),sandboxConfig=cfg.sandbox,originalCommandHash=hashArgs({command:rawCommand}),commandIdentity=`cmd=${originalCommandHash}`,assessment=await assessSandboxEnforcement2(sandboxConfig?{mode:sandboxConfig.mode,require_filesystem:sandboxConfig.require_filesystem,require_network:sandboxConfig.require_network,require_process:sandboxConfig.require_process,network_mode:sandboxConfig.network_mode,network_allowlist:sandboxConfig.network_allowlist,writable_roots:sandboxConfig.writable_roots}:void 0),capabilityIdentity=`cap=${assessment.capability.identity}`,recordOutcome2=(outcome)=>recordSandboxWrapOutcome({...outcome,sessionID,callID,originalCommandHash,originalCommand:rawCommand,assessmentCacheKey:assessment.cacheKey,executorMechanism:executor?.mechanism??"none",capabilityMechanism:assessment.capability.mechanism}),clearRecordedOutcome=()=>{clearSandboxWrapOutcome(sessionID,callID)};if(sandboxConfig?.mode==="required"){let assessmentSupported=assessment.supported!==!1,assessmentUnsupported=assessment.unsupported??[],missing=!executor||!executor.isAvailable()?["executor"]:assessment.missing;if(!executor||!executor.isAvailable()||!assessmentSupported||!assessment.satisfied){let missingOrUnsupported=assessmentSupported?missing.join(", "):assessmentUnsupported.join(", "),skipReason=missing[0]==="executor"?`required sandbox executor unavailable [${commandIdentity} ${capabilityIdentity}]`:!assessmentSupported?`required sandbox policy unsupported (${missingOrUnsupported}) [${commandIdentity} ${capabilityIdentity}]`:`required sandbox capability unsatisfied (${missingOrUnsupported}) [${commandIdentity} ${capabilityIdentity}]`;throw recordOutcome2({finalCommandHash:originalCommandHash,wrapped:!1,capabilityIdentity:assessment.capability.identity,reason:skipReason}),clearRecordedOutcome(),appendGuardrailDecision({type:"sandbox_skip",ts:new Date().toISOString(),sessionID,agent,tool:tool3,command,executorMechanism:executor?.mechanism??"none",skipReason},{directory:effectiveDirectory,enabled:auditEnabled}),Error(`[sandbox] BLOCKED: Required sandbox policy unsatisfied (${missingOrUnsupported}). [${commandIdentity} ${capabilityIdentity}] Command will not be executed unsandboxed.`)}}if(!executor||!executor.isAvailable()){if(recordOutcome2({finalCommandHash:originalCommandHash,wrapped:!1,capabilityIdentity:assessment.capability.identity,reason:"executor not available"}),!hasWarnedSandboxUnavailable)hasWarnedSandboxUnavailable=!0,criticalWarn("[guardrails] sandbox executor unavailable; shell commands will run unsandboxed. Run /swarm diagnose for details.");appendGuardrailDecision({type:"sandbox_skip",ts:new Date().toISOString(),sessionID,agent,tool:tool3,command,executorMechanism:executor?.mechanism??"none",skipReason:"executor not available"},{directory:effectiveDirectory,enabled:auditEnabled});return}let declaredPaths=resolveDeclaredScope(sessionID,!enforcePolicy);if(!declaredPaths||declaredPaths.length===0){if(recordOutcome2({finalCommandHash:originalCommandHash,wrapped:!1,capabilityIdentity:assessment.capability.identity,reason:"no declared scope"}),sandboxConfig?.mode==="required")throw clearRecordedOutcome(),Error("[sandbox] BLOCKED: Required sandbox policy needs a declared writable scope; command will not execute unsandboxed.");return}let resolved=resolveScopePaths(declaredPaths,sessionWorkspaceDirectory(sessionID)),configuredWritableRoots=resolveScopePaths(sandboxConfig?.writable_roots??[],sessionWorkspaceDirectory(sessionID));if(configuredWritableRoots.rejected.length>0){if(recordOutcome2({finalCommandHash:originalCommandHash,wrapped:!1,capabilityIdentity:assessment.capability.identity,reason:`configured writable_roots rejected (${configuredWritableRoots.rejected.map((item)=>item.path).join(", ")})`}),sandboxConfig?.mode==="required")throw clearRecordedOutcome(),Error("[sandbox] BLOCKED: Required sandbox policy contains writable_roots outside the session workspace; command will not execute unsandboxed.");return}if(resolved.paths.length===0){if(recordOutcome2({finalCommandHash:originalCommandHash,wrapped:!1,capabilityIdentity:assessment.capability.identity,reason:"resolved scope empty"}),sandboxConfig?.mode==="required")throw clearRecordedOutcome(),Error("[sandbox] BLOCKED: Required sandbox policy resolved no writable scope; command will not execute unsandboxed.");return}let writablePaths=[...new Set([...resolved.paths,...configuredWritableRoots.paths])];if(normalizeSandboxMechanism2(executor.mechanism)==="bubblewrap"&&isSandboxWrapperInvocation(rawCommand))throw recordOutcome2({finalCommandHash:originalCommandHash,wrapped:!1,capabilityIdentity:assessment.capability.identity,reason:"command already invokes the sandbox wrapper"}),clearRecordedOutcome(),Error(`[sandbox] BLOCKED: the command already invokes bwrap. Every bash call is sandboxed by the harness (${executor.mechanism}); a nested wrapper fails with "No permissions to create new namespace". Re-issue the plain command without the bwrap prefix.`);let workspaceRoot=sessionWorkspaceDirectory(sessionID),readonlyWorkspaceRoot=workspaceRoot;try{readonlyWorkspaceRoot=fs63.realpathSync(workspaceRoot)}catch{}try{let envOverrides=pluginOwnsExecutorEnv(executor.mechanism)?executor.getEnvOverrides():void 0,wrappedCommand=executor.wrapCommand(rawCommand,writablePaths,void 0,envOverrides,{network_mode:sandboxConfig?.network_mode??"off",network_allowlist:sandboxConfig?.network_allowlist??[],writable_roots:configuredWritableRoots.paths,readonly_roots:[readonlyWorkspaceRoot]});if(wrappedCommand.trim()===rawCommand)throw recordOutcome2({finalCommandHash:originalCommandHash,wrapped:!1,capabilityIdentity:assessment.capability.identity,reason:"sandbox wrapper returned the original command unchanged"}),clearRecordedOutcome(),Error(`[sandbox] BLOCKED: ${executor.mechanism} returned the original command unchanged. [${commandIdentity} ${capabilityIdentity}] Command will not be executed unsandboxed.`);if(normalizeSandboxMechanism2(executor.mechanism)!==normalizeSandboxMechanism2(assessment.capability.mechanism))throw recordOutcome2({finalCommandHash:originalCommandHash,wrapped:!1,capabilityIdentity:assessment.capability.identity,reason:"sandbox executor mechanism no longer matches the assessed capability"}),clearRecordedOutcome(),Error(`[sandbox] BLOCKED: sandbox executor mechanism drifted from the assessed capability (${executor.mechanism} != ${assessment.capability.mechanism}). [${commandIdentity} ${capabilityIdentity}]`);toolArgs.command=wrappedCommand,recordOutcome2({finalCommandHash:hashArgs({command:wrappedCommand}),wrapped:!0,capabilityIdentity:assessment.capability.identity,reason:"wrapped"}),markToolExecutionSandboxWrapped(sessionID,callID),appendGuardrailDecision({type:"sandbox_wrap",ts:new Date().toISOString(),sessionID,agent,tool:tool3,command:rawCommand,executorMechanism:executor.mechanism},{directory:effectiveDirectory,enabled:auditEnabled})}catch(err){recordOutcome2({finalCommandHash:originalCommandHash,wrapped:!1,capabilityIdentity:assessment.capability.identity,reason:err instanceof Error?err.message:String(err)}),clearRecordedOutcome(),forgetToolExecution(sessionID,callID);let message=`[sandbox] BLOCKED: Failed to wrap command with ${executor.mechanism}: ${err}. Command will not be executed unsandboxed.`,circuit=recordNonTransientFailure(sessionID,"sandbox_wrapper_failure",message,{tool:tool3,args:{command:rawCommand},armAttempt:!0});if(circuit?.hardStop)throw Error(nonTransientHardStopMessage(circuit));throw Error(message)}}async function checkGateLimits(params){let{sessionID,window:window2,agentConfig,elapsedMinutes,repetitionCount}=params;if(agentConfig.max_tool_calls>0&&window2.toolCalls>=agentConfig.max_tool_calls)throw window2.hardLimitHit=!0,telemetry.hardLimitHit(sessionID,window2.agentName,"tool_calls",window2.toolCalls),warn("Circuit breaker: tool call limit hit",{sessionID,agentName:window2.agentName,invocationId:window2.id,windowKey:`${window2.agentName}:${window2.id}`,resolvedMaxCalls:agentConfig.max_tool_calls,currentCalls:window2.toolCalls}),Error(`\uD83D\uDED1 LIMIT REACHED: Tool calls exhausted (${window2.toolCalls}/${agentConfig.max_tool_calls}). Finish the current operation and return your progress summary.`);if(agentConfig.max_duration_minutes>0&&elapsedMinutes>=agentConfig.max_duration_minutes)throw window2.hardLimitHit=!0,telemetry.hardLimitHit(sessionID,window2.agentName,"duration",elapsedMinutes),warn("Circuit breaker: duration limit hit",{sessionID,agentName:window2.agentName,invocationId:window2.id,windowKey:`${window2.agentName}:${window2.id}`,resolvedMaxMinutes:agentConfig.max_duration_minutes,elapsedMinutes:Math.floor(elapsedMinutes)}),Error(`\uD83D\uDED1 LIMIT REACHED: Duration exhausted (${Math.floor(elapsedMinutes)}/${agentConfig.max_duration_minutes} min). Finish the current operation and return your progress summary.`);if(repetitionCount>=agentConfig.max_repetitions)throw window2.hardLimitHit=!0,telemetry.hardLimitHit(sessionID,window2.agentName,"repetition",repetitionCount),Error(`\uD83D\uDED1 LIMIT REACHED: Repeated the same tool call ${repetitionCount} times. This suggests a loop. Return your progress summary.`);if(window2.consecutiveErrors>=agentConfig.max_consecutive_errors)throw window2.hardLimitHit=!0,telemetry.hardLimitHit(sessionID,window2.agentName,"consecutive_errors",window2.consecutiveErrors),Error(`\uD83D\uDED1 LIMIT REACHED: ${window2.consecutiveErrors} consecutive tool errors detected. Return your progress summary with details of what went wrong. Run /swarm reset-session to clear the circuit breaker without restarting your session.`);let idleMinutes=(Date.now()-window2.lastSuccessTimeMs)/60000;if(idleMinutes>=agentConfig.idle_timeout_minutes)throw window2.hardLimitHit=!0,telemetry.hardLimitHit(sessionID,window2.agentName,"idle_timeout",idleMinutes),warn("Circuit breaker: idle timeout hit",{sessionID,agentName:window2.agentName,invocationId:window2.id,windowKey:`${window2.agentName}:${window2.id}`,idleTimeoutMinutes:agentConfig.idle_timeout_minutes,idleMinutes:Math.floor(idleMinutes)}),Error(`\uD83D\uDED1 LIMIT REACHED: No successful tool call for ${Math.floor(idleMinutes)} minutes (idle timeout: ${agentConfig.idle_timeout_minutes} min). This suggests the agent may be stuck. Return your progress summary.`);if(!window2.warningIssued){let toolPct=agentConfig.max_tool_calls>0?window2.toolCalls/agentConfig.max_tool_calls:0,durationPct=agentConfig.max_duration_minutes>0?elapsedMinutes/agentConfig.max_duration_minutes:0,repPct=repetitionCount/agentConfig.max_repetitions,errorPct=window2.consecutiveErrors/agentConfig.max_consecutive_errors,reasons=[];if(agentConfig.max_tool_calls>0&&toolPct>=agentConfig.warning_threshold)reasons.push(`tool calls ${window2.toolCalls}/${agentConfig.max_tool_calls}`);if(durationPct>=agentConfig.warning_threshold)reasons.push(`duration ${Math.floor(elapsedMinutes)}/${agentConfig.max_duration_minutes} min`);if(repPct>=agentConfig.warning_threshold)reasons.push(`repetitions ${repetitionCount}/${agentConfig.max_repetitions}`);if(errorPct>=agentConfig.warning_threshold)reasons.push(`errors ${window2.consecutiveErrors}/${agentConfig.max_consecutive_errors}`);if(reasons.length>0)window2.warningIssued=!0,window2.warningReason=reasons.join(", ")}}function handleDelegatedWriteTracking(sessionID,tool3,args2){if(!swarmState.agentSessions.get(sessionID)?.delegationActive&&isArchitect(sessionID)){let coderDeleg=isAgentDelegation(tool3,args2);if(coderDeleg.isDelegation&&coderDeleg.targetAgent==="coder"){let coderSession=swarmState.agentSessions.get(sessionID);if(coderSession){let taskId=coderSession.currentTaskId??coderSession.lastCoderDelegationTaskId??`${sessionID}:unknown`;if(coderSession.currentTaskId=taskId,resetModifiedFilesForTask(coderSession,taskId),!coderSession.revisionLimitHit)coderSession.coderRevisions=0}}}}function isAgentDelegation(toolName,args2){if(!isTaskToolId(toolName))return{isDelegation:!1,targetAgent:null};let argsObj=args2;if(!argsObj)return{isDelegation:!1,targetAgent:null};let subagentType=argsObj.subagent_type;if(typeof subagentType==="string")return{isDelegation:!0,targetAgent:stripKnownSwarmPrefix(subagentType)};return{isDelegation:!1,targetAgent:null}}function handleLoopDetection(sessionID,tool3,args2){if(!isTaskToolId(tool3))return;let loopArgs=args2,loopResult=detectLoop(sessionID,tool3,loopArgs);if(loopResult.count>=5)throw Error(`CIRCUIT BREAKER: Delegation loop detected (${loopResult.count} identical patterns). Further identical delegations are blocked. Diagnose or rescope the task before retrying.`);else if(loopResult.count>=3&&loopResult.count<5){let agentName=typeof loopArgs?.subagent_type==="string"?loopArgs.subagent_type:"agent",loopSession=swarmState.agentSessions.get(sessionID);if(loopSession){let loopPattern=loopResult.pattern,modifiedFiles=loopSession.currentTaskId?getModifiedFilesForTask(loopSession,loopSession.currentTaskId):[],accomplishmentSummary=modifiedFiles.length>0?`Modified ${modifiedFiles.length} file(s): ${modifiedFiles.slice(0,3).join(", ")}${modifiedFiles.length>3?"...":""}`:"No files modified yet",alternativeSuggestions={coder:"Try a different task spec, simplify the constraint, or escalate to user",reviewer:"Try a different review dimension or escalate to user",test_engineer:"Run a specific test file with targeted scope",explorer:"Narrow the search scope or check a specific file directly"},cleanAgent=stripKnownSwarmPrefix(agentName).toLowerCase(),suggestion=alternativeSuggestions[cleanAgent]??"Try a different agent, different instructions, or escalate to the user";loopSession.loopWarningPending={agent:agentName,message:[`LOOP DETECTED: Pattern "${loopPattern}" repeated 3 times.`,`Agent: ${agentName}`,`Accomplished: ${accomplishmentSummary}`,`Suggested action: ${suggestion}`,"If still stuck after trying alternatives, escalate to the user."].join(`
|
|
1202
1202
|
`),timestamp:Date.now()}}}}function handleTestSuiteBlocking(tool3,args2){if(tool3!=="bash"&&tool3!=="shell")return;let bashArgs=args2,cmd=(typeof bashArgs?.command==="string"?bashArgs.command:"").trim();if(/^(bun\s+test|npm\s+test|npx\s+vitest|bunx\s+vitest)\b/.test(cmd)){let tokens=cmd.split(/\s+/),runnerTokenCount=tokens[0]==="npx"||tokens[0]==="bunx"?3:2;if(!tokens.slice(runnerTokenCount).some((token)=>token.length>0&&!token.startsWith("-")&&(token.includes("/")||token.includes("\\")||token.endsWith(".ts")||token.endsWith(".js")||token.endsWith(".tsx")||token.endsWith(".jsx")||token.endsWith(".mts")||token.endsWith(".mjs"))))throw Error("BLOCKED: Full test suite execution is not allowed in-session. Run a specific test file instead: bun test path/to/file.test.ts")}}function extractAllPatchPayloads(args2){let toolArgs=args2;if(!toolArgs)return[];let out=[];for(let key2 of PATCH_PAYLOAD_KEYS){let v=toolArgs[key2];if(typeof v==="string"&&v.length>0)out.push(v)}let cmd=toolArgs.cmd;if(Array.isArray(cmd)){for(let entry of cmd)if(typeof entry==="string"&&entry.length>0)out.push(entry)}return out}function getHumanOnlyAlternation(){return[...HUMAN_ONLY_SWARM_COMMANDS].map((c)=>c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")).sort((a,b)=>b.length-a.length).join("|")}function patchPayloadHasHumanOnlyInvocation(args2){let payloads=extractAllPatchPayloads(args2);if(payloads.length===0)return!1;let alternation=getHumanOnlyAlternation(),re=new RegExp(`\\bopencode-swarm\\b[\\s\\S]*?\\brun\\s+(${alternation})\\b`,"i");return payloads.some((p)=>re.test(p))}function extractPatchTargetPaths(tool3,args2){if(tool3!=="apply_patch"&&tool3!=="swarm_apply_patch"&&tool3!=="patch")return[];let toolArgs=args2,paths=new Set;if(Array.isArray(toolArgs?.files)){for(let f of toolArgs.files)if(typeof f==="string"&&f.length>0&&f!=="/dev/null")paths.add(f)}let patchText;for(let key2 of["input","patch","diff"]){let v=toolArgs?.[key2];if(typeof v==="string"){patchText=v;break}}if(patchText===void 0)for(let key2 of PATCH_PAYLOAD_KEYS){if(key2==="patch"||key2==="input"||key2==="diff")continue;let v=toolArgs?.[key2];if(typeof v==="string"){patchText=v;break}}if(patchText===void 0&&Array.isArray(toolArgs?.cmd))patchText=toolArgs.cmd[1];if(typeof patchText!=="string")return Array.from(paths);if(patchText.length>1e6)throw Error("WRITE BLOCKED: Patch payload exceeds 1 MB — authority cannot be verified for all modified paths. Split into smaller patches.");let normalizedPatchText=normalizePatchIndentation(patchText),patchPathPattern=/\*\*\*\s+(?:Update|Add|Delete)\s+File:\s*(.+)/gi,diffPathPattern=/\+\+\+\s+b\/(.+)/gm,gitDiffPathPattern=/^diff --git a\/(.+?) b\/(.+?)$/gm,minusPathPattern=/^---\s+a\/(.+)$/gm,traditionalMinusPattern=/^---\s+([^\s].+?)(?:\t.*)?$/gm,traditionalPlusPattern=/^\+\+\+\s+([^\s].+?)(?:\t.*)?$/gm;for(let match of normalizedPatchText.matchAll(patchPathPattern))paths.add(match[1].trim());for(let match of normalizedPatchText.matchAll(diffPathPattern)){let p=match[1].trim();if(p!=="/dev/null")paths.add(p)}for(let match of normalizedPatchText.matchAll(gitDiffPathPattern)){let aPath=match[1].trim(),bPath=match[2].trim();if(aPath!=="/dev/null")paths.add(aPath);if(bPath!=="/dev/null")paths.add(bPath)}for(let match of normalizedPatchText.matchAll(minusPathPattern)){let p=match[1].trim();if(p!=="/dev/null")paths.add(p)}for(let match of normalizedPatchText.matchAll(traditionalMinusPattern)){let p=match[1].trim();if(p!=="/dev/null"&&!p.startsWith("a/")&&!p.startsWith("b/"))paths.add(p)}for(let match of normalizedPatchText.matchAll(traditionalPlusPattern)){let p=match[1].trim();if(p!=="/dev/null"&&!p.startsWith("a/")&&!p.startsWith("b/"))paths.add(p)}return Array.from(paths)}function handlePlanAndScopeProtection(sessionID,tool3,args2){let toolArgs=args2,targetPath=toolArgs?.filePath??toolArgs?.path??toolArgs?.file??toolArgs?.target;if(tool3==="apply_patch"||tool3==="swarm_apply_patch"||tool3==="patch"){if(patchPayloadHasHumanOnlyInvocation(args2))throw Error("BLOCKED: apply_patch/swarm_apply_patch would introduce a script invoking a human-only swarm CLI subcommand. Present the situation to the user and ask them to run the command themselves.")}if(typeof targetPath==="string"&&targetPath.length>0){let resolvedTarget=path102.resolve(effectiveDirectory,targetPath).toLowerCase(),planMdPath=path102.resolve(effectiveDirectory,".swarm","plan.md").toLowerCase(),planJsonPath=path102.resolve(effectiveDirectory,".swarm","plan.json").toLowerCase();if(resolvedTarget===planMdPath||resolvedTarget===planJsonPath)throw Error("PLAN STATE VIOLATION: Direct writes to .swarm/plan.md and .swarm/plan.json are blocked. plan.md is auto-regenerated from plan.json by PlanSyncWorker. Use save_plan for ALL structural plan changes (adding/removing tasks, updating descriptions, dependencies, or phase names). Use update_task_status() for task status only. Use phase_complete() for phase transitions only.");let specStalenessPath=path102.resolve(effectiveDirectory,".swarm","spec-staleness.json").toLowerCase();if(resolvedTarget===specStalenessPath)throw Error("SPEC_DRIFT_VIOLATION: Direct writes to .swarm/spec-staleness.json are blocked. This file is system-managed and gates plan-mutating tools while spec drift is unresolved. Present the drift to the user and ask them to run /swarm acknowledge-spec-drift.");let content=toolArgs?.content??toolArgs?.text??toolArgs?.new_string??toolArgs?.newText;if(typeof content==="string"&&new RegExp(`\\bopencode-swarm\\b[\\s\\S]*?\\brun\\s+(${getHumanOnlyAlternation()})\\b`,"i").test(content))throw Error("BLOCKED: write/edit tool would create a script invoking a human-only swarm CLI subcommand. Present the situation to the user and ask them to run the command themselves.")}if(!targetPath&&(tool3==="apply_patch"||tool3==="swarm_apply_patch"||tool3==="patch"))for(let p of extractPatchTargetPaths(tool3,args2)){let resolvedP=path102.resolve(effectiveDirectory,p),planMdPath=path102.resolve(effectiveDirectory,".swarm","plan.md").toLowerCase(),planJsonPath=path102.resolve(effectiveDirectory,".swarm","plan.json").toLowerCase(),specStalenessPath=path102.resolve(effectiveDirectory,".swarm","spec-staleness.json").toLowerCase();if(resolvedP.toLowerCase()===planMdPath||resolvedP.toLowerCase()===planJsonPath)throw Error("PLAN STATE VIOLATION: Direct writes to .swarm/plan.md and .swarm/plan.json are blocked. plan.md is auto-regenerated from plan.json by PlanSyncWorker. Use save_plan for ALL structural plan changes (adding/removing tasks, updating descriptions, dependencies, or phase names). Use update_task_status() for task status only. Use phase_complete() for phase transitions only.");if(resolvedP.toLowerCase()===specStalenessPath)throw Error("SPEC_DRIFT_VIOLATION: Direct writes to .swarm/spec-staleness.json are blocked. This file is system-managed and gates plan-mutating tools while spec drift is unresolved. Present the drift to the user and ask them to run /swarm acknowledge-spec-drift.");if(isOutsideSwarmDir(p,effectiveDirectory)&&(isSourceCodePath(p)||hasTraversalSegments(p))){let session=swarmState.agentSessions.get(sessionID);if(session)session.architectWriteCount++,warn("Architect direct code edit detected via patch tool",{tool:tool3,sessionID,targetPath:p,writeCount:session.architectWriteCount});break}}if(typeof targetPath==="string"&&targetPath.length>0&&isOutsideSwarmDir(targetPath,effectiveDirectory)&&isSourceCodePath(path102.relative(effectiveDirectory,path102.resolve(effectiveDirectory,targetPath)))){let session=swarmState.agentSessions.get(sessionID);if(session){if(session.architectWriteCount++,warn("Architect direct code edit detected",{tool:tool3,sessionID,targetPath,writeCount:session.architectWriteCount}),session.lastGateFailure&&Date.now()-session.lastGateFailure.timestamp<120000){let failedGate=session.lastGateFailure.tool,failedTaskId=session.lastGateFailure.taskId;warn("Self-fix after gate failure detected",{failedGate,failedTaskId,currentTool:tool3,sessionID}),session.selfFixAttempted=!0}}}}function resolveSessionAndWindow(sessionID){let rawActiveAgent=swarmState.activeAgent.get(sessionID),strippedAgent=rawActiveAgent?stripKnownSwarmPrefix(rawActiveAgent):void 0;if(strippedAgent===ORCHESTRATOR_NAME)return null;if(strippedAgent&&isNativeOpencodeAgent(strippedAgent))return null;let existingSession=swarmState.agentSessions.get(sessionID);if(existingSession){let sessionAgent=stripKnownSwarmPrefix(existingSession.agentName);if(sessionAgent===ORCHESTRATOR_NAME)return null;if(isNativeOpencodeAgent(sessionAgent))return null}let agentName=swarmState.activeAgent.get(sessionID)??ORCHESTRATOR_NAME,session=ensureAgentSession(sessionID,agentName),resolvedName=stripKnownSwarmPrefix(session.agentName);if(resolvedName===ORCHESTRATOR_NAME)return null;if(isNativeOpencodeAgent(resolvedName))return null;let agentConfig=resolveGuardrailsConfig(cfg,session.agentName);if(agentConfig.max_duration_minutes===0&&agentConfig.max_tool_calls===0)return null;if(!getActiveWindow(sessionID)){let fallbackAgent=swarmState.activeAgent.get(sessionID)??session.agentName;if(stripKnownSwarmPrefix(fallbackAgent)!==ORCHESTRATOR_NAME)beginInvocation(sessionID,fallbackAgent)}let window2=getActiveWindow(sessionID);if(!window2)return null;return{agentConfig,window:window2}}function isNativeOpencodeAgent(agentName){return OPENCODE_NATIVE_AGENTS.has(agentName.toLowerCase())}function trackToolCall(window2,tool3,args2){if(window2.hardLimitHit)throw Error("\uD83D\uDED1 CIRCUIT BREAKER: Agent blocked. Hard limit was previously triggered. Stop making tool calls and return your progress summary.");window2.toolCalls++;let hash4=hashArgs(args2);if(window2.recentToolCalls.push({tool:tool3,argsHash:hash4,timestamp:Date.now()}),window2.recentToolCalls.length>20)window2.recentToolCalls.shift();let repetitionCount=0;if(window2.recentToolCalls.length>0){let lastEntry=window2.recentToolCalls[window2.recentToolCalls.length-1];for(let i=window2.recentToolCalls.length-1;i>=0;i--){let entry=window2.recentToolCalls[i];if(entry.tool===lastEntry.tool&&entry.argsHash===lastEntry.argsHash)repetitionCount++;else break}}let elapsedMinutes=(Date.now()-window2.startedAtMs)/60000;return{repetitionCount,elapsedMinutes}}return async(input,output)=>{if(enforcePolicy)assertNonTransientCircuitAllowsTool(input.sessionID,{tool:input.tool,args:output.args});let resolvedSessionWindow=swarmState.agentSessions.has(input.sessionID)||swarmState.activeAgent.has(input.sessionID)?resolveSessionAndWindow(input.sessionID):null,session=swarmState.agentSessions.get(input.sessionID),rawAgentForScope=swarmState.activeAgent.get(input.sessionID),isCoder=rawAgentForScope!==void 0&&stripKnownSwarmPrefix(rawAgentForScope).toLowerCase()==="coder";if(consecutiveNoToolTurns.set(input.sessionID,0),observeExecutionStallToolCall({sessionID:input.sessionID,tool:input.tool,args:output.args,callID:input.callID,options:executionStallOptions}),handleDelegatedWriteTracking(input.sessionID,input.tool,output.args),enforcePolicy)handleLoopDetection(input.sessionID,input.tool,output.args);if(enforcePolicy&&isSwarmOwnedSession(input.sessionID))handleTestSuiteBlocking(input.tool,output.args);let rawShellCommand=(()=>{let bashArgs=output.args;return typeof bashArgs?.command==="string"?bashArgs.command:""})(),normalizedAuditTool=normalizeToolName(input.tool).toLowerCase();if(normalizedAuditTool==="bash"||normalizedAuditTool==="shell")appendGuardrailDecision({type:"shell",ts:new Date().toISOString(),sessionID:input.sessionID,agent:(()=>{let rawAgent=swarmState.activeAgent.get(input.sessionID);return rawAgent?stripKnownSwarmPrefix(rawAgent):"unknown"})(),tool:input.tool,command:(()=>{let bashArgs=output.args,rawCmd=typeof bashArgs?.command==="string"?bashArgs.command:"";return redactShellCommand(rawCmd)})()},{directory:effectiveDirectory,enabled:shellAuditEnabled});if(enforcePolicy)handleInterpreterGating(input.sessionID,input.tool);try{if(enforcePolicy)checkDestructiveCommand(input.sessionID,input.tool,output.args)}catch(err){let destructiveCategory=err instanceof DestructiveCommandBlockedError?err.destructiveCategory:"destructive shell command";throw appendGuardrailDecision({type:"destructive_block",ts:new Date().toISOString(),sessionID:input.sessionID,agent:(()=>{let rawAgent=swarmState.activeAgent.get(input.sessionID);return rawAgent?stripKnownSwarmPrefix(rawAgent):"unknown"})(),tool:input.tool,command:(()=>{let bashArgs=output.args;return typeof bashArgs?.command==="string"?bashArgs.command:""})(),destructiveCategory},{directory:effectiveDirectory,enabled:shellAuditEnabled}),err}try{checkShellWriteScope(input.sessionID,input.callID,input.tool,output.args,rawShellCommand,{enforce:enforcePolicy})}catch(err){let toolArgs=output.args,declaredScope=resolveDeclaredScope(input.sessionID,!0),declaredScopeText=declaredScope!=null&&declaredScope.length>0?declaredScope.join(", "):"",resolvedScopeText=declaredScope!=null&&declaredScope.length>0?resolveScopePaths(declaredScope,sessionWorkspaceDirectory(input.sessionID)).paths.join(", "):"",pathMatch=/[^\s]+/.exec(err instanceof Error?err.message:String(err)),targetPath=(()=>{let p=toolArgs?.filePath??toolArgs?.path??toolArgs?.file??toolArgs?.target;if(typeof p==="string"&&p.length>0)return p;let rawMessage=err instanceof Error?err.message:String(err),extracted=/(?:write|target|file|path|scope|prefix)[^:]*:\s*(?:"([^"]+)"|'([^']+)'|(\S+))/i.exec(rawMessage)??/(?:write|target|file|path)\s+(?:"([^"]+)"|'([^']+)'|(\S+))/i.exec(rawMessage),candidate=extracted!=null?extracted[1]??extracted[2]??extracted[3]??extracted[4]??extracted[5]??extracted[6]:null;if(candidate&&candidate.length>0&&candidate.length<200)return candidate;if(pathMatch)return pathMatch[0];return"<shell write>"})(),agentName=(()=>{let rawAgent=swarmState.activeAgent.get(input.sessionID);return rawAgent?stripKnownSwarmPrefix(rawAgent):"unknown"})();throw appendGuardrailDecision({type:"scope_violation",ts:new Date().toISOString(),sessionID:input.sessionID,agent:agentName,tool:input.tool,path:targetPath,declaredScope:declaredScopeText,resolvedScope:resolvedScopeText,action:"bash"},{directory:effectiveDirectory,enabled:shellAuditEnabled}),err}let agentNameForSandbox=(()=>{let rawAgent=swarmState.activeAgent.get(input.sessionID);return rawAgent?stripKnownSwarmPrefix(rawAgent):"unknown"})();if(rememberToolExecution(input.sessionID,input.callID,input.tool,rawShellCommand),enforcePolicy)await applySandboxExecution(input.sessionID,input.callID,input.tool,output.args,agentNameForSandbox,rawShellCommand,shellAuditEnabled);if(enforcePolicy)enforceSpecDriftGate(effectiveDirectory,input.tool);if(enforcePolicy&&isArchitect(input.sessionID)&&isWriteTool(input.tool))handlePlanAndScopeProtection(input.sessionID,input.tool,output.args);if(input.tool==="apply_patch"||input.tool==="swarm_apply_patch"||input.tool==="patch"){let patchArgs=output.args,structuralPatch=typeof patchArgs?.input==="string"?patchArgs.input:typeof patchArgs?.patch==="string"?patchArgs.patch:typeof patchArgs?.diff==="string"?patchArgs.diff:void 0;if(structuralPatch===void 0)for(let key2 of PATCH_PAYLOAD_KEYS){let value=patchArgs?.[key2];if(typeof value==="string"){structuralPatch=value;break}}if(structuralPatch===void 0&&Array.isArray(patchArgs?.cmd)&&typeof patchArgs.cmd[1]==="string")structuralPatch=patchArgs.cmd[1];if(structuralPatch===void 0&&typeof patchArgs?.cmd==="string")structuralPatch=patchArgs.cmd;if((structuralPatch??"").length>1e6)throw Error("WRITE BLOCKED: Patch payload exceeds 1 MB — authority cannot be verified for all modified paths. Split into smaller patches.")}let writeDirectory=sessionWorkspaceDirectory(input.sessionID),resolvedFileTargets=null;if(isWriteTool(input.tool)){let resolution=resolveWriteTargets2(normalizeToolName(input.tool),output.args,{directory:writeDirectory});if(resolution.status==="unverifiable"){if(enforcePolicy)throw Error(`WRITE TARGET UNVERIFIABLE: ${resolution.reason}`)}else resolvedFileTargets=resolution.paths;let writeBinding=session?.currentTaskId&&isCoder?enforcePolicy?resolveActiveScopeBinding(input.sessionID):resolveActiveScopeBindingObserving(input.sessionID):null;if(writeBinding)rememberScopeLeaseCandidate?.({callID:input.callID,sessionID:input.sessionID,tool:input.tool,directory:writeDirectory,binding:writeBinding,targets:(resolvedFileTargets??[]).map((target)=>path102.resolve(writeDirectory,target)),args:output.args})}if(isWriteTool(input.tool))for(let targetPath of resolvedFileTargets??[]){let agentName=swarmState.activeAgent.get(input.sessionID);if(!agentName){if(!enforcePolicy)continue;throw Error(`WRITE BLOCKED: No active agent registered for session "${input.sessionID}". Call startAgentSession before issuing write tool calls.`)}let lstatBlock=checkWriteTargetForSymlink(targetPath,writeDirectory);if(lstatBlock){if(appendGuardrailDecision({type:"file_write",ts:new Date().toISOString(),sessionID:input.sessionID,agent:agentName,tool:input.tool,path:targetPath,reason:lstatBlock,resolvedScope:(()=>{let scope=resolveDeclaredScope(input.sessionID,!enforcePolicy);return scope!=null&&scope.length>0?scope.join(", "):""})()},{directory:effectiveDirectory,enabled:shellAuditEnabled}),enforcePolicy)throw Error(lstatBlock)}let writeBinding=session?.currentTaskId&&isCoder?enforcePolicy?resolveActiveScopeBinding(input.sessionID):resolveActiveScopeBindingObserving(input.sessionID):null,writeDeclaredScope=writeBinding?.files??null,authorityCheck=checkFileAuthorityWithRules(agentName,targetPath,writeDirectory,precomputedAuthorityRules,{declaredScope:writeDeclaredScope,authorityEnabled:authorityConfig?.enabled,universalDenyPrefixes,verifierConfigPaths:authorityConfig?.verifier_config_paths});if(!authorityCheck.allowed){let evidenceEventID=authorityCheck.layer==="protected-path"?recordFullAutoSevereEvidenceEvent({sessionID:input.sessionID,childSessionID:input.sessionID,category:"protected_state_mutation",paths:[targetPath]}):void 0;if(appendGuardrailDecision({type:"file_write",ts:new Date().toISOString(),sessionID:input.sessionID,agent:agentName,tool:input.tool,path:targetPath,reason:authorityCheck.reason,resolvedScope:(()=>{let scope=writeDeclaredScope;return scope!=null&&scope.length>0?scope.join(", "):""})()},{directory:effectiveDirectory,enabled:shellAuditEnabled}),!enforcePolicy)continue;throw Error(`WRITE BLOCKED: Agent "${agentName}" is not authorised to write "${targetPath}". Reason: ${authorityCheck.reason}${evidenceEventID?` Evidence event: ${evidenceEventID}.`:""}`)}let trackingSession=swarmState.agentSessions.get(input.sessionID),auditContext=trackingSession?.delegationActive?"delegated":"direct",auditOperation=["apply_patch","swarm_apply_patch","patch"].includes(normalizeToolName(input.tool))?"patch":"write";if(isConfigFilePath(targetPath,writeDirectory,authorityConfig?.verifier_config_paths)){let normalizedPath=path102.relative(path102.resolve(writeDirectory),path102.resolve(writeDirectory,targetPath)).replace(/\\/g,"/"),logEntry={agent:agentName,path:normalizedPath,allowed:authorityCheck.allowed,type:`${auditContext}_${auditOperation}`};if(!authorityCheck.allowed&&"reason"in authorityCheck)logEntry.reason=authorityCheck.reason;warn("Config file write attempt",logEntry)}if(trackingSession?.delegationActive){let taskId=trackingSession.currentTaskId??trackingSession.lastCoderDelegationTaskId??`${input.sessionID}:unknown`;trackingSession.currentTaskId=taskId,recordModifiedFileForTask(trackingSession,taskId,targetPath,writeDirectory)}if(writeBinding?.activation==="active"&&writeBinding.parentOwnerSessionId&&writeBinding.parentCallId){let relativeTarget=path102.relative(path102.resolve(writeDirectory),path102.resolve(writeDirectory,targetPath)).replace(/\\/g,"/");if(recordReviewerScopeGenerationFile({parentSessionID:writeBinding.parentOwnerSessionId,taskId:writeBinding.taskId,coderCallID:writeBinding.parentCallId,file:relativeTarget}))rememberReviewerScopeWrite?.({callID:input.callID,parentSessionID:writeBinding.parentOwnerSessionId,taskId:writeBinding.taskId,coderCallID:writeBinding.parentCallId,file:relativeTarget})}}let resolved=resolvedSessionWindow;if(resolved){let{agentConfig,window:window2}=resolved,{repetitionCount,elapsedMinutes}=trackToolCall(window2,input.tool,output.args);if(enforcePolicy)await checkGateLimits({sessionID:input.sessionID,window:window2,agentConfig,elapsedMinutes,repetitionCount})}if(enforcePolicy){let prmSession=swarmState.agentSessions.get(input.sessionID);if(prmSession?.prmHardStopPending){prmSession.prmHardStopPending=!1;let patternType=prmSession.prmLastPatternDetected?.pattern??"unknown";throw telemetry.prmHardStopDelivered(input.sessionID,patternType,prmSession.prmEscalationLevel,prmSession.prmPatternCounts?.get(patternType)??0),Error("\uD83D\uDED1 PRM HARD STOP: Pattern escalation maximum reached. Stop tool calls and return progress summary.")}}if(enforceInternalsGuard({sessionID:input.sessionID,tool:input.tool,args:output.args,directory:effectiveDirectory,options:internalsGuardOptions}),enforceExecutionStallDenial({sessionID:input.sessionID,tool:input.tool,options:executionStallOptions}),!resolved)return;setStoredInputArgs(input.callID,output.args)}}var hasWarnedSandboxUnavailable=!1,DestructiveCommandBlockedError,RMDIR_EXEMPTION_CONTROL_STATE;var init_tool_before=__esm(()=>{init_tool_policy();init_constants();init_schema();init_severe_result();init_executor();init_scope_resolver();init_skip_state();init_path_identity();init_scope_persistence();init_scope_resolution_diagnostic();init_command_classifier();init_protected_path_policy();init_state();init_telemetry();init_utils();init_core3();init_loop_detector();init_normalize_tool_name();init_shell_executor_context();init_shell_write_detect();init_write_target_resolver();init_audit_log();init_destructive_command();init_execution_stall();init_file_authority();init_guardrails();init_internals_guard();init_nontransient_circuit();init_stored_input_args();init_helpers();DestructiveCommandBlockedError=class DestructiveCommandBlockedError extends Error{destructiveCategory;constructor(message,destructiveCategory){super(message);this.destructiveCategory=destructiveCategory;this.name="DestructiveCommandBlockedError"}};RMDIR_EXEMPTION_CONTROL_STATE=[".git",".swarm"]});import*as fsSync11 from"node:fs";import*as path103 from"node:path";function emitDurableAttributionAdvisory(sessionID,key2,message){let now=Date.now(),prior=durableAttributionAdvisoryBySession.get(sessionID);if(prior&&prior.key===key2&&now-prior.at<DURABLE_ATTRIBUTION_ADVISORY_COOLDOWN_MS)return;if(!prior&&durableAttributionAdvisoryBySession.size>=MAX_DURABLE_ATTRIBUTION_ADVISORY_SESSIONS){let oldest=durableAttributionAdvisoryBySession.keys().next().value;if(oldest!==void 0)durableAttributionAdvisoryBySession.delete(oldest)}durableAttributionAdvisoryBySession.set(sessionID,{key:key2,at:now});let session=swarmState.agentSessions.get(sessionID);if(session)pushAdvisory(session,message);else criticalWarn(`[guardrails] ${message}`)}function stageAWriteErrorCode(error93){let message=error93 instanceof Error?error93.message:String(error93),match=/^[A-Z][A-Z0-9_]+/.exec(message);return match?match[0]:null}function extractGateCallFiles(args2){if(!args2||typeof args2!=="object")return null;let raw=args2.files;if(Array.isArray(raw)){let files=raw.filter((entry)=>typeof entry==="string"&&entry!=="");return files.length>0?files:null}let changed2=args2.changed_files;if(Array.isArray(changed2)){let files=changed2.map((entry)=>typeof entry==="string"?entry:entry&&typeof entry==="object"&&typeof entry.path==="string"?entry.path:null).filter((entry)=>entry!==null&&entry!=="");return files.length>0?files:null}return null}async function resolveDurableGateTaskId(directory,callerFiles){try{let{states,truncated}=await listCoderSettlementWalStates(directory),eligible=[],inFlightAtCoderDelegated=new Set;for(let state2 of states){if(!isStrictTaskId(state2.taskId))continue;if(state2.state==="DISPATCHED"||state2.state==="PREPARED"){if(getTaskWorkflowSnapshot(await readTaskEvidence(directory,state2.taskId)).state==="coder_delegated")inFlightAtCoderDelegated.add(state2.taskId);continue}if(state2.state!=="COMMITTED")continue;if(state2.accepted!==!0)continue;if(getTaskWorkflowSnapshot(await readTaskEvidence(directory,state2.taskId)).state==="coder_delegated")eligible.push(state2)}let ambiguousIds=new Set([...eligible.map((s)=>s.taskId),...inFlightAtCoderDelegated]);if(ambiguousIds.size>1)return{ambiguous:[...ambiguousIds].sort()};if(eligible.length===1){let candidate=eligible[0];if(truncated)return{unbound:candidate.taskId,reason:"truncated"};let declared=candidate.declaredFiles,normalizedCallerFiles=callerFiles!==null?normalizeScopeFiles(callerFiles):null;if(normalizedCallerFiles!==null&&normalizedCallerFiles.length>0&&declared!==null&&declared!==void 0&&declared.length>0&&declared.some((f)=>f!==""&&normalizedCallerFiles.includes(f)))return{taskId:candidate.taskId};return{unbound:candidate.taskId,reason:"files_mismatch"}}return null}catch(error93){return warn("Durable gate attribution fallback failed",{error:String(error93)}),null}}function enforceSpecDriftGate(directory,toolName){if(!directory)return;if(!SPEC_DRIFT_BLOCKED_TOOLS.has(toolName))return;let stalePath=path103.join(directory,".swarm","spec-staleness.json");if(fsSync11.existsSync(stalePath)){let diffInfo=null;try{diffInfo=computeSpecDiff(directory)}catch{}let message=`SPEC_DRIFT_BLOCK: tool "${toolName}" is blocked because .swarm/spec-staleness.json exists. Run /swarm clarify to enter spec repair mode. Clarify alone does not clear drift: rewrite the spec so recovery can reconcile it, or run /swarm acknowledge-spec-drift to dismiss, then retry.`;if(diffInfo){let sectionSummary=diffInfo.changedSections.length>0?`
|
|
1203
1203
|
Changed sections: ${diffInfo.changedSections.map((s)=>`## ${s}`).join(", ")}`:"";message+=`
|
|
1204
1204
|
|
|
@@ -1363,7 +1363,7 @@ Ignoring will not affect already-tracked files. To stop tracking them, run:
|
|
|
1363
1363
|
echo ".swarm/" >> .gitignore
|
|
1364
1364
|
git commit -m "Stop tracking opencode-swarm runtime state"`)}catch{}}var _internals114,_swarmGitExcludedChecked=!1,ENSURE_SWARM_GIT_EXCLUDED_OUTER_TIMEOUT_MS=3000,ENSURE_SWARM_GIT_EXCLUDED_PER_CALL_TIMEOUT_MS=1500,GIT_SPAWN_OPTIONS;var init_gitignore_warning=__esm(()=>{init_warning_buffer();init_bun_compat();init_git_executable();_internals114={bunSpawn,resolveGitExecutableAsync};GIT_SPAWN_OPTIONS={timeout:ENSURE_SWARM_GIT_EXCLUDED_PER_CALL_TIMEOUT_MS,stdin:"ignore",stdout:"pipe",stderr:"pipe"}});import*as fs77 from"node:fs";import*as path122 from"node:path";function getDeclaredScope(taskId,directory){try{let planPath=path122.join(directory,".swarm","plan.json");if(!fs77.existsSync(planPath))return null;let raw=fs77.readFileSync(planPath,"utf-8"),plan=JSON.parse(raw);for(let phase of plan.phases??[])for(let task of phase.tasks??[]){if(task.id!==taskId)continue;let ft=task.files_touched;if(Array.isArray(ft)&&ft.length>0)return ft;if(typeof ft==="string"&&ft.length>0)return[ft];return null}return null}catch{return null}}async function getChangedFiles(directory){try{let gitExecutable=_internals115.resolveGitExecutable(),proc=_internals115.bunSpawn([gitExecutable,"diff","--name-only","HEAD~1"],{cwd:directory,...GIT_DIFF_SPAWN_OPTIONS}),exitCode,stdout;try{[exitCode,stdout]=await Promise.all([proc.exited,proc.stdout.text()])}finally{try{proc.kill()}catch{}}if(exitCode===0)return{files:stdout.trim().split(`
|
|
1365
1365
|
`).map((f)=>f.trim()).filter((f)=>f.length>0),basis:"HEAD~1"};let proc2=_internals115.bunSpawn([gitExecutable,"diff","--name-only","HEAD"],{cwd:directory,...GIT_DIFF_SPAWN_OPTIONS}),exitCode2,stdout2;try{[exitCode2,stdout2]=await Promise.all([proc2.exited,proc2.stdout.text()])}finally{try{proc2.kill()}catch{}}if(exitCode2===0)return{files:stdout2.trim().split(`
|
|
1366
|
-
`).map((f)=>f.trim()).filter((f)=>f.length>0),basis:"HEAD"};return{files:null,basis:"HEAD~1"}}catch{return{files:null,basis:"HEAD~1"}}}async function getLatestCommitShortSha(directory){try{let gitExecutable=_internals115.resolveGitExecutable(),proc=_internals115.bunSpawn([gitExecutable,"rev-parse","--short","HEAD"],{cwd:directory,...GIT_DIFF_SPAWN_OPTIONS}),exitCode,stdout;try{[exitCode,stdout]=await Promise.all([proc.exited,proc.stdout.text()])}finally{try{proc.kill()}catch{}}if(exitCode===0){let sha=stdout.trim();if(sha.length>0&&!/\s/.test(sha))return sha}return""}catch{return""}}function hasDeclaredDiffScope(taskId,directory){try{return getDeclaredScope(taskId,directory)!==null}catch{return!1}}async function validateDiffScope(taskId,directory,attribution){try{let declaredScope=getDeclaredScope(taskId,directory);if(!declaredScope)return null;let normalise=(p)=>p.replace(/\\/g,"/").replace(/^\.\//,""),isSwarmPath2=(p)=>normalise(p).startsWith(".swarm/"),normScope=new Set(declaredScope.map(normalise)),canonicaliseAttributionEntry=(raw)=>{let resolved=path122.isAbsolute(raw)?path122.normalize(raw):path122.resolve(directory,raw),relative33=path122.relative(directory,resolved);if(!relative33)return null;if(relative33.startsWith("..")||path122.isAbsolute(relative33))return null;return relative33},attributed=attribution?.attributedFiles,undeclared,evidence2;if(Array.isArray(attributed)&&attributed.length>0){let normScopeAttribution=new Set(declaredScope.map(normalizePath));undeclared=attributed.filter((f)=>typeof f==="string"&&f.length>0).map(canonicaliseAttributionEntry).filter((entry)=>entry!==null).map(normalise).filter((f)=>!isSwarmPath2(f)).filter((f)=>!normScopeAttribution.has(normalizePath(f))),evidence2="task attribution record"}else{let{files,basis}=await getChangedFiles(directory);if(!files)return null;if(undeclared=files.filter((f)=>!isSwarmPath2(f)).map(normalise).filter((f)=>!normScope.has(f)),undeclared.length===0)return null;let sha=await getLatestCommitShortSha(directory),shaSuffix=sha?` ${sha}`:"";evidence2=basis==="HEAD"?`repository-wide uncommitted diff vs HEAD${shaSuffix}`:`repository-wide diff vs latest commit${shaSuffix}`}if(undeclared.length===0)return null;let scopeStr=declaredScope.join(", "),undeclaredStr=undeclared.slice(0,5).join(", "),extra=undeclared.length>5?` (+${undeclared.length-5} more)`:"";return`SCOPE WARNING: Task ${taskId} declared scope [${scopeStr}] but also modified [${undeclaredStr}${extra}] (evidence: ${evidence2}). Reviewer should verify these changes are intentional.`}catch{return null}}var _internals115,GIT_DIFF_SPAWN_OPTIONS;var init_diff_scope=__esm(()=>{init_bun_compat();init_git_executable();init_gitignore_warning();init_path();_internals115={bunSpawn,resolveGitExecutable};GIT_DIFF_SPAWN_OPTIONS={timeout:ENSURE_SWARM_GIT_EXCLUDED_PER_CALL_TIMEOUT_MS,stdin:"ignore",stdout:"pipe",stderr:"pipe"}});import*as fs78 from"node:fs";import*as path123 from"node:path";function verifyLeanTurboTaskCompletion(directory,taskId,sessionID){let persisted=null;try{let statePath2=path123.join(directory,".swarm","turbo-state.json");if(!fs78.existsSync(statePath2))return{ok:!1,reason:"Lean Turbo state file not found"};let raw=fs78.readFileSync(statePath2,"utf-8");persisted=JSON.parse(raw)}catch{return{ok:!1,reason:"Lean Turbo state file unreadable or malformed"}}if(typeof persisted!=="object"||persisted===null||typeof persisted.sessions!=="object"||persisted.sessions===null||Array.isArray(persisted.sessions))return{ok:!1,reason:"Lean Turbo state malformed: missing expected fields"};let runState=null;for(let sessionState of Object.values(persisted.sessions))if(typeof sessionState==="object"&&sessionState!==null&&sessionState.strategy==="lean"&&sessionState.status==="running"){if(sessionID!==void 0&&sessionState.sessionID!==sessionID)continue;runState=sessionState;break}if(!runState)return{ok:!1,reason:"No active Lean Turbo run state found"};if(!Array.isArray(runState.lanes)||!Array.isArray(runState.degradedTasks))return{ok:!1,reason:"Lean Turbo state malformed: missing expected fields"};let lane=runState.lanes.find((l)=>typeof l==="object"&&l!==null&&Array.isArray(l.taskIds)&&typeof l.laneId==="string"&&l.taskIds.includes(taskId));if(!lane)return{ok:!1,reason:`Task ${taskId} not found in any Lean Turbo lane`,laneFound:!1};let degradedTask=runState.degradedTasks.find((dt)=>typeof dt==="object"&&dt!==null&&dt.taskId===taskId);if(degradedTask)return{ok:!1,reason:`Task ${taskId} is degraded: ${degradedTask.reason}`,laneFound:!0};if(lane.status!=="completed")return{ok:!1,reason:`Lane ${lane.laneId} is not completed (status: ${lane.status})`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};if(lane.laneId.length===0||lane.laneId.includes("/")||lane.laneId.includes("\\")||lane.laneId.includes(".."))return{ok:!1,reason:`Lane ID contains invalid characters: ${lane.laneId}`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};let phase=runState.phase??0,evidencePath=path123.join(directory,".swarm","evidence",String(phase),"lean-turbo",`${lane.laneId}.json`),expectedDir=path123.join(directory,".swarm","evidence",String(phase),"lean-turbo"),resolvedPath=path123.resolve(evidencePath),resolvedDir=path123.resolve(expectedDir);if(!resolvedPath.startsWith(resolvedDir+path123.sep)&&resolvedPath!==resolvedDir)return{ok:!1,reason:`Lane ID causes path traversal: ${lane.laneId}`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};if(!fs78.existsSync(evidencePath))return{ok:!1,reason:`Lane ${lane.laneId} evidence file not found: ${evidencePath}`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};let laneLocks=_internals116.listActiveLocks(directory).filter((lock)=>lock.laneId===lane.laneId);if(laneLocks.length>0)return{ok:!1,reason:`Active file locks exist for lane ${lane.laneId}: ${laneLocks.map((l)=>l.filePath).join(", ")}`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};let filesTouched=[];try{let planPath=path123.join(directory,".swarm","plan.json"),planRaw=fs78.readFileSync(planPath,"utf-8"),plan=JSON.parse(planRaw);for(let planPhase of plan.phases??[])for(let task of planPhase.tasks??[])if(task.id===taskId&&task.files_touched){filesTouched=task.files_touched;break}}catch{return{ok:!1,reason:`Cannot verify Tier-3 patterns for task ${taskId}: plan.json unreadable`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}}}if(filesTouched.length>0&&matchesTier3(filesTouched))return{ok:!1,reason:`Task ${taskId} touches Tier-3 security-sensitive files and cannot bypass Stage B`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};return{ok:!0,reason:`Task ${taskId} in completed lane ${lane.laneId}`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}}}var _internals116;var init_task_completion=__esm(()=>{init_file_locks();init_tier3_classifier();_internals116={listActiveLocks,verifyLeanTurboTaskCompletion}});function applySessionWorkflowView(session,taskId,workflow){session.taskWorkflowStates.set(taskId,workflow.state),session.stageBCompletion?.delete(taskId),session.taskCouncilApproved?.delete(taskId),session.taskCouncilWorkflowGeneration?.delete(taskId),updateTaskWorkflowCache(session,taskId,workflow)}function isStageARecoveredState(state2){return STAGE_A_RECOVERED_STATES.includes(state2)}function shouldRefreshStageARecoveryView(view,recoveredState){if(view===void 0)return!0;if(view==="rework_required"||view==="blocked")return!0;if(view==="tests_run"||view==="closed"||view==="complete")return!1;return compareTaskWorkflowStateRank(recoveredState,view)>0}var STAGE_A_RECOVERED_STATES;var init_session_view=__esm(()=>{init_gate_evidence();init_state();STAGE_A_RECOVERED_STATES=["pre_check_passed","reviewer_run","tests_run"]});import*as fs79 from"node:fs";import*as path124 from"node:path";async function recordRunMemoryOutcome(directory,input){try{await _internals117.recordTaskAttempt(directory,input)}catch(_error){}}function syncCallerWorkflowFromEvidence(sessionId,taskId,evidence2){if(!sessionId)return;let callerSession=ensureAgentSession(sessionId),workflow=getTaskWorkflowSnapshot(evidence2);applySessionWorkflowView(callerSession,taskId,workflow)}async function hasPreparedWorkflowWal(directory,taskId,kind){return await readPreparedWorkflowWal(directory,taskId,kind)!==null}async function readPreparedWorkflowWal(directory,taskId,kind){let walPath2=validateSwarmPath(directory,kind==="task-repair"?`task-repairs/${taskId}.json`:`task-terminals/${taskId}.json`),wal=await readWorkflowWalFile(kind,walPath2,taskId);return wal?.state==="PREPARED"?wal:null}function resolveRunMemoryFileTargets(plan,taskId){return plan?.phases.flatMap((phase)=>phase.tasks).find((candidate)=>candidate.id===taskId)?.files_touched??[]}function validateStatus(status2){if(!VALID_STATUSES.includes(status2))return`Invalid status "${status2}". Must be one of: ${VALID_STATUSES.join(", ")}`;return}function validateTaskId(taskId){if(validateTaskIdFormat(taskId))return`Invalid task_id "${taskId}". Must match pattern N.M or N.M.P (e.g., "1.1", "1.2.3")`;return}function getSettledTransitionRejection(taskId,currentStatus,nextStatus,force){if(currentStatus!=="pending"&¤tStatus!=="in_progress"&&nextStatus!==currentStatus){if(nextStatus!=="in_progress"||force!==!0)return{success:!1,message:`Task ${taskId} is settled (${currentStatus}); backward transitions require the audited in_progress repair path.`,errors:[`Task ${taskId} is settled (${currentStatus}); use force:true with exact CAS and audit fields to repair it to in_progress.`]}}return null}function isRepairRetryShape(args2){return args2.status==="in_progress"&&args2.force===!0&&typeof args2.transition_id==="string"}function reviewerGateDecision(taskId,sessionID,result,reasonCode,evidenceKind){try{_internals117.emitReviewerGateDecision(sessionID??"",taskId,result.blocked,reasonCode,evidenceKind)}catch(_error){}return result}function hasPassedDurableGateEvidence(workingDirectory,taskId){let evidence2=readTaskEvidenceRaw(workingDirectory,taskId);if(!evidence2||!Array.isArray(evidence2.required_gates)||evidence2.required_gates.length===0)return!1;return evidence2.required_gates.every((gate)=>evidence2.gates?.[gate]!=null)}function routeGateAllowsTask(directory,taskId,sessionID){if(!directory)return!0;if(!(()=>{try{return loadPluginConfig(directory).review_routing?.enforce_receipts??!0}catch{return!0}})())return!0;let requirementReceipts=(()=>{try{return readTaskGateRequirementsReceiptsSync(directory,taskId)}catch{return null}})();if(!requirementReceipts)return!1;let session=sessionID?swarmState.agentSessions.get(sessionID):void 0,routeRequired=sessionID?session?isStageBRouteRequired(session,taskId):!1:[...swarmState.agentSessions.values()].some((candidate)=>isStageBRouteRequired(candidate,taskId)),legacyUnrouted=isLegacyTaskGateRequirementsChain(requirementReceipts)&&!routeRequired;if(!routeRequired&&requirementReceipts.length===0)return!0;let durableEvidence=routeEvidenceFromTaskGateRequirements(requirementReceipts),routeAllowsSession=(candidateSessionID,candidateSession)=>{try{readReviewRouteReceiptSync({projectRoot:directory,sessionId:candidateSessionID,taskId})}catch{return!1}let liveEvidence=candidateSession?getStageBRouteEvidence(candidateSession,taskId):[];return enforcePersistedReviewRouteReceipt({projectRoot:directory,sessionId:candidateSessionID,taskId,receipts:liveEvidence.length>0?liveEvidence:durableEvidence,enforcementEnabled:!0,legacyUnrouted:!1,requireEvidenceBindings:!0}).canAdvance};if(sessionID)return routeAllowsSession(sessionID,session);if(!routeRequired)return legacyUnrouted;let evidenceSessionIDs=new Set(durableEvidence.map((evidence2)=>evidence2.sessionId).filter((value)=>Boolean(value)));for(let[candidateSessionID,candidateSession]of swarmState.agentSessions){if(!isStageBRouteRequired(candidateSession,taskId)&&!evidenceSessionIDs.has(candidateSessionID))continue;if(routeAllowsSession(candidateSessionID,candidateSession))return!0}return!1}function checkReviewerGate(taskId,workingDirectory,stageBParallelEnabled=!1,sessionID,fallbackDir,currentDeclaredFiles){try{let skipStandardTurboBypass=!1;if(!fallbackDir&&!sessionID&&_internals117.hasActiveLeanTurbo(sessionID)){let resolvedDir2=workingDirectory;try{let leanCheck=_internals117.verifyLeanTurboTaskCompletion(resolvedDir2,taskId,sessionID);if(leanCheck.ok)return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:`Lean Turbo bypass: ${leanCheck.reason}`},"lean_turbo_completed_lane","fallback");if(leanCheck.laneFound!==!1)skipStandardTurboBypass=!0}catch{skipStandardTurboBypass=!0}}if(!fallbackDir&&!sessionID&&!skipStandardTurboBypass&&_internals117.hasActiveTurboMode(sessionID)){let resolvedDir2=workingDirectory;try{let planPath=path124.join(resolvedDir2,".swarm","plan.json"),planRaw=fs79.readFileSync(planPath,"utf-8"),plan=JSON.parse(planRaw);for(let planPhase of plan.phases??[])for(let task of planPhase.tasks??[])if(task.id===taskId&&Array.isArray(task.files_touched)&&task.files_touched.length>0){if(!matchesTier3(task.files_touched))return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:"Turbo Mode bypass"},"standard_turbo_non_tier3","fallback");break}}catch{}}let authoritativeDir;if(fallbackDir){let resolved=_internals117.resolveWorkingDirectory(workingDirectory,fallbackDir);authoritativeDir=resolved.success?resolved.directory:fallbackDir}else if(workingDirectory)authoritativeDir=workingDirectory;if(authoritativeDir){let legacyDirectCaller=Symbol("legacy-direct-reviewer-gate");try{let evidence2=_internals117.readTaskEvidenceRaw(authoritativeDir,taskId);if(!fallbackDir&&!sessionID&&!evidence2?.workflow)throw legacyDirectCaller;try{let planPath=path124.join(authoritativeDir,".swarm","plan.json"),planRaw=fs79.readFileSync(planPath,"utf-8"),plan=JSON.parse(planRaw),declaredTask=(plan.phases??[]).flatMap((phase)=>phase.tasks??[]).find((task)=>task.id===taskId);if(declaredTask&&declaredTask.evidence_class==="external_git"&&typeof plan.title==="string"&&typeof plan.swarm==="string"){let planIdentity={title:plan.title,swarm:plan.swarm},workflow2=getTaskWorkflowSnapshot(evidence2);if(isExternalEvidenceInitialCompletionEligible(planIdentity,declaredTask,evidence2)||workflow2.state==="complete"&&externalProofCurrent(planIdentity,declaredTask,evidence2))return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:`External evidence attested: task ${taskId} completed via the pinned external_git anchors (issue #3422)`,requiredGates:[],satisfiedGates:[],missingGates:[],source:"external_attest",generation:workflow2.generation},"durable_evidence_complete","fallback");return reviewerGateDecision(taskId,sessionID,{blocked:!0,reason:`Task ${taskId} declares external_git evidence but no matched attestation exists yet. Run /swarm attest ${taskId} (or re-plan it as a thin coder dispatch).`,requiredGates:[],satisfiedGates:[],missingGates:["external_attest"],source:"durable_exact_task",generation:workflow2.generation,nextAction:`Run /swarm attest ${taskId} (or re-plan it as a thin coder dispatch).`},"required_gates_missing","block")}}catch{}if(!evidence2)return reviewerGateDecision(taskId,sessionID,{blocked:!0,reason:`Task ${taskId} has no exact-task QA evidence. Delegate the required Stage B agents, then retry completion.`,requiredGates:[],satisfiedGates:[],missingGates:["reviewer","test_engineer"],source:"durable_exact_task",generation:0,nextAction:"Delegate reviewer and test_engineer for this exact task generation."},"required_gates_missing","block");if(!evidence2.workflow){let derivedGates2=deriveApplicableGateSet(evidence2);return reviewerGateDecision(taskId,sessionID,{blocked:!0,reason:`Task ${taskId} has legacy QA evidence without an authoritative workflow generation. Run a fresh exact-task workflow transition before completion.`,requiredGates:derivedGates2.requiredGates,satisfiedGates:derivedGates2.satisfiedGates,missingGates:derivedGates2.missingGates,source:"durable_exact_task",generation:0,nextAction:"Re-run the exact-task coder/Stage A/Stage B workflow to migrate evidence."},"required_gates_missing","block")}let workflow=getTaskWorkflowSnapshot(evidence2),derivedGates=deriveApplicableGateSet(evidence2,{currentDeclaredFiles:currentDeclaredFiles===void 0?readCurrentTaskDeclaredFiles(authoritativeDir,taskId):currentDeclaredFiles}),requiredGates=derivedGates.requiredGates,satisfiedGates=derivedGates.satisfiedGates,missingGates=derivedGates.missingGates;if(requiredGates.includes(TASK_GATE_REQUIREMENTS_RECONSTRUCTION_SENTINEL)){let recovery=`Task ${taskId} contains a legacy receipt-less gate-repair marker that no agent can satisfy. Call repair_gate_evidence for task ${taskId}, then delegate coder for a fresh accepted mutation before rerunning Stage A and Stage B.`;return reviewerGateDecision(taskId,sessionID,{blocked:!0,reason:recovery,requiredGates,satisfiedGates,missingGates,source:"durable_exact_task",generation:workflow.generation,nextAction:recovery},"required_gates_missing","data_quality")}let contradictorySignals=[];if((workflow.state==="tests_run"||workflow.state==="complete")&&missingGates.length>0)contradictorySignals.push(`workflow state ${workflow.state} claims completion readiness while required proof is missing`);if(workflow.state!=="tests_run"&&workflow.state!=="complete"&&evidence2.gates.pre_check!=null&&requiredGates.length>0&&missingGates.length===0)contradictorySignals.push(`all required proof exists but workflow state is ${workflow.state}`);let workflowComplete=workflow.state==="tests_run"||workflow.state==="complete";if(missingGates.length===0&&contradictorySignals.length===0&&(workflowComplete||derivedGates.readOnlyNoMutation)){if(!derivedGates.readOnlyNoMutation&&!routeGateAllowsTask(authoritativeDir,taskId,sessionID))return reviewerGateDecision(taskId,sessionID,{blocked:!0,reason:`Task ${taskId} has not satisfied its exact v1 review route receipt. Missing or mismatched route evidence fails closed.`,requiredGates,satisfiedGates,missingGates:["review_route_receipt"],source:"durable_exact_task",generation:workflow.generation,nextAction:"Recover the exact route receipt and independent Stage-B bindings before completing this task."},"required_gates_missing","block");return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:"",requiredGates,satisfiedGates,missingGates,contradictorySignals,source:"durable_exact_task",generation:workflow.generation},"durable_evidence_complete","genuine")}return reviewerGateDecision(taskId,sessionID,{blocked:!0,reason:`Task ${taskId} generation ${workflow.generation} has not passed exact-task QA. State: ${workflow.state}. Missing gates: [${missingGates.join(", ")}]. Contradictions: [${contradictorySignals.join("; ")}].`,requiredGates,satisfiedGates,missingGates,contradictorySignals,source:"durable_exact_task",generation:workflow.generation,nextAction:workflow.state==="rework_required"?"Delegate the same task to coder for repair, then rerun Stage A and Stage B.":"Complete the missing exact-task Stage A/Stage B transitions."},"required_gates_missing","block")}catch(error93){if(error93===legacyDirectCaller);else return reviewerGateDecision(taskId,sessionID,{blocked:!0,reason:`Evidence file for task ${taskId} is corrupt or unreadable: ${error93 instanceof Error?error93.message:String(error93)}. Call repair_gate_evidence for task ${taskId}; corrupt evidence fails closed until the repair completes.`,requiredGates:[],satisfiedGates:[],missingGates:["reviewer","test_engineer"],source:"durable_exact_task",corrupt:!0,nextAction:`Call repair_gate_evidence for task ${taskId}; corrupt evidence fails closed until the repair completes.`},"corrupt_evidence","data_quality")}}let resolvedDir;if(fallbackDir){let resolveResult=_internals117.resolveWorkingDirectory(workingDirectory,fallbackDir);if(resolveResult.success)resolvedDir=resolveResult.directory;else resolvedDir=fallbackDir}else if(workingDirectory)resolvedDir=workingDirectory;let routeAllowsStageB=(sessionId,_session)=>routeGateAllowsTask(resolvedDir,taskId,sessionId),evidenceIncompleteReason=null;try{if(!resolvedDir);else{let evidence2=_internals117.readTaskEvidenceRaw(resolvedDir,taskId);if(evidence2===null);else if(evidence2.required_gates&&Array.isArray(evidence2.required_gates)&&evidence2.gates){if(evidence2.required_gates.length>0&&evidence2.required_gates.every((gate)=>evidence2.gates[gate]!=null)){let routeSession=sessionID?swarmState.agentSessions.get(sessionID):void 0;if(!resolvedDir||routeAllowsStageB(sessionID,routeSession))return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:""},"durable_evidence_complete","genuine")}let missingGates=evidence2.required_gates.filter((gate)=>evidence2.gates[gate]==null);evidenceIncompleteReason=evidence2.required_gates.length===0?`Task ${taskId} has an evidence file with no required gates. Delegate reviewer and test_engineer before marking task as completed.`:`Task ${taskId} is missing required gates: [${missingGates.join(", ")}]. Required: [${evidence2.required_gates.join(", ")}]. Completed: [${Object.keys(evidence2.gates).join(", ")}]. Delegate the missing gate agents before marking task as completed.`}}}catch(error93){return log(`[gate-evidence] Evidence file for task ${taskId} is corrupt or unreadable:`,error93 instanceof Error?error93.message:String(error93)),telemetry.gateFailed("","qa_gate",taskId,"Evidence file corrupt or unreadable"),reviewerGateDecision(taskId,sessionID,{blocked:!0,reason:`Evidence file for task ${taskId} is corrupt or unreadable. Call repair_gate_evidence for task ${taskId}; corrupt evidence fails closed until the repair completes.`},"corrupt_evidence","data_quality")}if(swarmState.agentSessions.size===0&&!evidenceIncompleteReason)return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:""},"no_active_sessions","fallback");let validSessionCount=0;for(let[_sessionId,session]of swarmState.agentSessions){if(!(session.taskWorkflowStates instanceof Map))continue;validSessionCount++;let state2=getTaskState(session,taskId);if(state2==="tests_run"||state2==="complete"){if(resolvedDir&&!routeAllowsStageB(_sessionId,session))continue;return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:""},"workflow_state_complete","genuine")}if(stageBParallelEnabled&&hasBothStageBCompletions(session,taskId)&&(!resolvedDir||routeAllowsStageB(_sessionId,session)))return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:""},"stage_b_parallel_complete","genuine")}if(validSessionCount===0&&!evidenceIncompleteReason)return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:""},"zero_valid_sessions","data_quality");let stateEntries=[];for(let[sessionId,session]of swarmState.agentSessions){if(!(session.taskWorkflowStates instanceof Map))continue;let state2=getTaskState(session,taskId);stateEntries.push(`${sessionId}: ${state2}`)}if(resolvedDir)try{let planPath=path124.join(resolvedDir,".swarm","plan.json"),planRaw=fs79.readFileSync(planPath,"utf-8"),plan=JSON.parse(planRaw);for(let planPhase of plan.phases??[])for(let task of planPhase.tasks??[])if(task.id===taskId&&task.status==="completed"&&_internals117.hasPassedDurableGateEvidence(resolvedDir,taskId))return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:""},"restart_recovery_complete","genuine")}catch{}{let hasReviewer=!1,hasTestEngineer=!1;for(let[sessionId,chain]of swarmState.delegationChains){let session=swarmState.agentSessions.get(sessionId);if(session&&(session.currentTaskId===taskId||session.lastCoderDelegationTaskId===taskId))for(let delegation of chain){let target=stripKnownSwarmPrefix(delegation.to);if(target==="reviewer")hasReviewer=!0;if(target==="test_engineer")hasTestEngineer=!0}}if(hasReviewer&&hasTestEngineer)return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:""},"scoped_delegation_complete","genuine");if(!evidenceIncompleteReason&&(!hasReviewer||!hasTestEngineer)){for(let[sessionId,chain]of swarmState.delegationChains){if(chain.some((d)=>stripKnownSwarmPrefix(d.to)==="coder"))continue;let chainSession=swarmState.agentSessions.get(sessionId);if(chainSession){let chainTaskId=chainSession.currentTaskId||chainSession.lastCoderDelegationTaskId;if(chainTaskId&&chainTaskId!==taskId)continue}for(let delegation of chain){let target=stripKnownSwarmPrefix(delegation.to);if(target==="reviewer")hasReviewer=!0;if(target==="test_engineer")hasTestEngineer=!0}}if(hasReviewer&&hasTestEngineer)return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:""},"unscoped_delegation_complete","genuine")}}let currentStateStr=stateEntries.length>0?stateEntries.join(", "):"no active sessions",chainEntries=[];for(let[sessionId,chain]of swarmState.delegationChains){let session=swarmState.agentSessions.get(sessionId);if(session&&(session.currentTaskId===taskId||session.lastCoderDelegationTaskId===taskId)){let targets=chain.map((d)=>stripKnownSwarmPrefix(d.to));chainEntries.push(`${sessionId}: [${targets.join(", ")}]`)}}let chainSummary=chainEntries.length>0?chainEntries.join("; "):"no chains for this task",rehydratedSessionCount=[...swarmState.agentSessions.values()].filter((s)=>s.sessionRehydratedAt>0).length,finalReason=[`Task ${taskId} has not passed QA gates.`,` Session states: [${currentStateStr}].`,` Delegation chains: [${chainSummary}].`,` Evidence: [${evidenceIncompleteReason??"no evidence file found"}].`,` Rehydrated sessions: ${rehydratedSessionCount}.`," Missing required state: tests_run or complete."].join(`
|
|
1366
|
+
`).map((f)=>f.trim()).filter((f)=>f.length>0),basis:"HEAD"};return{files:null,basis:"HEAD~1"}}catch{return{files:null,basis:"HEAD~1"}}}async function getLatestCommitShortSha(directory){try{let gitExecutable=_internals115.resolveGitExecutable(),proc=_internals115.bunSpawn([gitExecutable,"rev-parse","--short","HEAD"],{cwd:directory,...GIT_DIFF_SPAWN_OPTIONS}),exitCode,stdout;try{[exitCode,stdout]=await Promise.all([proc.exited,proc.stdout.text()])}finally{try{proc.kill()}catch{}}if(exitCode===0){let sha=stdout.trim();if(sha.length>0&&!/\s/.test(sha))return sha}return""}catch{return""}}function hasDeclaredDiffScope(taskId,directory){try{return getDeclaredScope(taskId,directory)!==null}catch{return!1}}async function validateDiffScope(taskId,directory,attribution){try{let declaredScope=getDeclaredScope(taskId,directory);if(!declaredScope)return null;let normalise=(p)=>p.replace(/\\/g,"/").replace(/^\.\//,""),isSwarmPath2=(p)=>normalise(p).startsWith(".swarm/"),normScope=new Set(declaredScope.map(normalise)),canonicaliseAttributionEntry=(raw)=>{let resolved=path122.isAbsolute(raw)?path122.normalize(raw):path122.resolve(directory,raw),relative33=path122.relative(directory,resolved);if(!relative33)return null;if(relative33.startsWith("..")||path122.isAbsolute(relative33))return null;return relative33},attributed=attribution?.attributedFiles,undeclared,evidence2;if(Array.isArray(attributed)&&attributed.length>0){let normScopeAttribution=new Set(declaredScope.map(normalizePath));undeclared=attributed.filter((f)=>typeof f==="string"&&f.length>0).map(canonicaliseAttributionEntry).filter((entry)=>entry!==null).map(normalise).filter((f)=>!isSwarmPath2(f)).filter((f)=>!normScopeAttribution.has(normalizePath(f))),evidence2="task attribution record"}else{let{files,basis}=await getChangedFiles(directory);if(!files)return null;if(undeclared=files.filter((f)=>!isSwarmPath2(f)).map(normalise).filter((f)=>!normScope.has(f)),undeclared.length===0)return null;let sha=await getLatestCommitShortSha(directory),shaSuffix=sha?` ${sha}`:"";evidence2=basis==="HEAD"?`repository-wide uncommitted diff vs HEAD${shaSuffix}`:`repository-wide diff vs latest commit${shaSuffix}`}if(undeclared.length===0)return null;let scopeStr=declaredScope.join(", "),undeclaredStr=undeclared.slice(0,5).join(", "),extra=undeclared.length>5?` (+${undeclared.length-5} more)`:"";return`SCOPE WARNING: Task ${taskId} declared scope [${scopeStr}] but also modified [${undeclaredStr}${extra}] (evidence: ${evidence2}). Reviewer should verify these changes are intentional.`}catch{return null}}var _internals115,GIT_DIFF_SPAWN_OPTIONS;var init_diff_scope=__esm(()=>{init_bun_compat();init_git_executable();init_gitignore_warning();init_path();_internals115={bunSpawn,resolveGitExecutable};GIT_DIFF_SPAWN_OPTIONS={timeout:ENSURE_SWARM_GIT_EXCLUDED_PER_CALL_TIMEOUT_MS,stdin:"ignore",stdout:"pipe",stderr:"pipe"}});import*as fs78 from"node:fs";import*as path123 from"node:path";function verifyLeanTurboTaskCompletion(directory,taskId,sessionID){let persisted=null;try{let statePath2=path123.join(directory,".swarm","turbo-state.json");if(!fs78.existsSync(statePath2))return{ok:!1,reason:"Lean Turbo state file not found"};let raw=fs78.readFileSync(statePath2,"utf-8");persisted=JSON.parse(raw)}catch{return{ok:!1,reason:"Lean Turbo state file unreadable or malformed"}}if(typeof persisted!=="object"||persisted===null||typeof persisted.sessions!=="object"||persisted.sessions===null||Array.isArray(persisted.sessions))return{ok:!1,reason:"Lean Turbo state malformed: missing expected fields"};let runState=null;for(let sessionState of Object.values(persisted.sessions))if(typeof sessionState==="object"&&sessionState!==null&&sessionState.strategy==="lean"&&sessionState.status==="running"){if(sessionID!==void 0&&sessionState.sessionID!==sessionID)continue;runState=sessionState;break}if(!runState)return{ok:!1,reason:"No active Lean Turbo run state found"};if(!Array.isArray(runState.lanes)||!Array.isArray(runState.degradedTasks))return{ok:!1,reason:"Lean Turbo state malformed: missing expected fields"};let lane=runState.lanes.find((l)=>typeof l==="object"&&l!==null&&Array.isArray(l.taskIds)&&typeof l.laneId==="string"&&l.taskIds.includes(taskId));if(!lane)return{ok:!1,reason:`Task ${taskId} not found in any Lean Turbo lane`,laneFound:!1};let degradedTask=runState.degradedTasks.find((dt)=>typeof dt==="object"&&dt!==null&&dt.taskId===taskId);if(degradedTask)return{ok:!1,reason:`Task ${taskId} is degraded: ${degradedTask.reason}`,laneFound:!0};if(lane.status!=="completed")return{ok:!1,reason:`Lane ${lane.laneId} is not completed (status: ${lane.status})`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};if(lane.laneId.length===0||lane.laneId.includes("/")||lane.laneId.includes("\\")||lane.laneId.includes(".."))return{ok:!1,reason:`Lane ID contains invalid characters: ${lane.laneId}`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};let phase=runState.phase??0,evidencePath=path123.join(directory,".swarm","evidence",String(phase),"lean-turbo",`${lane.laneId}.json`),expectedDir=path123.join(directory,".swarm","evidence",String(phase),"lean-turbo"),resolvedPath=path123.resolve(evidencePath),resolvedDir=path123.resolve(expectedDir);if(!resolvedPath.startsWith(resolvedDir+path123.sep)&&resolvedPath!==resolvedDir)return{ok:!1,reason:`Lane ID causes path traversal: ${lane.laneId}`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};if(!fs78.existsSync(evidencePath))return{ok:!1,reason:`Lane ${lane.laneId} evidence file not found: ${evidencePath}`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};let laneLocks=_internals116.listActiveLocks(directory).filter((lock)=>lock.laneId===lane.laneId);if(laneLocks.length>0)return{ok:!1,reason:`Active file locks exist for lane ${lane.laneId}: ${laneLocks.map((l)=>l.filePath).join(", ")}`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};let filesTouched=[];try{let planPath=path123.join(directory,".swarm","plan.json"),planRaw=fs78.readFileSync(planPath,"utf-8"),plan=JSON.parse(planRaw);for(let planPhase of plan.phases??[])for(let task of planPhase.tasks??[])if(task.id===taskId&&task.files_touched){filesTouched=task.files_touched;break}}catch{return{ok:!1,reason:`Cannot verify Tier-3 patterns for task ${taskId}: plan.json unreadable`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}}}if(filesTouched.length>0&&matchesTier3(filesTouched))return{ok:!1,reason:`Task ${taskId} touches Tier-3 security-sensitive files and cannot bypass Stage B`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}};return{ok:!0,reason:`Task ${taskId} in completed lane ${lane.laneId}`,laneFound:!0,evidence:{laneId:lane.laneId,laneStatus:lane.status,taskIds:lane.taskIds}}}var _internals116;var init_task_completion=__esm(()=>{init_file_locks();init_tier3_classifier();_internals116={listActiveLocks,verifyLeanTurboTaskCompletion}});function applySessionWorkflowView(session,taskId,workflow){session.taskWorkflowStates.set(taskId,workflow.state),session.stageBCompletion?.delete(taskId),session.taskCouncilApproved?.delete(taskId),session.taskCouncilWorkflowGeneration?.delete(taskId),updateTaskWorkflowCache(session,taskId,workflow)}function isStageARecoveredState(state2){return STAGE_A_RECOVERED_STATES.includes(state2)}function shouldRefreshStageARecoveryView(view,recoveredState){if(view===void 0)return!0;if(view==="rework_required"||view==="blocked")return!0;if(view==="tests_run"||view==="closed"||view==="complete")return!1;return compareTaskWorkflowStateRank(recoveredState,view)>0}var STAGE_A_RECOVERED_STATES;var init_session_view=__esm(()=>{init_gate_evidence();init_state();STAGE_A_RECOVERED_STATES=["pre_check_passed","reviewer_run","tests_run"]});import*as fs79 from"node:fs";import*as path124 from"node:path";async function recordRunMemoryOutcome(directory,input){try{await _internals117.recordTaskAttempt(directory,input)}catch(_error){}}function syncCallerWorkflowFromEvidence(sessionId,taskId,evidence2){if(!sessionId)return;let callerSession=ensureAgentSession(sessionId),workflow=getTaskWorkflowSnapshot(evidence2);applySessionWorkflowView(callerSession,taskId,workflow)}async function hasPreparedWorkflowWal(directory,taskId,kind){return await readPreparedWorkflowWal(directory,taskId,kind)!==null}async function readPreparedWorkflowWal(directory,taskId,kind){let walPath2=validateSwarmPath(directory,kind==="task-repair"?`task-repairs/${taskId}.json`:`task-terminals/${taskId}.json`),wal=await readWorkflowWalFile(kind,walPath2,taskId);return wal?.state==="PREPARED"?wal:null}function resolveRunMemoryFileTargets(plan,taskId){return plan?.phases.flatMap((phase)=>phase.tasks).find((candidate)=>candidate.id===taskId)?.files_touched??[]}function validateStatus(status2){if(!VALID_STATUSES.includes(status2))return`Invalid status "${status2}". Must be one of: ${VALID_STATUSES.join(", ")}`;return}function validateTaskId(taskId){if(validateTaskIdFormat(taskId))return`Invalid task_id "${taskId}". Must match pattern N.M or N.M.P (e.g., "1.1", "1.2.3")`;return}function getSettledTransitionRejection(taskId,currentStatus,nextStatus,force){if(currentStatus!=="pending"&¤tStatus!=="in_progress"&&nextStatus!==currentStatus){if(nextStatus!=="in_progress"||force!==!0)return{success:!1,message:`Task ${taskId} is settled (${currentStatus}); backward transitions require the audited in_progress repair path.`,errors:[`Task ${taskId} is settled (${currentStatus}); use force:true with exact CAS and audit fields to repair it to in_progress.`]}}return null}function isRepairRetryShape(args2){return args2.status==="in_progress"&&args2.force===!0&&typeof args2.transition_id==="string"}function reviewerGateDecision(taskId,sessionID,result,reasonCode,evidenceKind){try{_internals117.emitReviewerGateDecision(sessionID??"",taskId,result.blocked,reasonCode,evidenceKind)}catch(_error){}return result}function hasPassedDurableGateEvidence(workingDirectory,taskId){let evidence2=readTaskEvidenceRaw(workingDirectory,taskId);if(!evidence2||!Array.isArray(evidence2.required_gates)||evidence2.required_gates.length===0)return!1;return evidence2.required_gates.every((gate)=>evidence2.gates?.[gate]!=null)}function routeGateAllowsTask(directory,taskId,sessionID){if(!directory)return!0;if(!(()=>{try{return loadPluginConfig(directory).review_routing?.enforce_receipts??!0}catch{return!0}})())return!0;let requirementReceipts=(()=>{try{return readTaskGateRequirementsReceiptsSync(directory,taskId)}catch{return null}})();if(!requirementReceipts)return!1;let session=sessionID?swarmState.agentSessions.get(sessionID):void 0,routeRequired=sessionID?session?isStageBRouteRequired(session,taskId):!1:[...swarmState.agentSessions.values()].some((candidate)=>isStageBRouteRequired(candidate,taskId)),legacyUnrouted=isLegacyTaskGateRequirementsChain(requirementReceipts)&&!routeRequired;if(!routeRequired&&requirementReceipts.length===0)return!0;let durableEvidence=routeEvidenceFromTaskGateRequirements(requirementReceipts),routeAllowsSession=(candidateSessionID,candidateSession)=>{try{readReviewRouteReceiptSync({projectRoot:directory,sessionId:candidateSessionID,taskId})}catch{return!1}let liveEvidence=candidateSession?getStageBRouteEvidence(candidateSession,taskId):[];return enforcePersistedReviewRouteReceipt({projectRoot:directory,sessionId:candidateSessionID,taskId,receipts:liveEvidence.length>0?liveEvidence:durableEvidence,enforcementEnabled:!0,legacyUnrouted:!1,requireEvidenceBindings:!0}).canAdvance};if(sessionID)return routeAllowsSession(sessionID,session);if(!routeRequired)return legacyUnrouted;let evidenceSessionIDs=new Set(durableEvidence.map((evidence2)=>evidence2.sessionId).filter((value)=>Boolean(value)));for(let[candidateSessionID,candidateSession]of swarmState.agentSessions){if(!isStageBRouteRequired(candidateSession,taskId)&&!evidenceSessionIDs.has(candidateSessionID))continue;if(routeAllowsSession(candidateSessionID,candidateSession))return!0}return!1}function checkReviewerGate(taskId,workingDirectory,stageBParallelEnabled=!1,sessionID,fallbackDir,currentDeclaredFiles){try{let skipStandardTurboBypass=!1;if(!fallbackDir&&!sessionID&&_internals117.hasActiveLeanTurbo(sessionID)){let resolvedDir2=workingDirectory;try{let leanCheck=_internals117.verifyLeanTurboTaskCompletion(resolvedDir2,taskId,sessionID);if(leanCheck.ok)return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:`Lean Turbo bypass: ${leanCheck.reason}`},"lean_turbo_completed_lane","fallback");if(leanCheck.laneFound!==!1)skipStandardTurboBypass=!0}catch{skipStandardTurboBypass=!0}}if(!fallbackDir&&!sessionID&&!skipStandardTurboBypass&&_internals117.hasActiveTurboMode(sessionID)){let resolvedDir2=workingDirectory;try{let planPath=path124.join(resolvedDir2,".swarm","plan.json"),planRaw=fs79.readFileSync(planPath,"utf-8"),plan=JSON.parse(planRaw);for(let planPhase of plan.phases??[])for(let task of planPhase.tasks??[])if(task.id===taskId&&Array.isArray(task.files_touched)&&task.files_touched.length>0){if(!matchesTier3(task.files_touched))return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:"Turbo Mode bypass"},"standard_turbo_non_tier3","fallback");break}}catch{}}let authoritativeDir;if(fallbackDir){let resolved=_internals117.resolveWorkingDirectory(workingDirectory,fallbackDir);authoritativeDir=resolved.success?resolved.directory:fallbackDir}else if(workingDirectory)authoritativeDir=workingDirectory;if(authoritativeDir){let legacyDirectCaller=Symbol("legacy-direct-reviewer-gate");try{let evidence2=_internals117.readTaskEvidenceRaw(authoritativeDir,taskId);if(!fallbackDir&&!sessionID&&!evidence2?.workflow)throw legacyDirectCaller;try{let planPath=path124.join(authoritativeDir,".swarm","plan.json"),planRaw=fs79.readFileSync(planPath,"utf-8"),plan=JSON.parse(planRaw),declaredTask=(plan.phases??[]).flatMap((phase)=>phase.tasks??[]).find((task)=>task.id===taskId);if(declaredTask&&declaredTask.evidence_class==="external_git"&&typeof plan.title==="string"&&typeof plan.swarm==="string"){let planIdentity={title:plan.title,swarm:plan.swarm},workflow2=getTaskWorkflowSnapshot(evidence2);if(isExternalEvidenceInitialCompletionEligible(planIdentity,declaredTask,evidence2)||workflow2.state==="complete"&&externalProofCurrent(planIdentity,declaredTask,evidence2))return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:`External evidence attested: task ${taskId} completed via the pinned external_git anchors (issue #3422)`,requiredGates:[],satisfiedGates:[],missingGates:[],source:"external_attest",generation:workflow2.generation},"durable_evidence_complete","fallback");return reviewerGateDecision(taskId,sessionID,{blocked:!0,reason:`Task ${taskId} declares external_git evidence but no matched attestation exists yet. Run /swarm attest ${taskId} (or re-plan it as a thin coder dispatch).`,requiredGates:[],satisfiedGates:[],missingGates:["external_attest"],source:"durable_exact_task",generation:workflow2.generation,nextAction:`Run /swarm attest ${taskId} (or re-plan it as a thin coder dispatch).`},"required_gates_missing","block")}}catch{}if(!evidence2)return reviewerGateDecision(taskId,sessionID,{blocked:!0,reason:`Task ${taskId} has no exact-task QA evidence. Delegate the required Stage B agents, then retry completion.`,requiredGates:[],satisfiedGates:[],missingGates:["reviewer","test_engineer"],source:"durable_exact_task",generation:0,nextAction:"Delegate reviewer and test_engineer for this exact task generation."},"required_gates_missing","block");if(!evidence2.workflow){let derivedGates2=deriveApplicableGateSet(evidence2);return reviewerGateDecision(taskId,sessionID,{blocked:!0,reason:`Task ${taskId} has legacy QA evidence without an authoritative workflow generation. Run a fresh exact-task workflow transition before completion.`,requiredGates:derivedGates2.requiredGates,satisfiedGates:derivedGates2.satisfiedGates,missingGates:derivedGates2.missingGates,source:"durable_exact_task",generation:0,nextAction:"Re-run the exact-task coder/Stage A/Stage B workflow to migrate evidence."},"required_gates_missing","block")}let workflow=getTaskWorkflowSnapshot(evidence2),derivedGates=deriveApplicableGateSet(evidence2,{currentDeclaredFiles:currentDeclaredFiles===void 0?readCurrentTaskDeclaredFiles(authoritativeDir,taskId):currentDeclaredFiles}),requiredGates=derivedGates.requiredGates,satisfiedGates=derivedGates.satisfiedGates,missingGates=derivedGates.missingGates;if(requiredGates.includes(TASK_GATE_REQUIREMENTS_RECONSTRUCTION_SENTINEL)){let recovery=`Task ${taskId} contains a legacy receipt-less gate-repair marker that no agent can satisfy. Call repair_gate_evidence for task ${taskId}, then delegate coder for a fresh accepted mutation before rerunning Stage A and Stage B.`;return reviewerGateDecision(taskId,sessionID,{blocked:!0,reason:recovery,requiredGates,satisfiedGates,missingGates,source:"durable_exact_task",generation:workflow.generation,nextAction:recovery},"required_gates_missing","data_quality")}let contradictorySignals=[];if((workflow.state==="tests_run"||workflow.state==="complete")&&missingGates.length>0)contradictorySignals.push(`workflow state ${workflow.state} claims completion readiness while required proof is missing`);if(workflow.state!=="tests_run"&&workflow.state!=="complete"&&evidence2.gates.pre_check!=null&&requiredGates.length>0&&missingGates.length===0)contradictorySignals.push(`all required proof exists but workflow state is ${workflow.state}`);let currentPlanIdentity=resolveCurrentPlanIdentitySync(authoritativeDir),priorCampaignEvidence=evidenceStampedForDifferentPlan(evidence2,currentPlanIdentity?.planIdentityHash),workflowComplete=workflow.state==="tests_run"||workflow.state==="complete";if(missingGates.length===0&&contradictorySignals.length===0&&(workflowComplete||derivedGates.readOnlyNoMutation)){if(!derivedGates.readOnlyNoMutation&&!routeGateAllowsTask(authoritativeDir,taskId,sessionID))return reviewerGateDecision(taskId,sessionID,{blocked:!0,reason:priorCampaignEvidence?`Task ${taskId}'s exact-task evidence predates the current plan campaign (plan-identity stamp names a different plan). Run repair_gate_evidence for task ${taskId} to rebuild current-campaign evidence, then re-run the QA chain.`:`Task ${taskId} has not satisfied its exact v1 review route receipt. Missing or mismatched route evidence fails closed.`,requiredGates,satisfiedGates,missingGates:["review_route_receipt"],source:"durable_exact_task",generation:workflow.generation,nextAction:priorCampaignEvidence?"Run repair_gate_evidence for this task to rebuild current-campaign evidence, then re-run Stage A and Stage B.":"Recover the exact route receipt and independent Stage-B bindings before completing this task."},"required_gates_missing","block");return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:"",requiredGates,satisfiedGates,missingGates,contradictorySignals,source:"durable_exact_task",generation:workflow.generation},"durable_evidence_complete","genuine")}return reviewerGateDecision(taskId,sessionID,{blocked:!0,reason:`Task ${taskId} generation ${workflow.generation} has not passed exact-task QA. State: ${workflow.state}. Missing gates: [${missingGates.join(", ")}]. Contradictions: [${contradictorySignals.join("; ")}].`,requiredGates,satisfiedGates,missingGates,contradictorySignals,source:"durable_exact_task",generation:workflow.generation,nextAction:workflow.state==="rework_required"?"Delegate the same task to coder for repair, then rerun Stage A and Stage B.":"Complete the missing exact-task Stage A/Stage B transitions."},"required_gates_missing","block")}catch(error93){if(error93===legacyDirectCaller);else return reviewerGateDecision(taskId,sessionID,{blocked:!0,reason:`Evidence file for task ${taskId} is corrupt or unreadable: ${error93 instanceof Error?error93.message:String(error93)}. Call repair_gate_evidence for task ${taskId}; corrupt evidence fails closed until the repair completes.`,requiredGates:[],satisfiedGates:[],missingGates:["reviewer","test_engineer"],source:"durable_exact_task",corrupt:!0,nextAction:`Call repair_gate_evidence for task ${taskId}; corrupt evidence fails closed until the repair completes.`},"corrupt_evidence","data_quality")}}let resolvedDir;if(fallbackDir){let resolveResult=_internals117.resolveWorkingDirectory(workingDirectory,fallbackDir);if(resolveResult.success)resolvedDir=resolveResult.directory;else resolvedDir=fallbackDir}else if(workingDirectory)resolvedDir=workingDirectory;let routeAllowsStageB=(sessionId,_session)=>routeGateAllowsTask(resolvedDir,taskId,sessionId),evidenceIncompleteReason=null;try{if(!resolvedDir);else{let evidence2=_internals117.readTaskEvidenceRaw(resolvedDir,taskId);if(evidence2===null);else if(evidence2.required_gates&&Array.isArray(evidence2.required_gates)&&evidence2.gates){if(evidence2.required_gates.length>0&&evidence2.required_gates.every((gate)=>evidence2.gates[gate]!=null)){let routeSession=sessionID?swarmState.agentSessions.get(sessionID):void 0;if(!resolvedDir||routeAllowsStageB(sessionID,routeSession))return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:""},"durable_evidence_complete","genuine")}let missingGates=evidence2.required_gates.filter((gate)=>evidence2.gates[gate]==null);evidenceIncompleteReason=evidence2.required_gates.length===0?`Task ${taskId} has an evidence file with no required gates. Delegate reviewer and test_engineer before marking task as completed.`:`Task ${taskId} is missing required gates: [${missingGates.join(", ")}]. Required: [${evidence2.required_gates.join(", ")}]. Completed: [${Object.keys(evidence2.gates).join(", ")}]. Delegate the missing gate agents before marking task as completed.`}}}catch(error93){return log(`[gate-evidence] Evidence file for task ${taskId} is corrupt or unreadable:`,error93 instanceof Error?error93.message:String(error93)),telemetry.gateFailed("","qa_gate",taskId,"Evidence file corrupt or unreadable"),reviewerGateDecision(taskId,sessionID,{blocked:!0,reason:`Evidence file for task ${taskId} is corrupt or unreadable. Call repair_gate_evidence for task ${taskId}; corrupt evidence fails closed until the repair completes.`},"corrupt_evidence","data_quality")}if(swarmState.agentSessions.size===0&&!evidenceIncompleteReason)return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:""},"no_active_sessions","fallback");let validSessionCount=0;for(let[_sessionId,session]of swarmState.agentSessions){if(!(session.taskWorkflowStates instanceof Map))continue;validSessionCount++;let state2=getTaskState(session,taskId);if(state2==="tests_run"||state2==="complete"){if(resolvedDir&&!routeAllowsStageB(_sessionId,session))continue;return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:""},"workflow_state_complete","genuine")}if(stageBParallelEnabled&&hasBothStageBCompletions(session,taskId)&&(!resolvedDir||routeAllowsStageB(_sessionId,session)))return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:""},"stage_b_parallel_complete","genuine")}if(validSessionCount===0&&!evidenceIncompleteReason)return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:""},"zero_valid_sessions","data_quality");let stateEntries=[];for(let[sessionId,session]of swarmState.agentSessions){if(!(session.taskWorkflowStates instanceof Map))continue;let state2=getTaskState(session,taskId);stateEntries.push(`${sessionId}: ${state2}`)}if(resolvedDir)try{let planPath=path124.join(resolvedDir,".swarm","plan.json"),planRaw=fs79.readFileSync(planPath,"utf-8"),plan=JSON.parse(planRaw);for(let planPhase of plan.phases??[])for(let task of planPhase.tasks??[])if(task.id===taskId&&task.status==="completed"&&_internals117.hasPassedDurableGateEvidence(resolvedDir,taskId))return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:""},"restart_recovery_complete","genuine")}catch{}{let hasReviewer=!1,hasTestEngineer=!1;for(let[sessionId,chain]of swarmState.delegationChains){let session=swarmState.agentSessions.get(sessionId);if(session&&(session.currentTaskId===taskId||session.lastCoderDelegationTaskId===taskId))for(let delegation of chain){let target=stripKnownSwarmPrefix(delegation.to);if(target==="reviewer")hasReviewer=!0;if(target==="test_engineer")hasTestEngineer=!0}}if(hasReviewer&&hasTestEngineer)return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:""},"scoped_delegation_complete","genuine");if(!evidenceIncompleteReason&&(!hasReviewer||!hasTestEngineer)){for(let[sessionId,chain]of swarmState.delegationChains){if(chain.some((d)=>stripKnownSwarmPrefix(d.to)==="coder"))continue;let chainSession=swarmState.agentSessions.get(sessionId);if(chainSession){let chainTaskId=chainSession.currentTaskId||chainSession.lastCoderDelegationTaskId;if(chainTaskId&&chainTaskId!==taskId)continue}for(let delegation of chain){let target=stripKnownSwarmPrefix(delegation.to);if(target==="reviewer")hasReviewer=!0;if(target==="test_engineer")hasTestEngineer=!0}}if(hasReviewer&&hasTestEngineer)return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:""},"unscoped_delegation_complete","genuine")}}let currentStateStr=stateEntries.length>0?stateEntries.join(", "):"no active sessions",chainEntries=[];for(let[sessionId,chain]of swarmState.delegationChains){let session=swarmState.agentSessions.get(sessionId);if(session&&(session.currentTaskId===taskId||session.lastCoderDelegationTaskId===taskId)){let targets=chain.map((d)=>stripKnownSwarmPrefix(d.to));chainEntries.push(`${sessionId}: [${targets.join(", ")}]`)}}let chainSummary=chainEntries.length>0?chainEntries.join("; "):"no chains for this task",rehydratedSessionCount=[...swarmState.agentSessions.values()].filter((s)=>s.sessionRehydratedAt>0).length,finalReason=[`Task ${taskId} has not passed QA gates.`,` Session states: [${currentStateStr}].`,` Delegation chains: [${chainSummary}].`,` Evidence: [${evidenceIncompleteReason??"no evidence file found"}].`,` Rehydrated sessions: ${rehydratedSessionCount}.`," Missing required state: tests_run or complete."].join(`
|
|
1367
1367
|
`);return telemetry.gateFailed("","qa_gate",taskId,evidenceIncompleteReason?"Missing gates: evidence incomplete":"Missing state: tests_run or complete"),reviewerGateDecision(taskId,sessionID,{blocked:!0,reason:finalReason},"required_gates_missing","block")}catch{return reviewerGateDecision(taskId,sessionID,{blocked:!1,reason:""},"inspection_error","fallback")}}function hasForeignAttributionRecord(taskId,checkingSessionId){try{let checkerProject=swarmState.agentSessions.get(checkingSessionId)?.owningProjectKey??null;for(let[sessionId,session]of swarmState.agentSessions){if(sessionId===checkingSessionId)continue;if(!(session.modifiedFilesByTask instanceof Map))continue;if((session.owningProjectKey??null)!==checkerProject)continue;let entry=session.modifiedFilesByTask.get(taskId);if(Array.isArray(entry)&&entry.length>0)return!0}return!1}catch{return!1}}async function checkReviewerGateWithScope(taskId,workingDirectory,sessionID,fallbackDir){let result=checkReviewerGate(taskId,workingDirectory,!0,sessionID,fallbackDir),session=sessionID?getAgentSession(sessionID):void 0,attributedFiles=session?getModifiedFilesForTask(session,taskId):[],scopeAdvisoryLine=!!sessionID&&!hasModifiedFilesForTask(session,taskId)&&!!workingDirectory&&hasDeclaredDiffScope(taskId,workingDirectory)?hasForeignAttributionRecord(taskId,sessionID)?`SCOPE ADVISORY: attribution record for task ${taskId} exists under another session — not used for scope verification`:"SCOPE ADVISORY: no attribution record in this session — not used for scope verification":null,scopeWarning=await validateDiffScope(taskId,workingDirectory,sessionID&&attributedFiles.length>0?{attributedFiles}:void 0).catch(()=>null);if(!scopeWarning&&!scopeAdvisoryLine)return result;return{...result,reason:[result.reason,scopeWarning,scopeAdvisoryLine].filter((part)=>typeof part==="string"&&part.length>0).join(`
|
|
1368
1368
|
`)}}function recoverTaskStateFromDelegations(taskId,directory){let hasReviewer=!1,hasTestEngineer=!1;for(let[sessionId,chain]of swarmState.delegationChains){let session=swarmState.agentSessions.get(sessionId);if(session&&(session.currentTaskId===taskId||session.lastCoderDelegationTaskId===taskId))for(let delegation of chain){let target=stripKnownSwarmPrefix(delegation.to);if(target==="reviewer")hasReviewer=!0;if(target==="test_engineer")hasTestEngineer=!0}}let hasDurableIncompleteGates=!1;if(directory)try{let taskEvidence=readTaskEvidenceRaw(directory,taskId);if(taskEvidence?.gates&&Array.isArray(taskEvidence.required_gates)&&taskEvidence.required_gates.length>0){let gates=taskEvidence.gates;hasDurableIncompleteGates=taskEvidence.required_gates.some((g)=>gates[g]==null)}}catch{hasDurableIncompleteGates=!0}if(!hasDurableIncompleteGates&&(!hasReviewer||!hasTestEngineer))for(let[sessionId,chain]of swarmState.delegationChains){if(chain.some((d)=>stripKnownSwarmPrefix(d.to)==="coder"))continue;let chainSession=swarmState.agentSessions.get(sessionId);if(chainSession){let chainTaskId=chainSession.currentTaskId||chainSession.lastCoderDelegationTaskId;if(chainTaskId&&chainTaskId!==taskId)continue}for(let delegation of chain){let target=stripKnownSwarmPrefix(delegation.to);if(target==="reviewer")hasReviewer=!0;if(target==="test_engineer")hasTestEngineer=!0}}if((!hasReviewer||!hasTestEngineer)&&directory)try{let evidence2=readTaskEvidenceRaw(directory,taskId);if(evidence2?.gates&&Array.isArray(evidence2.required_gates)){if(evidence2.gates.reviewer!=null)hasReviewer=!0;if(evidence2.gates.test_engineer!=null)hasTestEngineer=!0}}catch{}if(!hasReviewer&&!hasTestEngineer)return;if(swarmState.agentSessions.size===0)try{startAgentSession("recovery-session","architect")}catch{}let recoveryRouteEnforcementEnabled=directory?(()=>{try{return loadPluginConfig(directory).review_routing?.enforce_receipts??!0}catch{return!0}})():!1;for(let[sessionId,session]of swarmState.agentSessions){if(!(session.taskWorkflowStates instanceof Map))continue;let routeEvidence=(()=>{let live=getStageBRouteEvidence(session,taskId);if(live.length>0)return live;try{return routeEvidenceFromTaskGateRequirements(readTaskGateRequirementsReceiptsSync(directory,taskId))}catch{return[]}})(),routeRequired=isStageBRouteRequired(session,taskId)||routeEvidence.length>0;if(directory&&recoveryRouteEnforcementEnabled&&routeRequired&&!enforcePersistedReviewRouteReceipt({projectRoot:directory,sessionId,taskId,receipts:routeEvidence,enforcementEnabled:!0,legacyUnrouted:(()=>{try{return!isStageBRouteRequired(session,taskId)&&isLegacyTaskGateRequirementsChain(readTaskGateRequirementsReceiptsSync(directory,taskId))}catch{return!1}})(),requireEvidenceBindings:!0}).canAdvance)continue;let currentState=getTaskState(session,taskId);if(currentState==="tests_run"||currentState==="complete")continue;if(hasReviewer&¤tState==="idle")try{advanceTaskState(session,taskId,"coder_delegated")}catch{}if(hasReviewer)recordStageBCompletion(session,taskId,"reviewer");if(hasTestEngineer)recordStageBCompletion(session,taskId,"test_engineer");if(hasReviewer){let stateNow=getTaskState(session,taskId);if(stateNow==="coder_delegated"||stateNow==="pre_check_passed")try{advanceTaskState(session,taskId,"reviewer_run")}catch{}}if(hasTestEngineer){if(getTaskState(session,taskId)==="reviewer_run")try{advanceTaskState(session,taskId,"tests_run")}catch{}}}}function checkCouncilGate(workingDirectory,taskId){let councilEnabled=!1,effectiveMinimum=3;try{let config3=loadPluginConfig(workingDirectory);councilEnabled=config3.council?.enabled===!0,effectiveMinimum=config3.council?.requireAllMembers?5:config3.council?.minimumMembers??3}catch{return{blocked:!1,reason:"",active:!1}}if(!councilEnabled)return{blocked:!1,reason:"",active:!1};try{let planPath=path124.join(workingDirectory,".swarm","plan.json"),planRaw=fs79.readFileSync(planPath,"utf-8"),planObj=JSON.parse(planRaw);if(planObj.swarm&&planObj.title){let lookup=getProfileLookupForIdentity(workingDirectory,planObj);if(lookup.kind==="bound"){if(!lookup.profile.gates.council_mode)return{blocked:!1,reason:"",active:!1}}else if(lookup.kind==="unbound_legacy"){if(lookup.profile.gates.council_mode)return{blocked:!0,reason:`council gate required but the QA gate profile is not exact-bound to the current raw swarm_id/plan_title. ${formatLegacyQaBindingRecovery({swarm:planObj.swarm,title:planObj.title},"retry advancing this task")}`,active:!0};return{blocked:!1,reason:"",active:!1}}else return{blocked:!1,reason:"",active:!1}}}catch{return{blocked:!1,reason:"",active:!1}}let evidence2;try{evidence2=readTaskEvidenceRaw(workingDirectory,taskId)}catch{return{blocked:!0,reason:"council gate required but not yet run — architect must call submit_council_verdicts before advancing this task",active:!0}}let councilGate=evidence2?.gates?.council;if(!councilGate)return{blocked:!0,reason:"council gate required but not yet run — architect must call submit_council_verdicts before advancing this task",active:!0};let councilWorkflow=getTaskWorkflowSnapshot(evidence2);if(!councilWorkflow.authoritative||councilWorkflow.state!=="pre_check_passed"||councilGate.workflowGeneration!==councilWorkflow.generation)return{blocked:!0,reason:`council gate evidence is stale or unbound: expected pre_check_passed@${councilWorkflow.generation}, recorded generation ${String(councilGate.workflowGeneration)}`,active:!0};if(councilGate.verdict==="REJECT")return{blocked:!0,reason:"council gate blocked advancement — resolve requiredFixes and re-run submit_council_verdicts",active:!0};let rawQuorumSize=councilGate.quorumSize,quorumSize=typeof rawQuorumSize==="number"&&Number.isFinite(rawQuorumSize)&&rawQuorumSize>=1?rawQuorumSize:1;if(quorumSize<effectiveMinimum)return{blocked:!0,reason:`council gate blocked advancement — recorded verdict has insufficient quorum (${quorumSize} of ${effectiveMinimum} required members). Re-run submit_council_verdicts with the missing council members.`,active:!0};return{blocked:!1,reason:"",active:!0}}async function executeUpdateTaskStatus(args2,fallbackDir,ctx){let statusError=validateStatus(args2.status);if(statusError)return{success:!1,message:"Validation failed",errors:[statusError]};let taskIdError=validateTaskId(args2.task_id);if(taskIdError)return{success:!1,message:"Validation failed",errors:[taskIdError]};let directory,resolveResult=_internals117.resolveWorkingDirectory(args2.working_directory,fallbackDir);if(!resolveResult.success)return{success:!1,message:resolveResult.message,errors:[resolveResult.message]};directory=resolveResult.directory;try{assertProjectRoot(directory)}catch(error93){let message=error93 instanceof Error?error93.message:String(error93);return{success:!1,message,errors:[message]}}let planPath=path124.join(directory,".swarm","plan.json");if(!fs79.existsSync(planPath))return{success:!1,message:`Invalid working_directory: plan not found in "${directory}"`,errors:[`Invalid working_directory: plan not found in "${directory}"`]};if(fallbackDir&&directory!==fallbackDir){let canonicalDir=fs79.realpathSync(path124.resolve(directory)),canonicalRoot=fs79.realpathSync(path124.resolve(fallbackDir));if(isStrictPathDescendant(canonicalDir,canonicalRoot)&&!hasExplicitProjectBoundary(canonicalDir))return{success:!1,message:`Invalid working_directory: "${directory}" is a subdirectory of the project root "${fallbackDir}". Pass the project root path or omit working_directory entirely.`,errors:[`Subdirectory rejected: use project root "${fallbackDir}" instead`]}}let exactRepairRetry=!1;if(isRepairRetryShape(args2))try{let repairWal=await readWorkflowWalFile("task-repair",validateSwarmPath(directory,`task-repairs/${args2.task_id}.json`),args2.task_id);exactRepairRetry=repairWal?.state==="PREPARED"&&repairWal.transitionId===args2.transition_id}catch(error93){return{success:!1,message:"Task operation paused while recovering an interrupted task repair",errors:[error93 instanceof Error?error93.message:String(error93)]}}try{let recoveredCoder=await recoverCoderSettlement(directory,args2.task_id);if(recoveredCoder&&ctx?.sessionID){let callerSession=ensureAgentSession(ctx.sessionID),workflow=getTaskWorkflowSnapshot(recoveredCoder.evidence);callerSession.taskWorkflowStates.set(args2.task_id,workflow.state),callerSession.stageBCompletion?.delete(args2.task_id),updateTaskWorkflowCache(callerSession,args2.task_id,workflow)}}catch(error93){return{success:!1,message:"Task operation paused while recovering an interrupted coder settlement",errors:[error93 instanceof Error?error93.message:String(error93)]}}try{let recoveredTerminal=await recoverPreparedTaskTerminal(directory,args2.task_id,ctx?.sessionID??"update-task-status");if(recoveredTerminal)syncCallerWorkflowFromEvidence(ctx?.sessionID,args2.task_id,recoveredTerminal.evidence)}catch(error93){return{success:!1,message:"Task operation paused while recovering an interrupted terminal status transition",errors:[error93 instanceof Error?error93.message:String(error93)]}}if(!exactRepairRetry)try{if(await recoverPreparedTaskRepair(directory,args2.task_id,ctx?.sessionID??"update-task-status"))syncCallerWorkflowFromEvidence(ctx?.sessionID,args2.task_id,readTaskEvidenceRaw(directory,args2.task_id))}catch(error93){if(error93 instanceof Error&&error93.message.startsWith("TASK_REPAIR_AUDIT_LOCKED"))criticalWarn(`[update-task-status] task-repair audit recovery deferred for ${args2.task_id}: ${error93.message}`);else return{success:!1,message:"Task operation paused while recovering an interrupted task repair",errors:[error93 instanceof Error?error93.message:String(error93)]}}let loadedPlan=null;try{loadedPlan=await _internals117.loadPlan(directory)}catch(error93){return{success:!1,message:"Failed to load plan for task validation",errors:[error93 instanceof Error?error93.message:String(error93)]}}if(!loadedPlan)return{success:!1,message:"Failed to load plan for task validation",errors:["Plan could not be loaded"]};if(loadedPlan._ledgerReplayStale===!0){let staleReason=loadedPlan._ledgerReplayStaleReason??"plan.json is stale relative to the active plan-ledger authority";return{success:!1,message:`Task status update refused: plan.json is stale relative to the ledger (ledger replay failed). ${staleReason}`,errors:[staleReason],recovery_guidance:"Plan state could not be reconciled with the active plan-ledger authority. Retry save_plan with the unchanged loaded plan so it can reconverge the projections and authority metadata, then retry update_task_status."}}let currentTask=loadedPlan.phases.flatMap((phase)=>phase.tasks).find((task)=>task.id===args2.task_id);if(!currentTask)return{success:!1,message:"Failed to update task status",errors:[`Task not found: ${args2.task_id}`]};{let settledRejection=getSettledTransitionRejection(args2.task_id,currentTask.status,args2.status,args2.force);if(settledRejection)return settledRejection}if(args2.status==="in_progress"&&args2.force===!0){if(!(typeof args2.expected_state==="string"&&args2.expected_state.length>0&&Number.isInteger(args2.expected_generation)&&(args2.expected_generation??-1)>=0&&args2.target_state==="idle"&&typeof args2.reason==="string"&&args2.reason.trim().length>0&&args2.reason.length<=2000&&typeof args2.transition_id==="string"&&args2.transition_id.trim().length>0&&args2.transition_id.length<=200))return{success:!1,message:"TASK_REPAIR_INVALID: force repair requires an exact CAS and audit identity",errors:['Provide expected_state, expected_generation, target_state="idle", a non-empty reason (max 2000 chars), and a non-empty transition_id (max 200 chars).']};log(`[update-task-status] Force-override: attempting audited repair for task ${args2.task_id} (settled task, or in_progress at the retry-escalation rung per issue #3389; admission is verified under the plan lock) to in_progress`)}let agentName=(ctx?.sessionID?swarmState.activeAgent.get(ctx.sessionID):void 0)??"update-task-status",scopeAdvisories;if(args2.status==="completed"){if(!fallbackDir&&!ctx?.sessionID)recoverTaskStateFromDelegations(args2.task_id,directory);let phaseRequiresReviewer=!0,taskDeclaresExternalEvidence=!1;try{let planPath2=path124.join(directory,".swarm","plan.json"),planRaw=fs79.readFileSync(planPath2,"utf-8"),taskPhase=JSON.parse(planRaw).phases.find((p)=>p.tasks.some((t)=>t.id===args2.task_id));if(taskPhase?.required_agents&&!taskPhase.required_agents.includes("reviewer"))phaseRequiresReviewer=!1;taskDeclaresExternalEvidence=taskPhase?.tasks.find((t)=>t.id===args2.task_id)?.evidence_class==="external_git"}catch{}let councilCheck=taskDeclaresExternalEvidence?{blocked:!1,active:!1}:checkCouncilGate(directory,args2.task_id);if(councilCheck.blocked)return await recordRunMemoryOutcome(directory,{taskId:args2.task_id,agent:agentName,outcome:"fail",failureReason:`council gate: ${councilCheck.reason}`,fileTargets:resolveRunMemoryFileTargets(loadedPlan,args2.task_id)}),{success:!1,message:"Gate check failed: council gate not yet satisfied for task "+args2.task_id,errors:[councilCheck.reason]};if(phaseRequiresReviewer&&!councilCheck.active&&!taskDeclaresExternalEvidence){let reviewerCheck=await checkReviewerGateWithScope(args2.task_id,directory,ctx?.sessionID,ctx?.sessionID?fallbackDir:void 0);if(reviewerCheck.reason){let advisoryLines=reviewerCheck.reason.split(`
|
|
1369
1369
|
`).filter((line)=>line.length>0);if(advisoryLines.length>0)scopeAdvisories=advisoryLines}if(reviewerCheck.blocked)return await recordRunMemoryOutcome(directory,{taskId:args2.task_id,agent:agentName,outcome:"fail",failureReason:`QA gate: ${reviewerCheck.reason}`,fileTargets:resolveRunMemoryFileTargets(loadedPlan,args2.task_id)}),{success:!1,message:"Gate check failed: required QA gates not yet satisfied for task "+args2.task_id,errors:[reviewerCheck.reason]}}}let lockTaskId=`update-task-status-${args2.task_id}-${Date.now()}`,planFilePath="plan.json",lockResult;try{lockResult=await _internals117.tryAcquireLock(directory,planFilePath,agentName,lockTaskId)}catch(error93){return{success:!1,message:"Failed to acquire lock for task status update",errors:[error93 instanceof Error?error93.message:String(error93)]}}if(!lockResult.acquired)return{success:!1,message:`Task status write blocked: plan.json is locked by ${lockResult.existing?.agent??"another agent"} (task: ${lockResult.existing?.taskId??"unknown"})`,errors:["Concurrent plan write detected — retry after the current write completes"],recovery_guidance:"Wait a moment and retry update_task_status. The lock will expire automatically if the holding agent fails."};try{let lockedPlan=await _internals117.loadPlan(directory);if(lockedPlan?._ledgerReplayStale===!0)return{success:!1,message:"Task status update refused: plan became ledger-stale while waiting for the lock",errors:[lockedPlan._ledgerReplayStaleReason??"plan.json is stale relative to the authoritative ledger"],recovery_guidance:"Retry save_plan with the unchanged loaded plan to reconverge the projection/hash, then retry update_task_status."};if(!lockedPlan)return{success:!1,message:"Failed to update task status",errors:["No approved plan is available under the plan lock"]};let authoritativePlan=lockedPlan,lockedPreparedRepairWal=await readPreparedWorkflowWal(directory,args2.task_id,"task-repair"),lockedExactRepairRetry=isRepairRetryShape(args2)&&lockedPreparedRepairWal?.transitionId===args2.transition_id;if(lockedPreparedRepairWal&&!lockedExactRepairRetry)try{let recoveredRepair=await recoverPreparedTaskRepairUnderPlanLock(directory,args2.task_id,ctx?.sessionID??"update-task-status",authoritativePlan);if(recoveredRepair)authoritativePlan=recoveredRepair.plan,syncCallerWorkflowFromEvidence(ctx?.sessionID,args2.task_id,readTaskEvidenceRaw(directory,args2.task_id))}catch(error93){if(error93 instanceof Error&&error93.message.startsWith("TASK_REPAIR_AUDIT_LOCKED"))criticalWarn(`[update-task-status] task-repair audit recovery deferred for ${args2.task_id}: ${error93.message}`);else return{success:!1,message:"Task operation paused while recovering an interrupted task repair",errors:[error93 instanceof Error?error93.message:String(error93)]}}if(await hasPreparedWorkflowWal(directory,args2.task_id,"task-terminal"))try{let recoveredTerminal=await recoverPreparedTaskTerminalUnderPlanLock(directory,args2.task_id,ctx?.sessionID??"update-task-status",authoritativePlan);if(recoveredTerminal)authoritativePlan=recoveredTerminal.plan,syncCallerWorkflowFromEvidence(ctx?.sessionID,args2.task_id,recoveredTerminal.evidence)}catch(error93){return{success:!1,message:"Task operation paused while recovering an interrupted terminal status transition",errors:[error93 instanceof Error?error93.message:String(error93)]}}let lockedTask=authoritativePlan.phases.flatMap((phase)=>phase.tasks).find((task)=>task.id===args2.task_id);if(!lockedTask)return{success:!1,message:"Failed to update task status",errors:[`Task not found: ${args2.task_id}`]};let lockedSettledRejection=getSettledTransitionRejection(args2.task_id,lockedTask.status,args2.status,args2.force);if(lockedSettledRejection)return lockedSettledRejection;let repairResult=args2.status==="in_progress"&&args2.force===!0?await repairTaskWorkflowUnderPlanLock({directory,taskId:args2.task_id,actor:agentName,reason:args2.reason,transitionId:args2.transition_id,expectedState:args2.expected_state,expectedGeneration:args2.expected_generation,currentPlanStatus:lockedTask.status,currentPlan:authoritativePlan,updatePlan:()=>_internals117.updateTaskStatus(directory,args2.task_id,"in_progress",{force:!0,planLockAlreadyHeld:!0})}):null,updatedPlan,terminalEvidence=null;if(args2.status==="completed"){let lockedTaskPhase=authoritativePlan.phases.find((phase)=>phase.tasks.some((task)=>task.id===args2.task_id)),lockedPhaseRequiresReviewer=!lockedTaskPhase?.required_agents||lockedTaskPhase.required_agents.includes("reviewer"),lockedTaskDeclaresExternal=lockedTask.evidence_class==="external_git",terminalResult=await commitTaskTerminalUnderPlanLock({directory,taskId:args2.task_id,actor:agentName,transitionId:`plan-status:${args2.task_id}:completed:${Date.now()}`,currentPlanStatus:lockedTask.status,targetStatus:"completed",qaExempt:!lockedPhaseRequiresReviewer&&!lockedTaskDeclaresExternal,resolveTerminal:(evidence2)=>({targetStatus:"completed",qaExempt:!lockedPhaseRequiresReviewer&&!lockedTaskDeclaresExternal,readOnlyNoMutation:!lockedPhaseRequiresReviewer?!1:isReadOnlyNoMutationEligible(evidence2,{currentDeclaredFiles:lockedTask.files_touched}),externalEvidence:lockedTaskDeclaresExternal}),currentPlan:authoritativePlan,validateEvidence:async()=>{if(lockedTaskDeclaresExternal){let externalTaskEvidence=_internals117.readTaskEvidenceRaw(directory,args2.task_id),planIdentity={title:authoritativePlan.title,swarm:authoritativePlan.swarm},externalWorkflow=getTaskWorkflowSnapshot(externalTaskEvidence);if(!isExternalEvidenceInitialCompletionEligible(planIdentity,lockedTask,externalTaskEvidence)&&!(externalWorkflow.state==="complete"&&externalProofCurrent(planIdentity,lockedTask,externalTaskEvidence)))throw Error(`TASK_COMPLETION_CAS_MISMATCH: Task ${args2.task_id} declares external_git evidence but has no current matched attestation; run /swarm attest ${args2.task_id} first`);return}let lockedGate=checkReviewerGate(args2.task_id,directory,!1,ctx?.sessionID,fallbackDir??directory,lockedTask.files_touched??null),lockedCouncil=checkCouncilGate(directory,args2.task_id);if(lockedCouncil.blocked||lockedPhaseRequiresReviewer&&!lockedCouncil.active&&lockedGate.blocked)throw Error(`TASK_COMPLETION_CAS_MISMATCH: ${lockedCouncil.blocked?lockedCouncil.reason:lockedGate.reason}`)},updatePlan:async()=>{let next=await _internals117.updateTaskStatus(directory,args2.task_id,"completed",{force:!1,planLockAlreadyHeld:!0});if(next.phases.flatMap((phase)=>phase.tasks).find((task)=>task.id===args2.task_id)?.status!=="completed")throw Error("TASK_STATUS_WRITE_NOT_APPLIED");return next}});updatedPlan=terminalResult.plan,terminalEvidence=terminalResult.evidence}else if(args2.status==="blocked"){let terminalResult=await commitTaskTerminalUnderPlanLock({directory,taskId:args2.task_id,actor:agentName,transitionId:`plan-status:${args2.task_id}:blocked:${Date.now()}`,currentPlanStatus:lockedTask.status,targetStatus:"blocked",qaExempt:!1,currentPlan:authoritativePlan,updatePlan:async()=>{let next=await _internals117.updateTaskStatus(directory,args2.task_id,"blocked",{force:!1,planLockAlreadyHeld:!0});if(next.phases.flatMap((phase)=>phase.tasks).find((task)=>task.id===args2.task_id)?.status!=="blocked")throw Error("TASK_STATUS_WRITE_NOT_APPLIED");return next}});updatedPlan=terminalResult.plan,terminalEvidence=terminalResult.evidence}else if(updatedPlan=repairResult?.plan??await _internals117.updateTaskStatus(directory,args2.task_id,args2.status,{force:!1,planLockAlreadyHeld:!0}),updatedPlan.phases.flatMap((phase)=>phase.tasks).find((task)=>task.id===args2.task_id)?.status!==args2.status)throw Error("TASK_STATUS_WRITE_NOT_APPLIED");if(terminalEvidence){let terminal=getTaskWorkflowSnapshot(terminalEvidence),callerSession=ctx?.sessionID?swarmState.agentSessions.get(ctx.sessionID):void 0;if(callerSession){let session=callerSession;session.taskWorkflowStates.set(args2.task_id,terminal.state),session.stageBCompletion?.delete(args2.task_id),updateTaskWorkflowCache(session,args2.task_id,terminal)}}if(args2.status==="in_progress"){if(ctx?.sessionID)ensureAgentSession(ctx.sessionID).currentTaskId=args2.task_id;if(repairResult){let callerSession=ctx?.sessionID?swarmState.agentSessions.get(ctx.sessionID):void 0;if(callerSession){let session=callerSession;session.taskWorkflowStates.set(args2.task_id,"idle"),session.stageBCompletion?.delete(args2.task_id),session.taskCouncilApproved?.delete(args2.task_id),session.taskCouncilWorkflowGeneration?.delete(args2.task_id),updateTaskWorkflowCache(session,args2.task_id,{generation:repairResult.generation})}}}return{success:!0,message:"Task status updated successfully",task_id:args2.task_id,new_status:args2.status,current_phase:updatedPlan.current_phase,...scopeAdvisories&&scopeAdvisories.length>0?{warnings:scopeAdvisories}:{}}}catch(error93){return{success:!1,message:"Failed to update task status",errors:[error93 instanceof Error?error93.message:String(error93)]}}finally{if(lockResult?.acquired&&lockResult.lock._release)try{await lockResult.lock._release()}catch(releaseError){log("[update-task-status] Lock release failed:",releaseError)}}}var _internals117,VALID_STATUSES,update_task_status;var init_update_task_status=__esm(()=>{init_zod();init_loader();init_schema();init_qa_gate_profile();init_task_gate_requirements();init_gate_evidence();init_diff_scope();init_utils2();init_file_locks();init_tier3_classifier();init_manager();init_routing_enforcement();init_run_memory();init_state();init_telemetry();init_task_completion();init_logger();init_project_boundary();init_task_id();init_coder_settlement();init_session_view();init_task_repair();init_task_terminal();init_workflow_wal_file();init_create_tool();init_resolve_working_directory();_internals117={tryAcquireLock,updateTaskStatus,resolveWorkingDirectory,loadPlan,readTaskEvidenceRaw,hasActiveLeanTurbo,hasActiveTurboMode,verifyLeanTurboTaskCompletion,hasPassedDurableGateEvidence,emitReviewerGateDecision:telemetry.reviewerGateDecision,recordTaskAttempt};VALID_STATUSES=["pending","in_progress","completed","blocked"];update_task_status=createSwarmTool({description:"Update the status of a specific task in the implementation plan. Task status can be one of: pending, in_progress, completed, blocked.",args:{task_id:exports_external.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/,"Task ID must be in N.M or N.M.P format").describe('Task ID in N.M format, e.g. "1.1", "1.2.3"'),status:exports_external.enum(["pending","in_progress","completed","blocked"]).describe("New status for the task: pending, in_progress, completed, or blocked"),working_directory:exports_external.string().optional().describe("Working directory where the plan is located"),force:exports_external.boolean().optional().default(!1).describe('Enable the audited repair contract: re-open a settled task, or an in_progress task that reached the retry ladder user_escalation rung (issue #3389). Requires expected_state, expected_generation, target_state="idle", reason, and transition_id.'),expected_state:exports_external.string().optional().describe("CAS workflow state expected by a force repair."),expected_generation:exports_external.number().int().min(0).optional().describe("ABA-safe workflow generation expected by a force repair."),target_state:exports_external.literal("idle").optional().describe("Repair target state. The only valid target is idle (re-opens the task for new work)."),reason:exports_external.string().min(1).max(2000).optional().describe("Required human-readable audit reason for a force repair."),transition_id:exports_external.string().min(1).max(200).optional().describe("Caller-generated idempotency key for an audited force repair.")},execute:async(args2,_directory2,_ctx)=>{return JSON.stringify(await executeUpdateTaskStatus(args2,_directory2,_ctx),null,2)}})});var exports_attest_task={};__export(exports_attest_task,{executeAttestTask:()=>executeAttestTask,buildAnchorArgv:()=>buildAnchorArgv,_internals:()=>_internals118});import*as fs80 from"node:fs";import*as path125 from"node:path";function anchorEnv(){let env={PATH:process.env.PATH,HOME:process.env.HOME,LANG:process.env.LANG,LC_ALL:process.env.LC_ALL,GIT_CONFIG_NOSYSTEM:"1"};if(process.platform==="win32")env.SYSTEMROOT=process.env.SYSTEMROOT,env.WINDIR=process.env.WINDIR,env.COMSPEC=process.env.COMSPEC;return{env,envOverrides:{GIT_EXTERNAL_DIFF:null,GIT_CONFIG_PARAMETERS:null,GIT_CONFIG_COUNT:null,GIT_DIR:null,GIT_WORK_TREE:null,GIT_INDEX_FILE:null,GIT_SSH_COMMAND:null,GIT_ASKPASS:null,GIT_EXEC_PATH:null,GIT_PAGER:null}}}function buildAnchorArgv(command){let tokens2=command.trim().split(/\s+/).filter(Boolean);if(tokens2[0]!=="git"||tokens2.length<2)return{argv:null,refusal:`anchor command is not an allowed read-only git invocation: "${command}"`};let subcommand=tokens2[1];if(subcommand.startsWith("-"))return{argv:null,refusal:`anchor command smuggles a git global option ("${subcommand}"); only bare read-only git subcommands are allowed`};let allowed=READ_ONLY_GIT_FLAGS[subcommand];if(!allowed)return{argv:null,refusal:`git "${subcommand}" is not in the read-only git subcommand allowlist (rev-list, log, rev-parse, show, diff)`};let finalTokens=[subcommand];for(let i=2;i<tokens2.length;i++){let token=tokens2[i];if(token.startsWith("-")){let eq=token.indexOf("="),flag=eq>=0?token.slice(0,eq):token,inlineValue=eq>=0?token.slice(eq+1):void 0,arity2=allowed[flag];if(arity2===void 0)return{argv:null,refusal:`flag "${flag}" is not in the read-only git allowlist for git ${subcommand}`};if(arity2===0){if(inlineValue!==void 0)return{argv:null,refusal:`flag "${flag}" takes no value; =-joined forms are not valid for it`};finalTokens.push(flag)}else{let value=inlineValue;if(value===void 0){let next=tokens2[i+1];if(next===void 0||next.startsWith("--"))return{argv:null,refusal:`flag "${flag}" requires a value token`};value=next,i++}finalTokens.push(flag.startsWith("--")?`${flag}=${value}`:`${flag}${value}`)}continue}let hasControlByte=Array.from(token).some((ch)=>ch.charCodeAt(0)<32||ch.charCodeAt(0)===127);if(token.length>400||hasControlByte)return{argv:null,refusal:"anchor argument is too long or contains control bytes"};if(REMOTE_HELPER_PATTERN.test(token))return{argv:null,refusal:`anchor argument "${token.slice(0,32)}" looks like a remote-helper URL; remote helpers can execute commands and are not read-only git invocations`};finalTokens.push(token)}if(subcommand==="diff"||subcommand==="show"||subcommand==="log")finalTokens.push("--no-ext-diff","--no-textconv");return{argv:[resolveGitExecutable(),"--no-pager","-c","diff.external=","-c","core.pager=cat","-c","core.fsmonitor=","-c","gpg.program=","-c","credential.helper=",...finalTokens],refusal:null}}async function runAnchor(argv,cwd,timeoutMs){let{env,envOverrides}=anchorEnv(),proc=bunSpawn(argv,{cwd,env,envOverrides,stdin:"ignore",stdout:"pipe",stderr:"pipe",timeout:timeoutMs,maxBuffer:ANCHOR_SPAWN_MAX_BUFFER_BYTES});try{let exited=await proc.exited,stdout;try{stdout=await proc.stdout.text()}catch{return{exitCode:exited,stdout:"",refusal:`anchor output exceeded the ${Math.floor(ANCHOR_SPAWN_MAX_BUFFER_BYTES/1024)}KB spawn capture buffer; refusing rather than truncating`}}if(exited!==0){let detail=(await proc.stderr.text()).trim().slice(0,200);return{exitCode:exited,stdout,refusal:`anchor command exited with code ${exited}${detail?`: ${detail}`:""}`}}return{exitCode:exited,stdout,refusal:null}}finally{try{proc.kill()}catch{}}}function validateAnchorExpectations(anchors){for(let anchor of anchors){if(anchor.expect===void 0&&anchor.expect_prefix===void 0)return`anchor "${anchor.command.slice(0,60)}" declares neither expect nor expect_prefix`;if(anchor.expect_prefix!==void 0&&anchor.expect_prefix.length===0)return`anchor "${anchor.command.slice(0,60)}" declares an empty expect_prefix, which would match any output`}return null}async function executeAttestTask(args2,fallbackDir){let resolveResult=_internals117.resolveWorkingDirectory(args2.working_directory,fallbackDir);if(!resolveResult.success)return{success:!1,message:resolveResult.message,errors:[resolveResult.message]};let directory=resolveResult.directory;try{assertProjectRoot(directory)}catch(error93){let message=error93 instanceof Error?error93.message:String(error93);return{success:!1,message,errors:[message]}}let found;try{found=_internals118.loadPlanTask(directory,args2.task_id)}catch(error93){let message=error93 instanceof Error?error93.message:String(error93);if(message.includes("expect_prefix")||message.includes("evidence_anchors"))return{success:!1,message:"the plan declares an invalid external-evidence anchor: every anchor must carry expect and/or a non-empty expect_prefix (an empty prefix would match any output)",errors:["the plan declares an invalid external-evidence anchor: every anchor must carry expect and/or a non-empty expect_prefix (an empty prefix would match any output)"],task_id:args2.task_id};let refusal=`the plan at ${directory} is invalid or unreadable; fix or re-save the plan before attesting`;return{success:!1,message:refusal,errors:[`${refusal} (${message.slice(0,160)})`],task_id:args2.task_id}}if(!found){let message=`Task ${args2.task_id} not found in the plan at ${directory}`;return{success:!1,message,errors:[message],task_id:args2.task_id}}if(found.task.evidence_class!=="external_git"){let message=`Task ${args2.task_id} does not declare evidence_class external_git; the attest path is fail-closed to explicitly declared external-evidence tasks (issue #3422)`;return{success:!1,message,errors:[message],task_id:args2.task_id}}let anchors=found.task.evidence_anchors??[];if(anchors.length===0){let message=`Task ${args2.task_id} declares external_git evidence but pins no evidence_anchors`;return{success:!1,message,errors:[message],task_id:args2.task_id}}let malformed=validateAnchorExpectations(anchors);if(malformed)return{success:!1,message:malformed,errors:[malformed],task_id:args2.task_id};let startedAt=Date.now(),outcomes=[];for(let anchor of anchors){let{argv,refusal}=_internals118.buildAnchorArgv(anchor.command);if(refusal!==null||argv===null){let message=`anchor not admitted: ${refusal??"not an allowed read-only git invocation"}`;return{success:!1,message,errors:[message],task_id:args2.task_id}}let remaining=ATTEST_TOTAL_DEADLINE_MS-(Date.now()-startedAt);if(remaining<=0)return{success:!1,message:"attest total deadline (30s) exhausted before all anchors ran",errors:["attest total deadline (30s) exhausted before all anchors ran"],task_id:args2.task_id};let run=await _internals118.runAnchor(argv,directory,Math.min(ANCHOR_SPAWN_TIMEOUT_MS,remaining));if(run.refusal!==null){let message=`anchor "${anchor.command.slice(0,60)}" failed: ${run.refusal}`;return{success:!1,message,errors:[message],task_id:args2.task_id}}if(run.stdout.length>ANCHOR_STDOUT_MAX_CHARS){let message=`anchor "${anchor.command.slice(0,60)}" produced ${run.stdout.length} chars of stdout, exceeding the ${ANCHOR_STDOUT_MAX_CHARS}-char evidence storage bound; refusing rather than truncating`;return{success:!1,message,errors:[message],task_id:args2.task_id}}let trimmed=run.stdout.trim(),matched=anchor.expect!==void 0?trimmed===anchor.expect&&(anchor.expect_prefix===void 0||trimmed.startsWith(anchor.expect_prefix)):trimmed.startsWith(anchor.expect_prefix);outcomes.push({command:anchor.command,expect:anchor.expect,expect_prefix:anchor.expect_prefix,matched,exit_code:run.exitCode,stdout:run.stdout})}if(!outcomes.every((outcome)=>outcome.matched)){let failed=outcomes.find((outcome)=>!outcome.matched),message=`anchor "${failed?.command.slice(0,60)??"?"}" did not match its expectation (stdout: ${JSON.stringify(failed?.stdout.slice(0,120)??"")})`;return{success:!1,message,errors:[message],task_id:args2.task_id}}let current;try{current=_internals118.loadPlanTask(directory,args2.task_id)}catch{return{success:!1,message:"the plan became unreadable while anchors were running; re-run attest against the current declaration",errors:["the plan became unreadable while anchors were running; re-run attest against the current declaration"],task_id:args2.task_id}}let anchorsUnchanged=JSON.stringify(current?.task.evidence_anchors??null)===JSON.stringify(anchors);if(!current||current.task.evidence_class!=="external_git"||current.title!==found.title||current.swarm!==found.swarm||!anchorsUnchanged)return{success:!1,message:"the plan changed while anchors were running; re-run attest against the current declaration",errors:["the plan changed while anchors were running; re-run attest against the current declaration"],task_id:args2.task_id};let existingEvidence=null;try{existingEvidence=readTaskEvidenceRaw(directory,args2.task_id)}catch(error93){let message=`the existing evidence file for task ${args2.task_id} is unreadable (corrupt): ${error93 instanceof Error?error93.message.slice(0,160):String(error93).slice(0,160)}; inspect the file before attesting`;return{success:!1,message,errors:[message],task_id:args2.task_id}}let generation=existingEvidence?.workflow?.generation??0,transitionId=`attest:${args2.task_id}:${startedAt}:${Math.random().toString(36).slice(2,10)}`,bundle={class:"external_git",transitionId,declarationDigest:computeExternalDeclarationDigest({taskId:args2.task_id,evidence_class:"external_git",evidence_anchors:anchors,plan_title:current.title,plan_swarm:current.swarm,generation}),anchors:outcomes,attestedAt:new Date().toISOString()};try{await transitionTaskWorkflowEvidence(directory,args2.task_id,{type:"external_evidence_attested",bundle,expectedGeneration:generation,transitionId})}catch(error93){let message=error93 instanceof Error?error93.message:String(error93);return{success:!1,message,errors:[message],task_id:args2.task_id}}return{success:!0,message:`Task ${args2.task_id}: ${outcomes.length} external evidence anchor(s) attested and recorded; completion is now admissible for this declared task`,task_id:args2.task_id}}var ANCHOR_STDOUT_MAX_CHARS=4096,ANCHOR_SPAWN_TIMEOUT_MS=1e4,ANCHOR_SPAWN_MAX_BUFFER_BYTES=262144,ATTEST_TOTAL_DEADLINE_MS=30000,READ_ONLY_GIT_FLAGS,REMOTE_HELPER_PATTERN,_internals118;var init_attest_task=__esm(()=>{init_plan_schema();init_gate_evidence();init_bun_compat();init_git_executable();init_project_boundary();init_update_task_status();READ_ONLY_GIT_FLAGS={"rev-list":{"--count":0,"--max-count":1,"--format":1,"--skip":1},log:{"--format":1,"--max-count":1,"-n":1,"--oneline":0,"--no-patch":0,"--stat":0,"--name-only":0,"-1":0,"-2":0,"-3":0,"-4":0,"-5":0,"-9":0},show:{"--format":1,"--stat":0,"--name-only":0,"--no-patch":0,"--quiet":0},diff:{"--stat":0,"--name-only":0,"--quiet":0},"rev-parse":{"--verify":0,"--short":0}},REMOTE_HELPER_PATTERN=/^(ext::|[a-z+.-]+::)/;_internals118={runAnchor,buildAnchorArgv,loadPlanTask:(directory,taskId)=>{let planPath=path125.join(directory,".swarm","plan.json");if(!fs80.existsSync(planPath))return null;let plan=PlanSchema.parse(JSON.parse(fs80.readFileSync(planPath,"utf-8")));for(let phase of plan.phases)for(let task of phase.tasks)if(task.id===taskId)return{title:plan.title,swarm:plan.swarm,task};return null}}});async function handleAttestCommand(directory,args2,sessionID){let unknownOptions=args2.filter((arg)=>arg.startsWith("--"));if(unknownOptions.length>0)return["## External Evidence Attestation","",`❌ Unsupported option(s): ${unknownOptions.join(" ")}. Usage: /swarm attest <task_id>`].join(`
|
|
@@ -4365,8 +4365,8 @@ Phase **${result.phase??"unknown"}** retrospective saved to \`.swarm/evidence/${
|
|
|
4365
4365
|
Run \`/swarm evidence ${result.task_id??"unknown"}\` to view it, or \`/swarm status\` to check phase_complete readiness.`;return`Error: ${result.message}`}var init_write_retro2=__esm(()=>{init_write_retro()});var COMMAND_NAMES,COMMAND_NAME_SET;var init_command_names=__esm(()=>{init_registry2();COMMAND_NAMES=Object.freeze(Object.keys(COMMAND_REGISTRY)),COMMAND_NAME_SET=new Set(COMMAND_NAMES)});import path291 from"node:path";function parseGuardrailExplainArgs(args2){let agent="coder",scope=null,writeTargets=[],positional=[],i=0;while(i<args2.length){let token=args2[i];if(token==="--agent"&&i+1<args2.length)agent=args2[i+1],i+=2;else if(token==="--scope"&&i+1<args2.length)scope=args2[i+1],i+=2;else if(token==="--write"&&i+1<args2.length)writeTargets.push(args2[i+1]),i+=2;else positional.push(token),i++}return{agent,scope,writeTargets,shellCommand:positional.join(" ")}}function resolveShellType(command){if(/^(powershell|ps1|\.\s*\\|Remove-Item|Copy-Item|Move-Item|Start-Process|New-Object|Get-ChildItem|Set-Content|Add-Content|Out-File|Invoke-WebRequest|Invoke-RestMethod|IEX|iex)\b/i.test(command)||command.includes("$PSVersionTable")||command.includes("$env:")||/-EncodedCommand|-ExecutionPolicy|Enable-PSRemoting/i.test(command))return"powershell";if(/^(cmd|cmd\.exe|c:\/|set \w+=|\.\d+|del \/|rd \/|mkdir|chdir|echo |copy |move |ren |fc |diskpart)/i.test(command)||/%[^%\s]+%/.test(command)||/\b(set|echo|if|exist)\s+/i.test(command))return"cmd";return"posix"}function evaluateDestructiveDecision(rawCommand,cwd,declaredScope){if(!rawCommand)return{decision:"allow",firingRule:"allow: no rule matched"};let shared=classifyCommand(rawCommand),sharedFiringRule=`shared_classifier: ${shared.aggregate}`;if(getSharedClassifierGuardrailBlock(shared))return{decision:"block",firingRule:sharedFiringRule};let command=dcNormalizeCommand(rawCommand),unwrapped=dcUnwrapWrappers(command),outerSegments=dcSplitSegments(command),innerSegments=dcSplitSegments(unwrapped),perSegmentUnwrapped=outerSegments.map((s)=>dcUnwrapWrappers(s)),allSegments=[...new Set([...outerSegments,...innerSegments,...perSegmentUnwrapped])];for(let segment of allSegments){let seg=segment.trim();if(!seg)continue;if(dcCheckJunctionCreation(seg,cwd))return{decision:"block",firingRule:"destructive_block: junction creation"};let targets=dcExtractRecursiveRmTargets(seg);if(targets){let targetDecision=dcEvaluateRecursiveDeleteTargets({targets,cwd});if(!targetDecision.allowed)return{decision:"block",firingRule:`${targetDecision.code}: ${targetDecision.reason}`}}if(/^(?:rmdir|rd)(?:\.exe)?\s+.*\/[sS]/i.test(seg)){let targets2=dcExtractWindowsCmdTargets(seg);if(targets2.length===0)return{decision:"block",firingRule:"destructive_block: Windows recursive directory delete (rmdir /s)"};let targetDecision=dcEvaluateRecursiveDeleteTargets({targets:targets2,cwd});if(!targetDecision.allowed)return{decision:"block",firingRule:`${targetDecision.code}: ${targetDecision.reason}`}}if(/^del(?:\.exe)?\s+.*\/[sS]/i.test(seg)){let targets2=dcExtractWindowsCmdTargets(seg);if(targets2.length>0){let targetDecision=dcEvaluateRecursiveDeleteTargets({targets:targets2,cwd});if(!targetDecision.allowed)return{decision:"block",firingRule:`${targetDecision.code}: ${targetDecision.reason}`}}}if(/^(?:Remove-Item|ri|rm|rmdir|del|erase|rd)\b.*-[Rr]ecurse\b/i.test(seg)||/^(?:Remove-Item|ri|rm|rmdir|del|erase|rd)\b.*-[Rr]\b/i.test(seg)){let targets2=dcExtractPowerShellTargets(seg);if(targets2.length>0){let targetDecision=dcEvaluateRecursiveDeleteTargets({targets:targets2,cwd});if(!targetDecision.allowed)return{decision:"block",firingRule:`${targetDecision.code}: ${targetDecision.reason}`}}else return{decision:"block",firingRule:"destructive_block: PowerShell Remove-Item -Recurse (target unverifiable)"}}if(/Get-ChildItem\b.*\|\s*Remove-Item\b.*-[Rr]ecurse/i.test(seg)||/gci\b.*\|\s*ri\b.*-[Rr]ecurse/i.test(seg))return{decision:"block",firingRule:"destructive_block: PowerShell pipeline Get-ChildItem | Remove-Item -Recurse"};if(/^git\s+worktree\s+remove\s+.*--force\b/i.test(seg)){let worktreeRemoveMatch=/^git\s+worktree\s+remove\s+(.+)$/i.exec(seg);if(worktreeRemoveMatch){let pathArgs=worktreeRemoveMatch[1].trim().split(/\s+/).filter(Boolean).map((token)=>token.replace(/^["']|["']$/g,"")).filter((token)=>!token.startsWith("-")),target=pathArgs.length===1?pathArgs[0]?.trim():null;if(!(target!=null&&target.length>0&&declaredScope!=null&&declaredScope.length>0&&isInDeclaredScope(target,declaredScope,cwd)))return{decision:"block",firingRule:"destructive_block: git worktree remove --force"}}}if(/^rsync\b.*--delete(?:-after|-before|-during|-delay)?\b/.test(seg)){let rsyncTarget=seg.split(/\s+/).slice(1).filter((a)=>!a.startsWith("-")&&!a.includes("@")).pop();if(!(rsyncTarget!=null&&declaredScope!=null&&declaredScope.length>0&&isInDeclaredScope(rsyncTarget,declaredScope,cwd)))return{decision:"block",firingRule:`destructive_block: rsync --delete (target: ${redactPath(rsyncTarget??"unknown")})`}}if(/^\\?mv\s/i.test(seg)){let mvMatch=seg.match(/^\\?mv\s+(.+)$/i);if(mvMatch){let argsStr=mvMatch[1].replace(/["']/g,"");if(/\.swarm(?:[\x5c/\s]|$)/.test(argsStr))return{decision:"block",firingRule:'destructive_block: "mv" targeting .swarm/ detected — move operations under .swarm/ are not allowed from shell commands'}}}if(/^\\?(?:move|ren)(?:\.exe)?\s/i.test(seg)){let moveMatch=seg.match(/^\\?(?:move|ren)(?:\.exe)?\s+(.+)$/i);if(moveMatch){let argsStr=moveMatch[1].replace(/["']/g,"");if(/\.swarm(?:[\x5c/\s]|$)/i.test(argsStr))return{decision:"block",firingRule:'destructive_block: "move" or "ren" targeting .swarm/ detected — move/rename operations under .swarm/ are not allowed from shell commands'}}}if(/^\\?(?:Move-Item|Rename-Item|move|mi|mv|ren|rni)\b.*\.swarm(?:[\x5c/\s]|$)/i.test(seg))return{decision:"block",firingRule:"destructive_block: PowerShell Move-Item or Rename-Item targeting .swarm/ detected — move/rename operations under .swarm/ are not allowed from shell commands"};if(/^\\?rm\b/i.test(seg)&&!/^\\?rm\s+(?:-[a-zA-Z]*[rR][a-zA-Z]*|--recursive)\b/i.test(seg)&&/\.swarm(?:[\x5c/\s]|$)/i.test(seg))return{decision:"block",firingRule:'destructive_block: "rm" targeting .swarm/ detected — deleting files under .swarm/ is not allowed from shell commands'};if(/\bcp\b.*\.swarm(?:[\x5c/\s]|$)/i.test(seg)&&/\brm\b.*\.swarm(?:[\x5c/\s]|$)/i.test(seg))return{decision:"block",firingRule:'destructive_block: "cp" of .swarm/ file followed by "rm" of .swarm/ source detected — copy-and-delete bypass is not allowed'};if(/^rsync\b.*--remove-source-files\b/i.test(seg)&&/\.swarm(?:[\x5c/\s]|$)/i.test(seg))return{decision:"block",firingRule:'destructive_block: "rsync" with delete-source flag targeting .swarm/ detected — archive with source deletion under .swarm/ is not allowed'};if(/^tar\b.*--remove-files\b/i.test(seg)&&/\.swarm(?:[\x5c/\s]|$)/i.test(seg))return{decision:"block",firingRule:'destructive_block: "tar" with delete-source flag targeting .swarm/ detected — archive with source deletion under .swarm/ is not allowed'};if(/^zip\b.*\s-m\b/i.test(seg)&&/\.swarm(?:[\x5c/\s]|$)/i.test(seg))return{decision:"block",firingRule:'destructive_block: "zip" with delete-source flag targeting .swarm/ detected — archive with source deletion under .swarm/ is not allowed'};if(/^7z\b.*\s-sdel\b/i.test(seg)&&/\.swarm(?:[\x5c/\s]|$)/i.test(seg))return{decision:"block",firingRule:'destructive_block: "7z" with delete-source flag targeting .swarm/ detected — archive with source deletion under .swarm/ is not allowed'};{let probe2=seg.replace(/^(?:[A-Za-z_][A-Za-z0-9_]*=\S+\s+)+/,"").replace(/^eval(?:\s+--)?\s+["']?/,"").replace(/["']\s*$/,"").replace(/^\$\(\s*/,"").replace(/^\(\s*/,"").replace(/\s*\)$/,"").replace(/^`/,"").replace(/`$/,"").trim();for(let i=0;i<4;i++){let before=probe2;if(probe2=probe2.replace(/^env\s+(?:-i\b|--ignore-environment\b|-u\s+\S+|-[a-zA-Z]+\s+)*\s*/,"").replace(/^command\s+(?:-[pvV]\s+)*/,"").replace(/^(?:[A-Za-z_][A-Za-z0-9_]*=\S+\s+)+/,"").trim(),probe2===before)break}let swarmCliMatches=[probe2.match(/^\\?(?:bunx|npx|pnpx|npm(?:\s+(?:exec|x)(?:\s+--)?)?|pnpm(?:\s+(?:dlx|exec))?|yarn(?:\s+(?:dlx|exec))?|bun(?:\s+x)?|node|deno\s+run|tsx|ts-node)\b[^|;&]*?\bopencode-swarm\b[^|;&]*?\brun\s+([A-Za-z0-9_-]+(?:\s+(?!-)[A-Za-z0-9_-]+)?)/i),probe2.match(/^\\?opencode-swarm\b[^|;&]*?\brun\s+([A-Za-z0-9_-]+(?:\s+(?!-)[A-Za-z0-9_-]+)?)/i),probe2.match(/\bcli[/\\]+index\.[mc]?(?:js|ts)\b[^|;&]*?\brun\s+([A-Za-z0-9_-]+(?:\s+(?!-)[A-Za-z0-9_-]+)?)/i)];for(let m of swarmCliMatches){if(!m)continue;let normalized=m[1].trim().split(/\s+/).join(" "),firstToken=normalized.includes(" ")?normalized.split(" ")[0]:normalized;if(HUMAN_ONLY_SWARM_COMMANDS.has(normalized)||HUMAN_ONLY_SWARM_COMMANDS.has(firstToken))return{decision:"block",firingRule:`human_only_command: "${HUMAN_ONLY_SWARM_COMMANDS.has(normalized)?normalized:firstToken}" is a human-only swarm command (not invocable from shell by an agent)`}}}{let normForPathCheck=seg.replace(/\\/g,"/").replace(/\/(?:\.\/+)+/g,"/").replace(/\/{2,}/g,"/");if(/\.swarm\/spec-staleness\.json\b/i.test(normForPathCheck)){let trimmed=seg.trim(),looksReadOnly=/^(?:cat|less|more|head|tail|file|stat|ls|dir|Get-Content|gc|Get-Item|gi|type)\b/i.test(trimmed),hasWriteRedirect=/>{1,2}\s*[^\s>]/.test(trimmed);if(!looksReadOnly||hasWriteRedirect)return{decision:"block",firingRule:"system_file_tampering: shell command targeting .swarm/spec-staleness.json (system-managed file)"}}}}return{decision:"allow",firingRule:"allow: no destructive/scope rule matched"}}async function handleGuardrailExplain(directory,args2){let{agent,scope,writeTargets,shellCommand}=parseGuardrailExplainArgs(args2),resolvedScope=scope??directory,scopeEntries=scope!=null&&scope.length>0?[scope]:[resolvedScope];if(writeTargets.length>0){let results=[];for(let rawPath of writeTargets){let absolutePath2=path291.resolve(directory,rawPath),decision2=checkFileAuthority(agent,absolutePath2,directory,void 0,{declaredScope:scope!=null?[scope]:null}),zoneResult=classifyFile(absolutePath2),allowed=decision2.allowed===!0,zone=allowed?zoneResult.zone:decision2.zone??zoneResult.zone;results.push({path:rawPath,decision:allowed?"allow":"block",firingRule:allowed?"allow: no rule matched":decision2.reason,resolvedScope,zone})}let redactedResolvedScope=redactPath(resolvedScope);return["## Guardrail Explain (dry-run)","",`**Mode**: write-target | **Agent**: ${agent} | **Resolved scope**: ${redactedResolvedScope}`,"","| Path | Decision | Firing Rule | Resolved Scope | Zone |","| --- | --- | --- | --- | --- |",...results.map((r)=>`| ${redactPath(r.path)} | ${r.decision} | ${r.firingRule} | ${redactPath(r.resolvedScope)} | ${r.zone} |`),""].join(`
|
|
4366
4366
|
`)}if(!shellCommand)return["## Guardrail Explain (dry-run)","","Provide a shell command to analyze, or use `--write <path>` for write-target mode.","","```","/swarm guardrail explain <command>","/swarm guardrail explain --agent <role> --scope <path> <command>","/swarm guardrail explain --write <path> [--write <path2> ...]","```",""].join(`
|
|
4367
4367
|
`);let decision="allow",firingRule="allow: no rule matched",writeCategories=new Set,destructiveEval=evaluateDestructiveDecision(shellCommand,directory,scopeEntries);if(destructiveEval.decision==="block")decision="block",firingRule=destructiveEval.firingRule;let commandSegments=dcSplitSegments(shellCommand),unwrappedSegments=commandSegments.map((s)=>dcUnwrapWrappers(s)),detectionCommand=commandSegments.some((s,i)=>unwrappedSegments[i]!==s)?unwrappedSegments.join(`
|
|
4368
|
-
`):shellCommand;if(decision==="allow"){let detected=resolveShellType(shellCommand),authority=resolveWindowsWriteAuthority("shell",shellCommand,detected,isPowerShellShaped(shellCommand)),wrapperDeclaredHere=declaresWindowsWrapperLoose(shellCommand),posix24=detectPosixWrites(detectionCommand),analysis=authority===null?posix24:mergeWriteAnalyses(posix24,detectWindowsWrites(detectionCommand,authority),!0,wrapperDeclaredHere),rawPosix=detectPosixWrites(shellCommand);if((authority===null?rawPosix:mergeWriteAnalyses(rawPosix,detectWindowsWrites(shellCommand,authority),!0,wrapperDeclaredHere)).parseError&&!isPowerShellReadOnlyPipeline(shellCommand))decision="block",firingRule="parse_error: write detection failed to parse command — rejecting for safety";else if(analysis.parseError&&!isPowerShellReadOnlyPipeline(detectionCommand))decision="block",firingRule="parse_error: write detection failed to parse command — rejecting for safety";else if(analysis.hasWrites){let resolvedWrites=resolveWriteTargets(detectionCommand,analysis.writes,directory);for(let write of resolvedWrites)if(write.resolvedPath){if(agent!=="architect"){if(!(isInDeclaredScope(write.resolvedPath,scopeEntries,directory)||write.original.emptyDirectoryRemoval===!0&&isPosixRmdirExecutor("shell",authority,detectionCommand)&&isEmptyDirectoryRemovalWithinWorkspace(write.resolvedPath,directory))){decision="block",firingRule=`scope_violation: write outside declared scope: ${redactPath(write.resolvedPath)}`;break}}writeCategories.add(write.original.category)}else writeCategories.add(write.original.category)}}else{let detected=resolveShellType(shellCommand),authority=resolveWindowsWriteAuthority("shell",shellCommand,detected,isPowerShellShaped(shellCommand)),wrapperDeclaredElse=declaresWindowsWrapperLoose(shellCommand),posix24=detectPosixWrites(detectionCommand),analysis=authority===null?posix24:mergeWriteAnalyses(posix24,detectWindowsWrites(detectionCommand,authority),!0,wrapperDeclaredElse);if(!analysis.parseError&&analysis.hasWrites)for(let write of analysis.writes)writeCategories.add(write.category)}let redactedCommand=redactShellCommand(shellCommand),redactedResolvedScopeShell=redactPath(resolvedScope),shellResult={decision,firingRule,resolvedScope:redactedResolvedScopeShell,writeCategories:writeCategories.size>0?[...writeCategories]:[],command:redactedCommand};return["## Guardrail Explain (dry-run)","",`**Mode**: shell | **Agent**: ${agent} | **Resolved scope**: ${redactedResolvedScopeShell}`,"","| Field | Value |","| --- | --- |",`| Command | \`${shellResult.command}\` |`,`| Decision | ${shellResult.decision} |`,`| Firing Rule | ${shellResult.firingRule} |`,`| Resolved Scope | ${shellResult.resolvedScope} |`,`| Write Categories | ${shellResult.writeCategories.length>0?shellResult.writeCategories.join(", "):"(none)"} |`,""].join(`
|
|
4369
|
-
`)}var init_guardrail_explain_service=__esm(()=>{init_tool_policy();init_audit_log();init_destructive_command();init_file_authority();init_helpers();init_tool_before();init_shell_executor_context();init_shell_write_detect();init_command_classifier()});var exports_guardrail_explain={};__export(exports_guardrail_explain,{handleGuardrailExplain:()=>handleGuardrailExplain});var init_guardrail_explain=__esm(()=>{init_guardrail_explain_service()});function isBlockEntry(entry){if(entry.type===null||entry.type===void 0)return!1;return BLOCK_TYPES.has(entry.type)}function redactSummary(entry){if(entry.type==="file_write"||entry.type==="scope_violation"){let raw=entry.path??"";return redactPath(raw)}if(entry.type==="destructive_block"||entry.type==="sandbox_wrap"||entry.type==="sandbox_skip"||entry.type==="shell"||entry.type===null||entry.type===void 0){let raw=entry.command??"";return redactShellCommand(raw)}return""}function sanitizeDisplayText(value){return value.replace(/\u001b\[[0-9;?]*[ -/]*[@-~]/g,"").replace(/[\u0000-\u0008\u000a-\u001f\u007f-\u009f]/g,"").replace(/[\u202a-\u202e\u2066-\u2069]/g,"").replace(/[\u200e\u200f\u200b-\u200d\u2060-\u2064\ufeff]/g,"")}function formatEntry(entry){let decisionType=entry.type??"shell",summary=redactSummary(entry),line=`- [${sanitizeDisplayText(entry.ts)}] ${sanitizeDisplayText(decisionType)} | agent: ${sanitizeDisplayText(entry.agent)} | ${sanitizeDisplayText(summary)}`;if(entry.commandHash!==void 0)line+=` · fp:${sanitizeDisplayText(entry.commandHash)}`;return line.length>MAX_RENDERED_LINE_CHARS?`${line.slice(0,MAX_RENDERED_LINE_CHARS)}…`:line}function isPlainObject8(value){return typeof value==="object"&&value!==null&&(value.constructor===Object||Object.getPrototypeOf(value)===null)}function parseEntries(raw){let lines=raw.split(/\r?\n/),entries2=[];for(let line of lines){if(line.trim().length===0)continue;let parsed;try{parsed=JSON.parse(line)}catch{continue}if(!isPlainObject8(parsed))continue;if(typeof parsed.ts!=="string")continue;if(typeof parsed.sessionID!=="string")continue;if(typeof parsed.agent!=="string")continue;if(typeof parsed.tool!=="string")continue;let entry={ts:parsed.ts,sessionID:parsed.sessionID,agent:parsed.agent,tool:parsed.tool};if(typeof parsed.type==="string")entry.type=parsed.type;if(typeof parsed.command==="string")entry.command=parsed.command;if(typeof parsed.path==="string")entry.path=parsed.path;if(typeof parsed.commandHash==="string")entry.commandHash=parsed.commandHash;entries2.push(entry)}return entries2}async function handleGuardrailLog(directory,args2){let window2=readShellAuditTail(directory),entries2=parseEntries(window2.text),blocksOnly=args2.includes("--blocks-only");if(entries2.length===0){let folded2=getShellAuditFoldedSummary(directory);if(folded2!==null&&folded2.totalDecisions>0){let note=`${folded2.totalDecisions} earlier decision(s) compacted into the audit manifest.`;return blocksOnly?`No guardrail block decisions in the read window; ${note}`:`No guardrail decisions in the read window; ${note}`}return blocksOnly?"No guardrail block decisions recorded yet.":"No guardrail decisions recorded yet."}let filtered=blocksOnly?entries2.filter(isBlockEntry):entries2;if(filtered.length===0){let folded2=getShellAuditFoldedSummary(directory);if(blocksOnly&&folded2!==null){let foldedBlocks=[...BLOCK_TYPES].reduce((sum,type)=>sum+(folded2.byType[type]??0),0);if(foldedBlocks>0)return`No guardrail block decisions in the read window; ${foldedBlocks} earlier block decision(s) compacted into the audit manifest.`}if(blocksOnly)return"No guardrail block decisions recorded yet.";return"No guardrail decisions recorded yet."}filtered.sort((a,b)=>{let diff=b.ts.localeCompare(a.ts);return diff===0?0:diff});let rendered=filtered.slice(0,MAX_RENDERED_ENTRIES),header=blocksOnly?"# Guardrail Block Log (most-recent-first)":"# Guardrail Decision Log (most-recent-first)",body=rendered.map(formatEntry).join(`
|
|
4368
|
+
`):shellCommand;if(decision==="allow"){let detected=resolveShellType(shellCommand),authority=resolveWindowsWriteAuthority("shell",shellCommand,detected,isPowerShellShaped(shellCommand),process.platform,getObservedHostShell()),wrapperDeclaredHere=declaresWindowsWrapperLoose(shellCommand),posix24=detectPosixWrites(detectionCommand),analysis=authority===null?posix24:mergeWriteAnalyses(posix24,detectWindowsWrites(detectionCommand,authority),!0,wrapperDeclaredHere),rawPosix=detectPosixWrites(shellCommand);if((authority===null?rawPosix:mergeWriteAnalyses(rawPosix,detectWindowsWrites(shellCommand,authority),!0,wrapperDeclaredHere)).parseError&&!isPowerShellReadOnlyPipeline(shellCommand))decision="block",firingRule="parse_error: write detection failed to parse command — rejecting for safety";else if(analysis.parseError&&!isPowerShellReadOnlyPipeline(detectionCommand))decision="block",firingRule="parse_error: write detection failed to parse command — rejecting for safety";else if(analysis.hasWrites){let resolvedWrites=resolveWriteTargets(detectionCommand,analysis.writes,directory);for(let write of resolvedWrites)if(write.resolvedPath){if(agent!=="architect"){if(!(isInDeclaredScope(write.resolvedPath,scopeEntries,directory)||write.original.emptyDirectoryRemoval===!0&&isPosixRmdirExecutor("shell",authority,detectionCommand)&&isEmptyDirectoryRemovalWithinWorkspace(write.resolvedPath,directory))){decision="block",firingRule=`scope_violation: write outside declared scope: ${redactPath(write.resolvedPath)}`;break}}writeCategories.add(write.original.category)}else writeCategories.add(write.original.category)}}else{let detected=resolveShellType(shellCommand),authority=resolveWindowsWriteAuthority("shell",shellCommand,detected,isPowerShellShaped(shellCommand),process.platform,getObservedHostShell()),wrapperDeclaredElse=declaresWindowsWrapperLoose(shellCommand),posix24=detectPosixWrites(detectionCommand),analysis=authority===null?posix24:mergeWriteAnalyses(posix24,detectWindowsWrites(detectionCommand,authority),!0,wrapperDeclaredElse);if(!analysis.parseError&&analysis.hasWrites)for(let write of analysis.writes)writeCategories.add(write.category)}let redactedCommand=redactShellCommand(shellCommand),redactedResolvedScopeShell=redactPath(resolvedScope),shellResult={decision,firingRule,resolvedScope:redactedResolvedScopeShell,writeCategories:writeCategories.size>0?[...writeCategories]:[],command:redactedCommand};return["## Guardrail Explain (dry-run)","",`**Mode**: shell | **Agent**: ${agent} | **Resolved scope**: ${redactedResolvedScopeShell}`,"","| Field | Value |","| --- | --- |",`| Command | \`${shellResult.command}\` |`,`| Decision | ${shellResult.decision} |`,`| Firing Rule | ${shellResult.firingRule} |`,`| Resolved Scope | ${shellResult.resolvedScope} |`,`| Write Categories | ${shellResult.writeCategories.length>0?shellResult.writeCategories.join(", "):"(none)"} |`,""].join(`
|
|
4369
|
+
`)}var init_guardrail_explain_service=__esm(()=>{init_tool_policy();init_audit_log();init_destructive_command();init_file_authority();init_helpers();init_tool_before();init_shell_executor_context();init_shell_executor_context();init_shell_write_detect();init_command_classifier()});var exports_guardrail_explain={};__export(exports_guardrail_explain,{handleGuardrailExplain:()=>handleGuardrailExplain});var init_guardrail_explain=__esm(()=>{init_guardrail_explain_service()});function isBlockEntry(entry){if(entry.type===null||entry.type===void 0)return!1;return BLOCK_TYPES.has(entry.type)}function redactSummary(entry){if(entry.type==="file_write"||entry.type==="scope_violation"){let raw=entry.path??"";return redactPath(raw)}if(entry.type==="destructive_block"||entry.type==="sandbox_wrap"||entry.type==="sandbox_skip"||entry.type==="shell"||entry.type===null||entry.type===void 0){let raw=entry.command??"";return redactShellCommand(raw)}return""}function sanitizeDisplayText(value){return value.replace(/\u001b\[[0-9;?]*[ -/]*[@-~]/g,"").replace(/[\u0000-\u0008\u000a-\u001f\u007f-\u009f]/g,"").replace(/[\u202a-\u202e\u2066-\u2069]/g,"").replace(/[\u200e\u200f\u200b-\u200d\u2060-\u2064\ufeff]/g,"")}function formatEntry(entry){let decisionType=entry.type??"shell",summary=redactSummary(entry),line=`- [${sanitizeDisplayText(entry.ts)}] ${sanitizeDisplayText(decisionType)} | agent: ${sanitizeDisplayText(entry.agent)} | ${sanitizeDisplayText(summary)}`;if(entry.commandHash!==void 0)line+=` · fp:${sanitizeDisplayText(entry.commandHash)}`;return line.length>MAX_RENDERED_LINE_CHARS?`${line.slice(0,MAX_RENDERED_LINE_CHARS)}…`:line}function isPlainObject8(value){return typeof value==="object"&&value!==null&&(value.constructor===Object||Object.getPrototypeOf(value)===null)}function parseEntries(raw){let lines=raw.split(/\r?\n/),entries2=[];for(let line of lines){if(line.trim().length===0)continue;let parsed;try{parsed=JSON.parse(line)}catch{continue}if(!isPlainObject8(parsed))continue;if(typeof parsed.ts!=="string")continue;if(typeof parsed.sessionID!=="string")continue;if(typeof parsed.agent!=="string")continue;if(typeof parsed.tool!=="string")continue;let entry={ts:parsed.ts,sessionID:parsed.sessionID,agent:parsed.agent,tool:parsed.tool};if(typeof parsed.type==="string")entry.type=parsed.type;if(typeof parsed.command==="string")entry.command=parsed.command;if(typeof parsed.path==="string")entry.path=parsed.path;if(typeof parsed.commandHash==="string")entry.commandHash=parsed.commandHash;entries2.push(entry)}return entries2}async function handleGuardrailLog(directory,args2){let window2=readShellAuditTail(directory),entries2=parseEntries(window2.text),blocksOnly=args2.includes("--blocks-only");if(entries2.length===0){let folded2=getShellAuditFoldedSummary(directory);if(folded2!==null&&folded2.totalDecisions>0){let note=`${folded2.totalDecisions} earlier decision(s) compacted into the audit manifest.`;return blocksOnly?`No guardrail block decisions in the read window; ${note}`:`No guardrail decisions in the read window; ${note}`}return blocksOnly?"No guardrail block decisions recorded yet.":"No guardrail decisions recorded yet."}let filtered=blocksOnly?entries2.filter(isBlockEntry):entries2;if(filtered.length===0){let folded2=getShellAuditFoldedSummary(directory);if(blocksOnly&&folded2!==null){let foldedBlocks=[...BLOCK_TYPES].reduce((sum,type)=>sum+(folded2.byType[type]??0),0);if(foldedBlocks>0)return`No guardrail block decisions in the read window; ${foldedBlocks} earlier block decision(s) compacted into the audit manifest.`}if(blocksOnly)return"No guardrail block decisions recorded yet.";return"No guardrail decisions recorded yet."}filtered.sort((a,b)=>{let diff=b.ts.localeCompare(a.ts);return diff===0?0:diff});let rendered=filtered.slice(0,MAX_RENDERED_ENTRIES),header=blocksOnly?"# Guardrail Block Log (most-recent-first)":"# Guardrail Decision Log (most-recent-first)",body=rendered.map(formatEntry).join(`
|
|
4370
4370
|
`),notes=[];if(rendered.length<filtered.length)notes.push(`showing ${rendered.length} most recent of ${filtered.length} matching entries in the read window`);if(window2.truncated||window2.coverage==="truncated")notes.push("read window truncated to the newest bounded tail (older decisions may exist beyond it)");let folded=getShellAuditFoldedSummary(directory);if(folded!==null&&folded.totalDecisions>0)notes.push(`${folded.totalDecisions} earlier decision(s) already compacted into the audit manifest (lifetime total)`);if(notes.length===0)return`${header}
|
|
4371
4371
|
|
|
4372
4372
|
${body}`;return`${header}
|
|
@@ -7465,11 +7465,11 @@ Review before proceeding.`;injectSystemMessage(input.sessionID,message)}}}init_c
|
|
|
7465
7465
|
|
|
7466
7466
|
`);return system.length=0,system.push(joined),{capability,entriesBefore,entriesAfter:1,collapsed:!0}}function createSystemRenderBoundaryHook(){return{"experimental.chat.system.transform":async(input,output)=>{try{let model=typeof input==="object"&&input!==null?input.model:void 0,system=typeof output==="object"&&output!==null?output.system:void 0;if(model===void 0||model===null){log("[system-render-boundary] no model on input; leaving system surface untouched (multi-system)");return}if(!Array.isArray(system))return;let result=applySystemRenderBoundary(model,system);if(result.collapsed)log(`[system-render-boundary] strict-single-system collapse: ${result.entriesBefore} -> 1 entry (${joinedByteLength(system)} bytes)`)}catch(error93){log(`[system-render-boundary] fail-open, system surface untouched: ${error93 instanceof Error?error93.message:String(error93)}`)}}}}function joinedByteLength(system){return system[0]?.length??0}init_trajectory_logger();init_utils2();init_utils();init_timeout();var V2_MODEL_APPLY_TIMEOUT_MS=1e4,DEFAULT_V2_MODEL_APPLY_OWNER="__default__",MAX_HELD_APPLY_REGISTRATIONS=128,modelApplyOwners=new Map;function touchModelApplyOwner(token){let existing=modelApplyOwners.get(token);if(existing!==void 0)return modelApplyOwners.delete(token),modelApplyOwners.set(token,existing),existing;let state2={transform:void 0,registrationsByAgent:new Map};return modelApplyOwners.set(token,state2),state2}function disposeHeldRegistrations(owner,label){let held=[...owner.registrationsByAgent.values()];owner.registrationsByAgent.clear();for(let reg of held)reg.dispose().catch((err)=>{log(`v2 model-apply registration dispose failed (${label}; non-fatal)`,{error:err instanceof Error?err.message:String(err)})})}function registerV2AgentTransformSurface(ctx,token){let ownerToken=token??DEFAULT_V2_MODEL_APPLY_OWNER,transform3=ctx?.agent&&typeof ctx.agent.transform==="function"?ctx.agent.transform.bind(ctx.agent):void 0,owner=touchModelApplyOwner(ownerToken);if(owner.transform=transform3,transform3===void 0)log("v2 agent transform surface absent; runtime model apply disabled",{})}function clearV2AgentTransformSurface(token){if(token===void 0){for(let[ownerToken,owner2]of[...modelApplyOwners.entries()])disposeHeldRegistrations(owner2,`clear-all ${ownerToken}`);modelApplyOwners.clear();return}let owner=modelApplyOwners.get(token);if(owner===void 0)return;if(owner.transform=void 0,disposeHeldRegistrations(owner,`owner ${token}`),owner.transform===void 0&&owner.registrationsByAgent.size===0)modelApplyOwners.delete(token)}function resolveActiveModelApplyOwner(){let tokens2=[...modelApplyOwners.keys()];for(let i=tokens2.length-1;i>=0;i-=1){let owner=modelApplyOwners.get(tokens2[i]??"");if(owner?.transform!==void 0)return owner}return}async function applyV2AgentModelOverride(agentName,modelString){let owner=resolveActiveModelApplyOwner(),transform3=owner?.transform;if(owner===void 0||transform3===void 0)return!1;let separator=modelString.indexOf("/");if(typeof agentName!=="string"||agentName.length===0||separator<=0||separator===modelString.length-1)return log("v2 model apply rejected malformed input (non-fatal)",{agentName,modelString}),!1;let providerID=modelString.slice(0,separator),id=modelString.slice(separator+1);try{let applied2=await withTimeout(Promise.resolve(transform3((editor)=>{editor.update(agentName,(agent)=>{agent.model={providerID,id}})})),V2_MODEL_APPLY_TIMEOUT_MS,Error(`[opencode-swarm] v2: model apply for ${agentName} exceeded budget`)),previous=owner.registrationsByAgent.get(agentName);owner.registrationsByAgent.set(agentName,applied2);while(owner.registrationsByAgent.size>MAX_HELD_APPLY_REGISTRATIONS){let oldest=owner.registrationsByAgent.keys().next().value;if(typeof oldest!=="string")break;let evicted=owner.registrationsByAgent.get(oldest);owner.registrationsByAgent.delete(oldest),evicted?.dispose().catch((err)=>{log("v2 evicted model-apply registration dispose failed (non-fatal)",{agentName:oldest,error:err instanceof Error?err.message:String(err)})})}if(previous)previous.dispose().catch((err)=>{log("v2 previous model-apply registration dispose failed (non-fatal)",{agentName,error:err instanceof Error?err.message:String(err)})});return log("v2 agent model applied",{agentName,modelString}),!0}catch(err){return log("v2 agent model apply failed (non-fatal)",{agentName,modelString,error:err instanceof Error?err.message:String(err)}),!1}}init_zod();init_loader();init_model_preflight();init_warning_buffer();init_state();init_utils();init_project_boundary();init_timeout();init_command_dispatch();init_registry2();init_utils2();init_warning_buffer();init_utils();init_timeout();var V2_AGENT_COMMAND_CALL_TIMEOUT_MS=60000,V2_COMMAND_DISPATCH_TIMEOUT_MS=300000,_internals272={dispatchTimeoutMs:V2_COMMAND_DISPATCH_TIMEOUT_MS},V2_OPERATOR_WARNING_BOUND=32,operatorWarningsSeen=new Map,AMBIENT_V2_OWNER="__ambient__",v2OwnerStates=new Map,currentV2OwnerToken=AMBIENT_V2_OWNER,ownerTokenByCtx=new WeakMap,CONFIG_DOCTOR_FIX_POLICY_REFUSAL_MARKER="/swarm config doctor --fix is not available through";function v2OwnerEntry(token,create){let entry=v2OwnerStates.get(token);if(entry===void 0&&create)entry={},v2OwnerStates.set(token,entry);return entry}function dropV2OwnerEntryIfEmpty(token){let entry=v2OwnerStates.get(token);if(entry===void 0)return;if(entry.rebuild===void 0&&entry.quiet===void 0&&entry.snapshot===void 0)v2OwnerStates.delete(token)}function resolveCurrentV2OwnerToken(){if(v2OwnerStates.has(currentV2OwnerToken))return currentV2OwnerToken;return[...v2OwnerStates.keys()].filter((token)=>token!==AMBIENT_V2_OWNER).pop()??AMBIENT_V2_OWNER}function resolveV2OwnerTokenForCtx(ctx){return ownerTokenByCtx.get(ctx)??resolveCurrentV2OwnerToken()}function resolveV2ConfigRebuildSourceForToken(token){let entry=v2OwnerStates.get(token);if(entry?.rebuild!==void 0)return entry.rebuild;return v2OwnerStates.get(AMBIENT_V2_OWNER)?.rebuild}function resolveV2OperatorQuiet(){return resolveV2OperatorQuietForToken(resolveCurrentV2OwnerToken())}function resolveV2OperatorQuietForToken(token){let entry=v2OwnerStates.get(token);if(entry?.quiet!==void 0)return entry.quiet;return v2OwnerStates.get(AMBIENT_V2_OWNER)?.quiet??!1}function resolveV2RegistrationSnapshotForToken(token){return v2OwnerStates.get(token)?.snapshot??v2OwnerStates.get(AMBIENT_V2_OWNER)?.snapshot}function setV2OperatorQuiet(quiet){setV2OperatorQuietForOwner(resolveCurrentV2OwnerToken(),quiet)}function setV2OperatorQuietForOwner(token,quiet){if(quiet===void 0){let existing=v2OwnerStates.get(token);if(existing!==void 0)existing.quiet=void 0,dropV2OwnerEntryIfEmpty(token);return}let entry=v2OwnerEntry(token,!0);if(entry===void 0)return;entry.quiet=quiet,currentV2OwnerToken=token}function deferredV2WarnOperator(message,dedupKey,ownerToken){let key3=dedupKey??message;if(operatorWarningsSeen.has(key3))return;operatorWarningsSeen.set(key3,!0);while(operatorWarningsSeen.size>V2_OPERATOR_WARNING_BOUND){let oldest=operatorWarningsSeen.keys().next().value;if(oldest===void 0)break;operatorWarningsSeen.delete(oldest)}if(addDeferredWarning(message),!(ownerToken!==void 0?resolveV2OperatorQuietForToken(ownerToken):resolveV2OperatorQuiet()))console.warn(message)}function clearV2OwnerRegistrationSnapshot(ownerToken){let entry=v2OwnerStates.get(ownerToken);if(entry!==void 0)entry.snapshot=void 0,dropV2OwnerEntryIfEmpty(ownerToken)}function clearV2CtxOwnerBinding(ctx){ownerTokenByCtx.delete(ctx)}function normalizeV2PermissionAction(action2){if(action2==="write"||action2==="patch")return"edit";if(action2==="task")return"subagent";if(action2==="bash")return"shell";return action2}function migrateV1PermissionBlock(permission){let rules=[];if(!permission||typeof permission!=="object")return rules;for(let[name,value]of Object.entries(permission)){let action2=normalizeV2PermissionAction(name);if(typeof value==="string"){rules.push({action:action2,resource:"*",effect:value});continue}if(value&&typeof value==="object")for(let[resource,effect]of Object.entries(value)){if(typeof effect!=="string")continue;rules.push({action:action2,resource,effect})}}return rules}function mapV1AgentToV2(name,config3){let info={id:name,name,mode:config3.mode==="primary"||config3.mode==="subagent"||config3.mode==="all"?config3.mode:"subagent",hidden:!1,request:{settings:{},headers:{},body:{}}};if(typeof config3.prompt==="string"&&config3.prompt.length>0)info.system=config3.prompt;if(typeof config3.description==="string"&&config3.description.length>0)info.description=config3.description;if(typeof config3.model==="string"&&config3.model.includes("/")){let separator=config3.model.indexOf("/");info.model={providerID:config3.model.slice(0,separator),id:config3.model.slice(separator+1)}}let rules=migrateV1PermissionBlock(config3.permission);if(rules.length>0)info.permissions=rules;return info}function expandV1Template(template,argumentsText){return template.replaceAll("$ARGUMENTS",argumentsText).trim()}function normalizeV2CommandArguments(text){let trimmed=text.trim();if(trimmed==="/swarm"||trimmed==="swarm")return"";let match=trimmed.match(/^(?:\/swarm|swarm)\s+([\s\S]*)$/);return match!==null?match[1]:trimmed}function extractDispatchedPromptText(parts){let texts=[];for(let part of parts){if(!part||typeof part!=="object")continue;let typed=part;if(typed.type!==void 0&&typed.type!=="text")continue;if(typeof typed.text!=="string")continue;if(typed.text.trim().length===0)continue;texts.push(typed.text)}if(texts.length===0)return null;return texts.join(`
|
|
7467
7467
|
|
|
7468
|
-
`)}function buildFallbackPromptText(template,argumentsText){if(template.includes("$ARGUMENTS"))return expandV1Template(template,argumentsText);let trimmed=argumentsText.trim();return trimmed.length>0?`${template} ${trimmed}`:template}function isConfigDoctorFixInvocation(key3,argumentsText){let normalized=normalizeSwarmCommandInput(key3,argumentsText);if(!normalized.isSwarmCommand)return!1;let resolved=resolveCommand(normalized.tokens);if(resolved===null)return!1;if(canonicalCommandKey(resolved)!=="config doctor")return!1;return normalized.tokens.includes("--fix")||normalized.tokens.includes("-f")}async function deferredV2ExecuteSwarmCommand(hooks2,key3,template,ctx,invocation,directory,registrations){let dispatchOwnerToken=resolveV2OwnerTokenForCtx(ctx),prompt=ctx.session?.prompt;if(typeof prompt!=="function"){log("v2 command executed without a session prompt surface",{name:key3}),deferredV2WarnOperator(`[opencode-swarm] v2: command ${key3} was not run — the host exposes no session prompt surface; the registry handler was skipped.`,`no-prompt-surface:${directory}:${key3}`,dispatchOwnerToken);return}let rawArguments=invocation?.prompt?.text,rawText=typeof rawArguments==="string"?rawArguments:"",delivery=invocation?.delivery;log("v2 command invocation",{name:key3,text:rawText.length>200?`${rawText.slice(0,200)}… [+${rawText.length-200} chars]`:rawText,delivery});let argumentsText=normalizeV2CommandArguments(rawText),deliveryPart=delivery!==void 0?{delivery}:{},dispatched=null,hook=hooks2["command.execute.before"];if(typeof hook==="function"){let output={parts:[]},dispatchTimeoutError=Error(`[opencode-swarm] v2: command ${key3} dispatch exceeded budget`),dispatchStartedAt=Date.now();try{await withTimeout(Promise.resolve(hook({command:key3,sessionID:invocation.sessionID,arguments:argumentsText},output)),_internals272.dispatchTimeoutMs,dispatchTimeoutError),dispatched=extractDispatchedPromptText(output.parts)}catch(err){if(err===dispatchTimeoutError){let budgetSeconds=_internals272.dispatchTimeoutMs/1000;try{await withTimeout(Promise.resolve(prompt({sessionID:invocation.sessionID,text:`[opencode-swarm] v2: command ${key3} dispatch exceeded its ${budgetSeconds}s budget; the command may still be completing `+"in the background — check its status before re-running.",...deliveryPart})),V2_AGENT_COMMAND_CALL_TIMEOUT_MS,Error(`[opencode-swarm] v2: command ${key3} prompt exceeded budget`))}catch(noticeErr){log("v2 command timeout notice submission failed",{name:key3,error:noticeErr instanceof Error?noticeErr.message:String(noticeErr)})}return}log("v2 command dispatch failed (falling back to template)",{name:key3,error:err instanceof Error?err.message:String(err)}),deferredV2WarnOperator(`[opencode-swarm] v2: command ${key3} dispatch failed (${err instanceof Error?err.message:String(err)}); the expanded template fallback was submitted.`,`dispatch-failed:${key3}`,dispatchOwnerToken)}let configDoctorFixInvocation=isConfigDoctorFixInvocation(key3,argumentsText),policyRefused=configDoctorFixInvocation&&dispatched!==null&&dispatched.includes(CONFIG_DOCTOR_FIX_POLICY_REFUSAL_MARKER);if(dispatched===null){let swallowed=getLastSwallowedCommandError(invocation.sessionID,key3,dispatchStartedAt);if(swallowed!==void 0)deferredV2WarnOperator(`[opencode-swarm] v2: command ${key3} handler failed (${swallowed}); the expanded template fallback was submitted.`,`handler-failed:${invocation.sessionID}:${key3}`,dispatchOwnerToken)}if(configDoctorFixInvocation&&!policyRefused&&dispatched!==null&&getLastSwallowedCommandError(invocation.sessionID,key3,dispatchStartedAt)===void 0)await deferredV2RefreshRegistrations(ctx,hooks2,directory,registrations)}let text=dispatched??buildFallbackPromptText(template,argumentsText);try{await withTimeout(Promise.resolve(prompt({sessionID:invocation.sessionID,text,...deliveryPart})),V2_AGENT_COMMAND_CALL_TIMEOUT_MS,Error(`[opencode-swarm] v2: command ${key3} prompt exceeded budget`))}catch(err){log("v2 command prompt submission failed",{name:key3,error:err instanceof Error?err.message:String(err)}),deferredV2WarnOperator(`[opencode-swarm] v2: command ${key3} prompt submission failed (${err instanceof Error?err.message:String(err)}); the handler output was not delivered to the session.`,`prompt-failed:${invocation.sessionID}:${key3}`,dispatchOwnerToken)}}async function registerV2AgentsAndCommands(ctx,hooks2,directory,registrations,ownerToken){if(ownerToken!==void 0)ownerTokenByCtx.set(ctx,ownerToken);if(typeof hooks2.config!=="function")return;let syntheticConfig={};try{await withTimeout(Promise.resolve(hooks2.config(syntheticConfig)),V2_AGENT_COMMAND_CALL_TIMEOUT_MS,Error("[opencode-swarm] v2: synthetic config-hook run exceeded budget"))}catch(err){let message=err instanceof Error?err.message:String(err);log("v2 synthetic config-hook run failed (non-fatal)",{error:message}),deferredV2WarnOperator(`[opencode-swarm] v2: command registration failed — the shared config-hook run errored (${message}); no agents or commands were registered.`,`registration-config-hook-failed:${directory}`,ownerToken);return}let agentTable=syntheticConfig.agent??{},commandTable=syntheticConfig.command??{},registrationSnapshot={agentTable,commandTable,dirtyAgent:!1,dirtyCommand:!1},ownerEntry=v2OwnerEntry(ownerToken??resolveCurrentV2OwnerToken(),!0);if(ownerEntry!==void 0)ownerEntry.snapshot=registrationSnapshot;let agentLanded=!1;try{let agentRegistration=await withTimeout(ctx.agent.transform((editor)=>{for(let[name,config3]of Object.entries(registrationSnapshot.agentTable)){if(!config3||typeof config3!=="object")continue;if(config3.disable===!0){editor.remove(name);continue}let mapped=mapV1AgentToV2(name,config3);editor.update(name,(agent)=>{let existingPermissions=Array.isArray(agent.permissions)?[...agent.permissions]:[];if(Object.assign(agent,mapped),mapped.permissions!==void 0)agent.permissions=[...existingPermissions,...mapped.permissions]})}}),V2_AGENT_COMMAND_CALL_TIMEOUT_MS,Error("[opencode-swarm] v2: agent transform exceeded budget"));registrations.push(agentRegistration),agentLanded=!0}catch(err){let message=err instanceof Error?err.message:String(err);log("v2 agent transform failed (non-fatal)",{error:message}),deferredV2WarnOperator(`[opencode-swarm] v2: agent registration failed (${message}); no v2 agents were registered.`,`agent-registration-failed:${directory}`,ownerToken)}let commandLanded=!1;try{let commandRegistration=await withTimeout(ctx.command.transform((editor)=>{for(let[key3,entry]of Object.entries(registrationSnapshot.commandTable)){if(!entry||typeof entry!=="object")continue;let template=typeof entry.template==="string"?entry.template:void 0;if(template===void 0)continue;let definition={name:key3,description:typeof entry.description==="string"?entry.description:void 0,execute:(invocation)=>deferredV2ExecuteSwarmCommand(hooks2,key3,template,ctx,invocation,directory,registrations)};editor.add(definition)}}),V2_AGENT_COMMAND_CALL_TIMEOUT_MS,Error("[opencode-swarm] v2: command transform exceeded budget"));registrations.push(commandRegistration),commandLanded=!0}catch(err){let message=err instanceof Error?err.message:String(err);log("v2 command transform failed (non-fatal)",{error:message}),deferredV2WarnOperator(`[opencode-swarm] v2: command registration failed (${message}); the v2 command table was not registered.`,`command-registration-failed:${directory}`,ownerToken)}if(log("v2 agents + commands registered",{directory,agents:Object.keys(agentTable).length,commands:Object.keys(commandTable).length}),!agentLanded&&!commandLanded)throw Error("[opencode-swarm] v2: agent and command registrations both failed")}function registerV2ConfigRebuildSourceForOwner(token,rebuild){if(rebuild===void 0){let entry2=v2OwnerStates.get(token);if(entry2!==void 0)entry2.rebuild=void 0,dropV2OwnerEntryIfEmpty(token);return}let entry=v2OwnerEntry(token,!0);if(entry===void 0)return;entry.rebuild=rebuild,currentV2OwnerToken=token}async function deferredV2ReloadRegistrationDomain(ctx,domain3){let reload=ctx[domain3]?.reload;if(typeof reload!=="function")return!1;try{return await withTimeout(Promise.resolve(reload()),V2_AGENT_COMMAND_CALL_TIMEOUT_MS,Error(`[opencode-swarm] v2: ${domain3} registration reload exceeded budget`)),!0}catch(err){return log(`v2 ${domain3} registration reload failed (non-fatal)`,{error:err instanceof Error?err.message:String(err)}),!1}}async function deferredV2RefreshRegistrations(ctx,hooks2,directory,registrations){let ownerToken=resolveV2OwnerTokenForCtx(ctx),rebuild=resolveV2ConfigRebuildSourceForToken(ownerToken);if(rebuild===void 0){deferredV2WarnOperator("[opencode-swarm] v2: registration refresh skipped — no config rebuild source is registered on this host; the registration tables were not reloaded.",`refresh-no-rebuild-source:${directory}`,ownerToken);return}let tables;try{tables=await withTimeout(Promise.resolve(rebuild(directory)),V2_AGENT_COMMAND_CALL_TIMEOUT_MS,Error("[opencode-swarm] v2: registration rebuild exceeded budget"))}catch(err){deferredV2WarnOperator(`[opencode-swarm] v2: registration refresh failed — the config rebuild source errored (${err instanceof Error?err.message:String(err)}); the registration tables were not reloaded.`,`refresh-rebuild-failed:${directory}`,ownerToken);return}let snapshot=resolveV2RegistrationSnapshotForToken(ownerToken);if(snapshot===void 0){log("v2 registration refresh skipped — no registration snapshot",{directory});return}if(!(snapshot.dirtyAgent||snapshot.dirtyCommand||JSON.stringify(snapshot.agentTable)!==JSON.stringify(tables.agentTable)||JSON.stringify(snapshot.commandTable)!==JSON.stringify(tables.commandTable))){log("v2 registration refresh — tables unchanged, no reload",{directory,registrations:registrations?.length??0,hooksConfigPresent:typeof hooks2.config==="function"});return}snapshot.agentTable=tables.agentTable,snapshot.commandTable=tables.commandTable;let agentReloaded=await deferredV2ReloadRegistrationDomain(ctx,"agent");snapshot.dirtyAgent=!agentReloaded;let commandReloaded=await deferredV2ReloadRegistrationDomain(ctx,"command");if(snapshot.dirtyCommand=!commandReloaded,!agentReloaded||!commandReloaded){let failed=[agentReloaded?void 0:"agent",commandReloaded?void 0:"command"].filter((domain3)=>domain3!==void 0).join(", ");deferredV2WarnOperator(`[opencode-swarm] v2: registration tables changed but the ${failed} domain reload failed; the domain stays marked dirty and the next refresh retries it.`,`refresh-reload-failed:${directory}`,ownerToken)}log("v2 registration tables refreshed",{directory,registrations:registrations?.length??0,agentReloaded,commandReloaded})}init_task_model_routing();init_utils();init_timeout();init_state2();init_normalize_tool_name();init_warning_buffer();init_utils();init_timeout();var DEFAULT_CONFIG2={oversightTotalMs:120000},budgets=new Map;function finitePositive(value){return typeof value==="number"&&Number.isFinite(value)&&value>0?value:void 0}function configureV2ToolBeforeBudget(fullAuto,directory){let oversight=fullAuto?.oversight,hook=finitePositive(oversight?.hook_timeout_ms),key3=directory??"";if(!budgets.has(key3)&&budgets.size>=64){let oldest=budgets.keys().next().value;if(oldest!==void 0)budgets.delete(oldest)}budgets.set(key3,{...hook!==void 0?{hookTimeoutMs:Math.min(900000,Math.round(hook))}:{},oversightTotalMs:finitePositive(oversight?.total_timeout_ms)??120000})}function resolveV2ToolBeforeBudgetMs(fullAutoActive,directory){let cfg=(directory!==void 0?budgets.get(directory):void 0)??budgets.get("")??DEFAULT_CONFIG2;if(cfg.hookTimeoutMs!==void 0)return cfg.hookTimeoutMs;if(!fullAutoActive)return 60000;return Math.min(900000,Math.max(60000,cfg.oversightTotalMs+30000))}function resetV2ToolBeforeBudget(directory){if(directory===void 0)budgets.clear();else budgets.delete(directory)}var V2_HOOK_TIMEOUT_MS=60000;function isV2SubagentToolId(toolName){if(!toolName)return!1;if(toolName.includes("."))return/^tool\.[^.:]+\.subagent$/i.test(toolName);return normalizeToolNameLowerCase(toolName)==="subagent"}function isV2CodeModeWrapper(event){return event.tool==="execute"&&isPlainObject9(event.input)&&typeof event.input.code==="string"}function isPlainObject9(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}function mapV2SubagentArgsToV1(input){if(!isPlainObject9(input))return input;let mapped={};for(let[key3,value]of Object.entries(input))if(key3==="agent")mapped.subagent_type=value;else if(key3==="sessionID")mapped.task_id=value;else mapped[key3]=value;return mapped}function mapV1TaskArgsToV2(args2){if(!isPlainObject9(args2))return args2;let mapped={};for(let[key3,value]of Object.entries(args2))if(key3==="subagent_type")mapped.agent=value;else if(key3==="task_id")mapped.sessionID=value;else mapped[key3]=value;return mapped}var V2_SUBAGENT_WRAPPER_RE=/<subagent\s+sessionID="([^"]+)"\s+state="(running|completed|error|cancelled|canceled)"[^>]*>/,MAX_V2_WRAPPER_INNER_CHARS=20000;function parseV2SubagentWrapper(content){if(typeof content!=="string")return null;let match=content.match(V2_SUBAGENT_WRAPPER_RE);if(!match)return null;let sessionID=match[1];if(sessionID.includes("<")||sessionID.includes(">"))return null;let rawState=match[2],matchStart=match.index??0,inner=content.slice(matchStart+match[0].length).replace(/\s*<\/subagent>\s*$/,"");return{sessionID,state:rawState==="canceled"?"cancelled":rawState,inner}}var V2_WRAPPER_STRUCTURAL_TAG_RE=/<\/?(?:task_result|task_error|summary)>/g;function renderV1TaskEnvelopeFromV2(wrapper){let inner=wrapper.inner;if(inner.length>MAX_V2_WRAPPER_INNER_CHARS){let omitted=inner.length-MAX_V2_WRAPPER_INNER_CHARS;inner=`${inner.slice(0,MAX_V2_WRAPPER_INNER_CHARS)}
|
|
7468
|
+
`)}function buildFallbackPromptText(template,argumentsText){if(template.includes("$ARGUMENTS"))return expandV1Template(template,argumentsText);let trimmed=argumentsText.trim();return trimmed.length>0?`${template} ${trimmed}`:template}function isConfigDoctorFixInvocation(key3,argumentsText){let normalized=normalizeSwarmCommandInput(key3,argumentsText);if(!normalized.isSwarmCommand)return!1;let resolved=resolveCommand(normalized.tokens);if(resolved===null)return!1;if(canonicalCommandKey(resolved)!=="config doctor")return!1;return normalized.tokens.includes("--fix")||normalized.tokens.includes("-f")}async function deferredV2ExecuteSwarmCommand(hooks2,key3,template,ctx,invocation,directory,registrations){let dispatchOwnerToken=resolveV2OwnerTokenForCtx(ctx),prompt=ctx.session?.prompt;if(typeof prompt!=="function"){log("v2 command executed without a session prompt surface",{name:key3}),deferredV2WarnOperator(`[opencode-swarm] v2: command ${key3} was not run — the host exposes no session prompt surface; the registry handler was skipped.`,`no-prompt-surface:${directory}:${key3}`,dispatchOwnerToken);return}let rawArguments=invocation?.prompt?.text,rawText=typeof rawArguments==="string"?rawArguments:"",delivery=invocation?.delivery;log("v2 command invocation",{name:key3,text:rawText.length>200?`${rawText.slice(0,200)}… [+${rawText.length-200} chars]`:rawText,delivery});let argumentsText=normalizeV2CommandArguments(rawText),deliveryPart=delivery!==void 0?{delivery}:{},dispatched=null,hook=hooks2["command.execute.before"];if(typeof hook==="function"){let output={parts:[]},dispatchTimeoutError=Error(`[opencode-swarm] v2: command ${key3} dispatch exceeded budget`),dispatchStartedAt=Date.now();try{await withTimeout(Promise.resolve(hook({command:key3,sessionID:invocation.sessionID,arguments:argumentsText},output)),_internals272.dispatchTimeoutMs,dispatchTimeoutError),dispatched=extractDispatchedPromptText(output.parts)}catch(err){if(err===dispatchTimeoutError){let budgetSeconds=_internals272.dispatchTimeoutMs/1000;try{await withTimeout(Promise.resolve(prompt({sessionID:invocation.sessionID,text:`[opencode-swarm] v2: command ${key3} dispatch exceeded its ${budgetSeconds}s budget; the command may still be completing `+"in the background — check its status before re-running.",...deliveryPart})),V2_AGENT_COMMAND_CALL_TIMEOUT_MS,Error(`[opencode-swarm] v2: command ${key3} prompt exceeded budget`))}catch(noticeErr){log("v2 command timeout notice submission failed",{name:key3,error:noticeErr instanceof Error?noticeErr.message:String(noticeErr)})}return}log("v2 command dispatch failed (falling back to template)",{name:key3,error:err instanceof Error?err.message:String(err)}),deferredV2WarnOperator(`[opencode-swarm] v2: command ${key3} dispatch failed (${err instanceof Error?err.message:String(err)}); the expanded template fallback was submitted.`,`dispatch-failed:${key3}`,dispatchOwnerToken)}let configDoctorFixInvocation=isConfigDoctorFixInvocation(key3,argumentsText),policyRefused=configDoctorFixInvocation&&dispatched!==null&&dispatched.includes(CONFIG_DOCTOR_FIX_POLICY_REFUSAL_MARKER);if(dispatched===null){let swallowed=getLastSwallowedCommandError(invocation.sessionID,key3,dispatchStartedAt);if(swallowed!==void 0)deferredV2WarnOperator(`[opencode-swarm] v2: command ${key3} handler failed (${swallowed}); the expanded template fallback was submitted.`,`handler-failed:${invocation.sessionID}:${key3}`,dispatchOwnerToken)}if(configDoctorFixInvocation&&!policyRefused&&dispatched!==null&&getLastSwallowedCommandError(invocation.sessionID,key3,dispatchStartedAt)===void 0)await deferredV2RefreshRegistrations(ctx,hooks2,directory,registrations)}let text=dispatched??buildFallbackPromptText(template,argumentsText);try{await withTimeout(Promise.resolve(prompt({sessionID:invocation.sessionID,text,...deliveryPart})),V2_AGENT_COMMAND_CALL_TIMEOUT_MS,Error(`[opencode-swarm] v2: command ${key3} prompt exceeded budget`))}catch(err){log("v2 command prompt submission failed",{name:key3,error:err instanceof Error?err.message:String(err)}),deferredV2WarnOperator(`[opencode-swarm] v2: command ${key3} prompt submission failed (${err instanceof Error?err.message:String(err)}); the handler output was not delivered to the session.`,`prompt-failed:${invocation.sessionID}:${key3}`,dispatchOwnerToken)}}async function registerV2AgentsAndCommands(ctx,hooks2,directory,registrations,ownerToken){if(ownerToken!==void 0)ownerTokenByCtx.set(ctx,ownerToken);if(typeof hooks2.config!=="function")return;let syntheticConfig={};try{await withTimeout(Promise.resolve(hooks2.config(syntheticConfig)),V2_AGENT_COMMAND_CALL_TIMEOUT_MS,Error("[opencode-swarm] v2: synthetic config-hook run exceeded budget"))}catch(err){let message=err instanceof Error?err.message:String(err);log("v2 synthetic config-hook run failed (non-fatal)",{error:message}),deferredV2WarnOperator(`[opencode-swarm] v2: command registration failed — the shared config-hook run errored (${message}); no agents or commands were registered.`,`registration-config-hook-failed:${directory}`,ownerToken);return}let agentTable=syntheticConfig.agent??{},commandTable=syntheticConfig.command??{},registrationSnapshot={agentTable,commandTable,dirtyAgent:!1,dirtyCommand:!1},ownerEntry=v2OwnerEntry(ownerToken??resolveCurrentV2OwnerToken(),!0);if(ownerEntry!==void 0)ownerEntry.snapshot=registrationSnapshot;let agentLanded=!1;try{let agentRegistration=await withTimeout(ctx.agent.transform((editor)=>{for(let[name,config3]of Object.entries(registrationSnapshot.agentTable)){if(!config3||typeof config3!=="object")continue;if(config3.disable===!0){editor.remove(name);continue}let mapped=mapV1AgentToV2(name,config3);editor.update(name,(agent)=>{let existingPermissions=Array.isArray(agent.permissions)?[...agent.permissions]:[];if(Object.assign(agent,mapped),mapped.permissions!==void 0)agent.permissions=[...existingPermissions,...mapped.permissions]})}}),V2_AGENT_COMMAND_CALL_TIMEOUT_MS,Error("[opencode-swarm] v2: agent transform exceeded budget"));registrations.push(agentRegistration),agentLanded=!0}catch(err){let message=err instanceof Error?err.message:String(err);log("v2 agent transform failed (non-fatal)",{error:message}),deferredV2WarnOperator(`[opencode-swarm] v2: agent registration failed (${message}); no v2 agents were registered.`,`agent-registration-failed:${directory}`,ownerToken)}let commandLanded=!1;try{let commandRegistration=await withTimeout(ctx.command.transform((editor)=>{for(let[key3,entry]of Object.entries(registrationSnapshot.commandTable)){if(!entry||typeof entry!=="object")continue;let template=typeof entry.template==="string"?entry.template:void 0;if(template===void 0)continue;let definition={name:key3,description:typeof entry.description==="string"?entry.description:void 0,execute:(invocation)=>deferredV2ExecuteSwarmCommand(hooks2,key3,template,ctx,invocation,directory,registrations)};editor.add(definition)}}),V2_AGENT_COMMAND_CALL_TIMEOUT_MS,Error("[opencode-swarm] v2: command transform exceeded budget"));registrations.push(commandRegistration),commandLanded=!0}catch(err){let message=err instanceof Error?err.message:String(err);log("v2 command transform failed (non-fatal)",{error:message}),deferredV2WarnOperator(`[opencode-swarm] v2: command registration failed (${message}); the v2 command table was not registered.`,`command-registration-failed:${directory}`,ownerToken)}if(log("v2 agents + commands registered",{directory,agents:Object.keys(agentTable).length,commands:Object.keys(commandTable).length}),!agentLanded&&!commandLanded)throw Error("[opencode-swarm] v2: agent and command registrations both failed")}function registerV2ConfigRebuildSourceForOwner(token,rebuild){if(rebuild===void 0){let entry2=v2OwnerStates.get(token);if(entry2!==void 0)entry2.rebuild=void 0,dropV2OwnerEntryIfEmpty(token);return}let entry=v2OwnerEntry(token,!0);if(entry===void 0)return;entry.rebuild=rebuild,currentV2OwnerToken=token}async function deferredV2ReloadRegistrationDomain(ctx,domain3){let reload=ctx[domain3]?.reload;if(typeof reload!=="function")return!1;try{return await withTimeout(Promise.resolve(reload()),V2_AGENT_COMMAND_CALL_TIMEOUT_MS,Error(`[opencode-swarm] v2: ${domain3} registration reload exceeded budget`)),!0}catch(err){return log(`v2 ${domain3} registration reload failed (non-fatal)`,{error:err instanceof Error?err.message:String(err)}),!1}}async function deferredV2RefreshRegistrations(ctx,hooks2,directory,registrations){let ownerToken=resolveV2OwnerTokenForCtx(ctx),rebuild=resolveV2ConfigRebuildSourceForToken(ownerToken);if(rebuild===void 0){deferredV2WarnOperator("[opencode-swarm] v2: registration refresh skipped — no config rebuild source is registered on this host; the registration tables were not reloaded.",`refresh-no-rebuild-source:${directory}`,ownerToken);return}let tables;try{tables=await withTimeout(Promise.resolve(rebuild(directory)),V2_AGENT_COMMAND_CALL_TIMEOUT_MS,Error("[opencode-swarm] v2: registration rebuild exceeded budget"))}catch(err){deferredV2WarnOperator(`[opencode-swarm] v2: registration refresh failed — the config rebuild source errored (${err instanceof Error?err.message:String(err)}); the registration tables were not reloaded.`,`refresh-rebuild-failed:${directory}`,ownerToken);return}let snapshot=resolveV2RegistrationSnapshotForToken(ownerToken);if(snapshot===void 0){log("v2 registration refresh skipped — no registration snapshot",{directory});return}if(!(snapshot.dirtyAgent||snapshot.dirtyCommand||JSON.stringify(snapshot.agentTable)!==JSON.stringify(tables.agentTable)||JSON.stringify(snapshot.commandTable)!==JSON.stringify(tables.commandTable))){log("v2 registration refresh — tables unchanged, no reload",{directory,registrations:registrations?.length??0,hooksConfigPresent:typeof hooks2.config==="function"});return}snapshot.agentTable=tables.agentTable,snapshot.commandTable=tables.commandTable;let agentReloaded=await deferredV2ReloadRegistrationDomain(ctx,"agent");snapshot.dirtyAgent=!agentReloaded;let commandReloaded=await deferredV2ReloadRegistrationDomain(ctx,"command");if(snapshot.dirtyCommand=!commandReloaded,!agentReloaded||!commandReloaded){let failed=[agentReloaded?void 0:"agent",commandReloaded?void 0:"command"].filter((domain3)=>domain3!==void 0).join(", ");deferredV2WarnOperator(`[opencode-swarm] v2: registration tables changed but the ${failed} domain reload failed; the domain stays marked dirty and the next refresh retries it.`,`refresh-reload-failed:${directory}`,ownerToken)}log("v2 registration tables refreshed",{directory,registrations:registrations?.length??0,agentReloaded,commandReloaded})}init_task_model_routing();init_utils();init_timeout();init_state2();init_normalize_tool_name();init_shell_executor_context();init_warning_buffer();init_utils();init_timeout();var DEFAULT_CONFIG2={oversightTotalMs:120000},budgets=new Map;function finitePositive(value){return typeof value==="number"&&Number.isFinite(value)&&value>0?value:void 0}function configureV2ToolBeforeBudget(fullAuto,directory){let oversight=fullAuto?.oversight,hook=finitePositive(oversight?.hook_timeout_ms),key3=directory??"";if(!budgets.has(key3)&&budgets.size>=64){let oldest=budgets.keys().next().value;if(oldest!==void 0)budgets.delete(oldest)}budgets.set(key3,{...hook!==void 0?{hookTimeoutMs:Math.min(900000,Math.round(hook))}:{},oversightTotalMs:finitePositive(oversight?.total_timeout_ms)??120000})}function resolveV2ToolBeforeBudgetMs(fullAutoActive,directory){let cfg=(directory!==void 0?budgets.get(directory):void 0)??budgets.get("")??DEFAULT_CONFIG2;if(cfg.hookTimeoutMs!==void 0)return cfg.hookTimeoutMs;if(!fullAutoActive)return 60000;return Math.min(900000,Math.max(60000,cfg.oversightTotalMs+30000))}function resetV2ToolBeforeBudget(directory){if(directory===void 0)budgets.clear();else budgets.delete(directory)}var V2_HOOK_TIMEOUT_MS=60000;function isV2SubagentToolId(toolName){if(!toolName)return!1;if(toolName.includes("."))return/^tool\.[^.:]+\.subagent$/i.test(toolName);return normalizeToolNameLowerCase(toolName)==="subagent"}function isV2CodeModeWrapper(event){return event.tool==="execute"&&isPlainObject9(event.input)&&typeof event.input.code==="string"}function isPlainObject9(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}function mapV2SubagentArgsToV1(input){if(!isPlainObject9(input))return input;let mapped={};for(let[key3,value]of Object.entries(input))if(key3==="agent")mapped.subagent_type=value;else if(key3==="sessionID")mapped.task_id=value;else mapped[key3]=value;return mapped}function mapV1TaskArgsToV2(args2){if(!isPlainObject9(args2))return args2;let mapped={};for(let[key3,value]of Object.entries(args2))if(key3==="subagent_type")mapped.agent=value;else if(key3==="task_id")mapped.sessionID=value;else mapped[key3]=value;return mapped}var V2_SUBAGENT_WRAPPER_RE=/<subagent\s+sessionID="([^"]+)"\s+state="(running|completed|error|cancelled|canceled)"[^>]*>/,MAX_V2_WRAPPER_INNER_CHARS=20000;function parseV2SubagentWrapper(content){if(typeof content!=="string")return null;let match=content.match(V2_SUBAGENT_WRAPPER_RE);if(!match)return null;let sessionID=match[1];if(sessionID.includes("<")||sessionID.includes(">"))return null;let rawState=match[2],matchStart=match.index??0,inner=content.slice(matchStart+match[0].length).replace(/\s*<\/subagent>\s*$/,"");return{sessionID,state:rawState==="canceled"?"cancelled":rawState,inner}}var V2_WRAPPER_STRUCTURAL_TAG_RE=/<\/?(?:task_result|task_error|summary)>/g;function renderV1TaskEnvelopeFromV2(wrapper){let inner=wrapper.inner;if(inner.length>MAX_V2_WRAPPER_INNER_CHARS){let omitted=inner.length-MAX_V2_WRAPPER_INNER_CHARS;inner=`${inner.slice(0,MAX_V2_WRAPPER_INNER_CHARS)}
|
|
7469
7469
|
[... ${omitted} chars truncated by v2 task translation ...]`}return inner=inner.replace(V2_WRAPPER_STRUCTURAL_TAG_RE,(tag)=>tag.replace("<","<\\")),`<task id="${wrapper.sessionID}" state="${wrapper.state}"><task_result>${inner}</task_result></task>`}function isFullAutoRunActive2(directory,sessionID){try{let status2=loadFullAutoRunState(directory,sessionID)?.status;return status2!==void 0&&status2!=="idle"}catch{return!1}}async function onV2ToolBefore(event,hooks2,directory){let handler=hooks2["tool.execute.before"];if(typeof handler!=="function")return;seedV1SessionState(event.sessionID,event.agent,directory);let isSubagent2=isV2SubagentToolId(event.tool),wrapperMarked=isV2CodeModeWrapper(event);if(wrapperMarked)recordCodeModeWrapperCall(event.sessionID,event.id);try{let output={args:isSubagent2?mapV2SubagentArgsToV1(event.input):event.input},budgetMs=resolveV2ToolBeforeBudgetMs(isFullAutoRunActive2(directory,event.sessionID),directory);if(await withTimeout(Promise.resolve(handler({tool:isSubagent2?"task":event.tool,sessionID:event.sessionID,callID:event.id,agent:normalizeV2AgentRef(event.agent),messageID:event.messageID},output)),budgetMs,Error(`[opencode-swarm] v2: tool.execute.before exceeded budget (${budgetMs} ms; set full_auto.oversight.hook_timeout_ms to change)`)),isSubagent2){let mapped=mapV1TaskArgsToV2(output.args);if(isPlainObject9(event.input)&&isPlainObject9(mapped)){for(let key3 of Object.keys(event.input))delete event.input[key3];Object.assign(event.input,mapped)}}else event.input=output.args}finally{if(wrapperMarked)clearCodeModeWrapperCall(event.sessionID,event.id)}}async function onV2ToolAfter(event,hooks2,directory){clearCodeModeWrapperCall(event.sessionID,event.id);let handler=hooks2["tool.execute.after"];if(typeof handler!=="function")return;seedV1SessionState(event.sessionID,event.agent,directory);let isSubagent2=isV2SubagentToolId(event.tool),output=translateV2ResultToV1Output(event,isSubagent2);await withTimeout(Promise.resolve(handler({tool:isSubagent2?"task":event.tool,sessionID:event.sessionID,callID:event.id,agent:normalizeV2AgentRef(event.agent),messageID:event.messageID,...isSubagent2?{args:mapV2SubagentArgsToV1(event.input)}:{}},output)),V2_HOOK_TIMEOUT_MS,Error("[opencode-swarm] v2: tool.execute.after exceeded budget")).catch((err)=>{log("v2 tool.execute.after failed (non-fatal)",{tool:event.tool,error:err instanceof Error?err.message:String(err)})})}function translateV2ResultToV1Output(event,isSubagent2){if(event.status==="error")return{title:"error",state:"error",output:event.error&&typeof event.error.message==="string"?event.error.message:"tool error",metadata:{}};let result=event.result,content=typeof result?.content==="string"?result.content:Array.isArray(result?.content)?(result?.content).filter((p)=>p.type==="text"&&typeof p.text==="string").map((p)=>p.text).join(`
|
|
7470
|
-
`):"";if(isSubagent2){let wrapper=parseV2SubagentWrapper(content);if(wrapper)return{title:"",state:wrapper.state==="running"?"running":wrapper.state==="completed"?"completed":wrapper.state==="error"?"error":"cancelled",output:renderV1TaskEnvelopeFromV2(wrapper),metadata:result?.metadata??{}};if(content.includes("<subagent"))log("v2 subagent wrapper not recognized; passing result text through",{chars:content.length})}return{title:"",state:"completed",output:content,metadata:result?.metadata??{}}}async function onV2Compaction(event,hooks2,directory){let handler=hooks2["experimental.session.compacting"];if(typeof handler!=="function")return;seedV1SessionState(event.sessionID,event.agent,directory);let model=event.model,output={};await withTimeout(Promise.resolve(handler({sessionID:event.sessionID,providerID:typeof model?.providerID==="string"?model.providerID:"unknown",modelID:typeof model?.id==="string"?model.id:"unknown"},output)),V2_HOOK_TIMEOUT_MS,Error("[opencode-swarm] v2: compaction hook exceeded budget")).catch((err)=>{log("v2 compaction hook failed (non-fatal)",{error:err instanceof Error?err.message:String(err)})})}async function onV2Prompt(event,hooks2){let handler=hooks2["chat.message"];if(typeof handler!=="function")return;let text=event.prompt?.text??"",message={id:event.messageID,role:"user",sessionID:event.sessionID},parts=[{type:"text",text}],input={sessionID:event.sessionID,message:{...message},parts:[...parts]},output={message:{...message},parts:[...parts]};if(await withTimeout(Promise.resolve(handler(input,output)),V2_HOOK_TIMEOUT_MS,Error("[opencode-swarm] v2: prompt hook exceeded budget")).catch((err)=>{log("v2 prompt (chat.message) hook failed (non-fatal)",{error:err instanceof Error?err.message:String(err)})}),typeof event.prompt==="object"&&event.prompt!==null){let rewritten=output.parts.find((p)=>p.type==="text"&&typeof p.text==="string");if(rewritten&&typeof rewritten.text==="string"&&rewritten.text!==text)event.prompt.text=rewritten.text}}function warnV2HookRegistrationFailure(label,err){let message=err instanceof Error?err.message:String(err);log(`v2 ${label} registration failed (non-fatal)`,{error:message}),addDeferredWarning(`[opencode-swarm] v2: ${label} registration failed (${message}); the hook was not installed on this host.`)}async function registerV2ToolHooks(ctx,hooks2,directory,registrations){let before=await withTimeout(ctx.tool.hook("execute.before",async(event)=>{return onV2ToolBefore(event,hooks2,directory)}),V2_HOOK_TIMEOUT_MS,Error("[opencode-swarm] v2: execute.before registration exceeded budget")).catch((err)=>{warnV2HookRegistrationFailure("execute.before",err);return});if(before!==void 0)registrations.push(before);let after=await withTimeout(ctx.tool.hook("execute.after",async(event)=>{return onV2ToolAfter(event,hooks2,directory)}),V2_HOOK_TIMEOUT_MS,Error("[opencode-swarm] v2: execute.after registration exceeded budget")).catch((err)=>{warnV2HookRegistrationFailure("execute.after",err);return});if(after!==void 0)registrations.push(after);if(before===void 0&&after===void 0)throw Error("[opencode-swarm] v2: execute.before and execute.after registrations both failed")}async function registerV2SessionHooks(ctx,hooks2,directory,registrations){let compaction=await withTimeout(ctx.session.hook("compaction",async(event)=>{return onV2Compaction(event,hooks2,directory)}),V2_HOOK_TIMEOUT_MS,Error("[opencode-swarm] v2: compaction registration exceeded budget")).catch((err)=>{warnV2HookRegistrationFailure("compaction",err);return});if(compaction!==void 0)registrations.push(compaction);let prompt=await withTimeout(ctx.session.hook("prompt",async(event)=>{return onV2Prompt(event,hooks2)}),V2_HOOK_TIMEOUT_MS,Error("[opencode-swarm] v2: prompt registration exceeded budget")).catch((err)=>{warnV2HookRegistrationFailure("prompt",err);return});if(prompt!==void 0)registrations.push(prompt);if(compaction===void 0&&prompt===void 0)throw Error("[opencode-swarm] v2: compaction and prompt registrations both failed")}init_canonical_root();init_logger();init_timeout();var SYSTEM_DIRECTIVE_FENCE_OPEN="<swarm_system_directive",MAX_PLACEHOLDER_SESSIONS=64,MAX_RECORDED_SESSION_ERRORS=128,ERROR_RECHECK_ATTEMPTS=3,ERROR_RECHECK_DELAY_MS=50,SIGNAL_LESS_WAIT_CAP_MS=600000,placeholderSessions=new Map,sessionErrors=new Map,placeholderCounter=0;function rememberPlaceholder(id,record3){placeholderSessions.set(id,record3);while(placeholderSessions.size>MAX_PLACEHOLDER_SESSIONS){let oldest=placeholderSessions.keys().next().value;if(oldest===void 0)break;placeholderSessions.delete(oldest)}}function rememberSessionError(sessionId,error93){sessionErrors.set(sessionId,error93);while(sessionErrors.size>MAX_RECORDED_SESSION_ERRORS){let oldest=sessionErrors.keys().next().value;if(oldest===void 0)break;sessionErrors.delete(oldest)}}function recordV2SessionErrorFromEnvelope(envelope){let type=typeof envelope?.type==="string"?envelope.type:void 0;if(type!=="session.error"&&type!=="session.execution.failed")return;let payload=envelope.data??envelope.properties??{},sessionID=typeof payload.sessionID==="string"?payload.sessionID:void 0,error93=payload.error;if(sessionID!==void 0&&error93!==void 0)rememberSessionError(sessionID,error93)}function clearV2SessionClientState(){placeholderSessions.clear(),sessionErrors.clear()}function readOnlyToolsToV2Permissions(tools){if(!tools||typeof tools!=="object")return[];let permissions=[];for(let resource of Object.keys(tools)){if(resource.length===0)continue;permissions.push({action:"tool",resource,effect:"deny"})}return permissions}function sameDirectoryLexical(a,b){return canonicalRootKeyLexical(a)===canonicalRootKeyLexical(b)}function isAssistantEntry(entry){if(!entry||typeof entry!=="object")return!1;let record3=entry;if(record3.role==="assistant")return!0;return typeof record3.type==="string"&&record3.type.includes("assistant")}function isUserEntry(entry){if(!entry||typeof entry!=="object")return!1;let record3=entry;if(record3.role==="user")return!0;return typeof record3.type==="string"&&record3.type.includes("user")}function entryText2(entry){if(!entry||typeof entry!=="object")return;let record3=entry;if(typeof record3.text==="string")return record3.text;let blocks=Array.isArray(record3.content)?record3.content:Array.isArray(record3.parts)?record3.parts:void 0;if(!blocks)return;let texts=[];for(let block of blocks)if(block&&typeof block==="object"&&block.type==="text"&&typeof block.text==="string")texts.push(block.text);return texts.length>0?texts.join(`
|
|
7470
|
+
`):"";if(isSubagent2){let wrapper=parseV2SubagentWrapper(content);if(wrapper)return{title:"",state:wrapper.state==="running"?"running":wrapper.state==="completed"?"completed":wrapper.state==="error"?"error":"cancelled",output:renderV1TaskEnvelopeFromV2(wrapper),metadata:result?.metadata??{}};if(content.includes("<subagent"))log("v2 subagent wrapper not recognized; passing result text through",{chars:content.length})}return{title:"",state:"completed",output:content,metadata:result?.metadata??{}}}async function onV2Compaction(event,hooks2,directory){let handler=hooks2["experimental.session.compacting"];if(typeof handler!=="function")return;seedV1SessionState(event.sessionID,event.agent,directory);let model=event.model,output={};await withTimeout(Promise.resolve(handler({sessionID:event.sessionID,providerID:typeof model?.providerID==="string"?model.providerID:"unknown",modelID:typeof model?.id==="string"?model.id:"unknown"},output)),V2_HOOK_TIMEOUT_MS,Error("[opencode-swarm] v2: compaction hook exceeded budget")).catch((err)=>{log("v2 compaction hook failed (non-fatal)",{error:err instanceof Error?err.message:String(err)})})}async function onV2Prompt(event,hooks2){let handler=hooks2["chat.message"];if(typeof handler!=="function")return;let text=event.prompt?.text??"",message={id:event.messageID,role:"user",sessionID:event.sessionID},parts=[{type:"text",text}],input={sessionID:event.sessionID,message:{...message},parts:[...parts]},output={message:{...message},parts:[...parts]};if(await withTimeout(Promise.resolve(handler(input,output)),V2_HOOK_TIMEOUT_MS,Error("[opencode-swarm] v2: prompt hook exceeded budget")).catch((err)=>{log("v2 prompt (chat.message) hook failed (non-fatal)",{error:err instanceof Error?err.message:String(err)})}),typeof event.prompt==="object"&&event.prompt!==null){let rewritten=output.parts.find((p)=>p.type==="text"&&typeof p.text==="string");if(rewritten&&typeof rewritten.text==="string"&&rewritten.text!==text)event.prompt.text=rewritten.text}}function warnV2HookRegistrationFailure(label,err){let message=err instanceof Error?err.message:String(err);log(`v2 ${label} registration failed (non-fatal)`,{error:message}),addDeferredWarning(`[opencode-swarm] v2: ${label} registration failed (${message}); the hook was not installed on this host.`)}async function registerV2ToolHooks(ctx,hooks2,directory,registrations){let before=await withTimeout(ctx.tool.hook("execute.before",async(event)=>{return onV2ToolBefore(event,hooks2,directory)}),V2_HOOK_TIMEOUT_MS,Error("[opencode-swarm] v2: execute.before registration exceeded budget")).catch((err)=>{warnV2HookRegistrationFailure("execute.before",err);return});if(before!==void 0)registrations.push(before);let after=await withTimeout(ctx.tool.hook("execute.after",async(event)=>{return onV2ToolAfter(event,hooks2,directory)}),V2_HOOK_TIMEOUT_MS,Error("[opencode-swarm] v2: execute.after registration exceeded budget")).catch((err)=>{warnV2HookRegistrationFailure("execute.after",err);return});if(after!==void 0)registrations.push(after);if(before===void 0&&after===void 0)throw Error("[opencode-swarm] v2: execute.before and execute.after registrations both failed")}async function registerV2SessionHooks(ctx,hooks2,directory,registrations){let compaction=await withTimeout(ctx.session.hook("compaction",async(event)=>{return onV2Compaction(event,hooks2,directory)}),V2_HOOK_TIMEOUT_MS,Error("[opencode-swarm] v2: compaction registration exceeded budget")).catch((err)=>{warnV2HookRegistrationFailure("compaction",err);return});if(compaction!==void 0)registrations.push(compaction);let prompt=await withTimeout(ctx.session.hook("prompt",async(event)=>{return onV2Prompt(event,hooks2)}),V2_HOOK_TIMEOUT_MS,Error("[opencode-swarm] v2: prompt registration exceeded budget")).catch((err)=>{warnV2HookRegistrationFailure("prompt",err);return});if(prompt!==void 0)registrations.push(prompt);if(compaction===void 0&&prompt===void 0)throw Error("[opencode-swarm] v2: compaction and prompt registrations both failed")}async function registerV2ShellHooks(ctx,registrations){let shellDomain=ctx.shell;if(!shellDomain||typeof shellDomain.hook!=="function")return;let registration=await withTimeout(Promise.resolve(shellDomain.hook("create.before",(invocation)=>{let shell=invocation&&typeof invocation.shell==="string"?invocation.shell:"";recordObservedHostShell(shell)})),V2_HOOK_TIMEOUT_MS,Error("[opencode-swarm] v2: shell.create.before registration exceeded budget")).catch((err)=>{warnV2HookRegistrationFailure("shell.create.before",err);return});if(registration!==void 0&®istration!==null)registrations.push(registration)}init_canonical_root();init_logger();init_timeout();var SYSTEM_DIRECTIVE_FENCE_OPEN="<swarm_system_directive",MAX_PLACEHOLDER_SESSIONS=64,MAX_RECORDED_SESSION_ERRORS=128,ERROR_RECHECK_ATTEMPTS=3,ERROR_RECHECK_DELAY_MS=50,SIGNAL_LESS_WAIT_CAP_MS=600000,placeholderSessions=new Map,sessionErrors=new Map,placeholderCounter=0;function rememberPlaceholder(id,record3){placeholderSessions.set(id,record3);while(placeholderSessions.size>MAX_PLACEHOLDER_SESSIONS){let oldest=placeholderSessions.keys().next().value;if(oldest===void 0)break;placeholderSessions.delete(oldest)}}function rememberSessionError(sessionId,error93){sessionErrors.set(sessionId,error93);while(sessionErrors.size>MAX_RECORDED_SESSION_ERRORS){let oldest=sessionErrors.keys().next().value;if(oldest===void 0)break;sessionErrors.delete(oldest)}}function recordV2SessionErrorFromEnvelope(envelope){let type=typeof envelope?.type==="string"?envelope.type:void 0;if(type!=="session.error"&&type!=="session.execution.failed")return;let payload=envelope.data??envelope.properties??{},sessionID=typeof payload.sessionID==="string"?payload.sessionID:void 0,error93=payload.error;if(sessionID!==void 0&&error93!==void 0)rememberSessionError(sessionID,error93)}function clearV2SessionClientState(){placeholderSessions.clear(),sessionErrors.clear()}function readOnlyToolsToV2Permissions(tools){if(!tools||typeof tools!=="object")return[];let permissions=[];for(let resource of Object.keys(tools)){if(resource.length===0)continue;permissions.push({action:"tool",resource,effect:"deny"})}return permissions}function sameDirectoryLexical(a,b){return canonicalRootKeyLexical(a)===canonicalRootKeyLexical(b)}function isAssistantEntry(entry){if(!entry||typeof entry!=="object")return!1;let record3=entry;if(record3.role==="assistant")return!0;return typeof record3.type==="string"&&record3.type.includes("assistant")}function isUserEntry(entry){if(!entry||typeof entry!=="object")return!1;let record3=entry;if(record3.role==="user")return!0;return typeof record3.type==="string"&&record3.type.includes("user")}function entryText2(entry){if(!entry||typeof entry!=="object")return;let record3=entry;if(typeof record3.text==="string")return record3.text;let blocks=Array.isArray(record3.content)?record3.content:Array.isArray(record3.parts)?record3.parts:void 0;if(!blocks)return;let texts=[];for(let block of blocks)if(block&&typeof block==="object"&&block.type==="text"&&typeof block.text==="string")texts.push(block.text);return texts.length>0?texts.join(`
|
|
7471
7471
|
`):void 0}function entryModelIds(entry){if(!entry||typeof entry!=="object")return{};let record3=entry,providerID=typeof record3.model?.providerID==="string"?record3.model.providerID:typeof record3.providerID==="string"?record3.providerID:void 0,modelID=typeof record3.model?.id==="string"?record3.model.id:typeof record3.modelID==="string"?record3.modelID:void 0;return{providerID,modelID}}function idleOutcome(entries2){for(let i=entries2.length-1;i>=0;i-=1){let entry=entries2[i];if(!entry||typeof entry!=="object")continue;let record3=entry;if(record3.type!=="idle")continue;return typeof record3.outcome==="string"?record3.outcome:void 0}return}function recordedErrorToInfoError(error93){if(error93&&typeof error93==="object"){let record3=error93,message=typeof record3.data?.message==="string"&&record3.data.message.length>0?record3.data.message:typeof record3.message==="string"&&record3.message.length>0?record3.message:"no message",statusCodeValue=typeof record3.data?.statusCode==="number"&&Number.isFinite(record3.data.statusCode)?record3.data.statusCode:typeof record3.statusCode==="number"&&Number.isFinite(record3.statusCode)?record3.statusCode:typeof record3.status==="number"&&Number.isFinite(record3.status)?record3.status:void 0;return{name:typeof record3.name==="string"&&record3.name.length>0?record3.name.slice(0,64):"ProviderError",data:{message,...statusCodeValue===void 0?{}:{statusCode:statusCodeValue}}}}return{name:"ProviderError",data:{message:"v2 session failed without recorded error detail"}}}function classifyContextEntries(entries2){let lastUserIndex=entries2.reduce((last,entry,index)=>isUserEntry(entry)?index:last,-1),assistantEntries=entries2.slice(lastUserIndex+1).filter(isAssistantEntry),texts=assistantEntries.map(entryText2).filter((text)=>typeof text==="string"),outcome=idleOutcome(entries2);return{outcome,texts,model:assistantEntries.reduce((acc,entry)=>{let ids=entryModelIds(entry);if(ids.providerID!==void 0&&ids.modelID!==void 0)return{providerID:ids.providerID,modelID:ids.modelID};return acc},{}),needsErrorLookup:outcome==="failed"||outcome===void 0&&texts.length===0}}function buildTranslatedPromptData(classification,recordedError){if(classification.needsErrorLookup||recordedError!==void 0)return{info:{error:recordedErrorToInfoError(recordedError)},parts:[]};return{info:classification.model,parts:classification.texts.map((text)=>({type:"text",text}))}}async function deferredV2SessionErrorRecheck(realId){for(let attempt=0;attempt<ERROR_RECHECK_ATTEMPTS;attempt+=1){if(sessionErrors.has(realId))return sessionErrors.get(realId);if(attempt<ERROR_RECHECK_ATTEMPTS-1)await new Promise((resolve124)=>setTimeout(resolve124,ERROR_RECHECK_DELAY_MS))}return}async function deferredV2SessionTranslate(entries2,sessionId){let classification=classifyContextEntries(entries2),recordedError=sessionErrors.get(sessionId);if(classification.needsErrorLookup&&recordedError===void 0)recordedError=await deferredV2SessionErrorRecheck(sessionId);return buildTranslatedPromptData(classification,recordedError)}async function deferredV2SessionGetParentDirectory(ctx,parentID){let info=await ctx.session.get({sessionID:parentID});if(!info||typeof info!=="object")return;let location=info.location;return typeof location?.directory==="string"?location.directory:void 0}async function deferredV2SessionWait(ctx,realId,signal2){if(signal2?.aborted)throw await ctx.session.interrupt({sessionID:realId}).catch(()=>{return}),Error("v2 session-client: prompt wait aborted");await new Promise((resolve124,reject3)=>{let settled=!1,timer=signal2===void 0?setTimeout(()=>{if(settled)return;settled=!0,ctx.session.interrupt({sessionID:realId}).catch(()=>{return}).finally(()=>{reject3(Error("v2 session-client: signal-less prompt wait exceeded cap"))})},SIGNAL_LESS_WAIT_CAP_MS):void 0,onAbort=()=>{if(settled)return;if(settled=!0,timer!==void 0)clearTimeout(timer);ctx.session.interrupt({sessionID:realId}).catch(()=>{return}).finally(()=>{reject3(Error("v2 session-client: prompt wait aborted"))})};signal2?.addEventListener("abort",onAbort,{once:!0}),Promise.resolve(ctx.session.wait({sessionID:realId})).then(()=>{if(settled)return;if(settled=!0,timer!==void 0)clearTimeout(timer);signal2?.removeEventListener("abort",onAbort),resolve124()}).catch((error93)=>{if(settled)return;if(settled=!0,timer!==void 0)clearTimeout(timer);signal2?.removeEventListener("abort",onAbort),reject3(error93 instanceof Error?error93:String(error93))})})}function makeV2SessionContextHandler(realId,system,tools){return(event)=>{let typed=event;if(!typed||typed.sessionID!==realId)return Promise.resolve();if(system!==void 0&&Array.isArray(typed.system)){let fenced=typed.system.filter((part)=>part&&typeof part.text==="string"&&part.text.includes(SYSTEM_DIRECTIVE_FENCE_OPEN));typed.system.length=0,typed.system.push(...fenced.map((part)=>({type:"text",text:part.text})),{type:"text",text:system})}if(tools&&typed.tools&&typeof typed.tools==="object"){let deleted=0;for(let name of Object.keys(tools))if(Object.hasOwn(typed.tools,name))delete typed.tools[name],deleted+=1;if(deleted>0)log("v2 session-client: denied tools via context hook",{count:deleted})}return Promise.resolve()}}function promptBodyText(parts){if(!Array.isArray(parts))return"";let texts=[];for(let part of parts)if(part&&typeof part==="object"&&part.type==="text"&&typeof part.text==="string")texts.push(part.text);return texts.join(`
|
|
7472
|
-
`)}async function deferredV2SessionPromptPlaceholder(ctx,_placeholderId,stash,body,text,signal2){if(stash.promptStarted=!0,signal2?.aborted)throw Error("v2 session-client: prompt wait aborted");let previousRealId=stash.realId;if(previousRealId!==void 0)stash.realId=void 0,stash.abortPending=!1,stash.deletePending=!1,await ctx.session.remove({sessionID:previousRealId}).catch(()=>{return});let agent=typeof body.agent==="string"?body.agent:void 0,model=body.model&&typeof body.model.providerID==="string"&&typeof body.model.modelID==="string"?{id:body.model.modelID,providerID:body.model.providerID}:void 0,system=typeof body.system==="string"?body.system:void 0,createdRecord=await ctx.session.create({...stash.parentID!==void 0?{parentID:stash.parentID}:{},...stash.title!==void 0?{title:stash.title}:{},...agent!==void 0?{agent}:{},...model!==void 0?{model}:{},location:{directory:stash.directory},permissions:readOnlyToolsToV2Permissions(body.tools)}),realId=typeof createdRecord?.id==="string"?createdRecord.id:void 0;if(realId===void 0)throw Error("v2 session-client: session create returned no id");let echoedDirectory=typeof createdRecord.location?.directory==="string"?createdRecord.location.directory:void 0;if(echoedDirectory!==void 0&&!sameDirectoryLexical(echoedDirectory,stash.directory))throw await ctx.session.remove({sessionID:realId}).catch(()=>{return}),Error(`v2 session-client: created session landed in ${echoedDirectory}, not the requested ${stash.directory} (#3169 Phase 0 C1)`);sessionErrors.delete(realId);let registration;try{if(system!==void 0||body.tools!==void 0)registration=await ctx.session.hook("context",makeV2SessionContextHandler(realId,system,body.tools));await ctx.session.prompt({sessionID:realId,text}),await deferredV2SessionWait(ctx,realId,signal2);let entries2=await ctx.session.context({sessionID:realId});return{data:await deferredV2SessionTranslate(Array.isArray(entries2)?entries2:[],realId)}}finally{if(stash.realId=realId,registration?.dispose)await registration.dispose().catch(()=>{return});if(stash.abortPending)await ctx.session.interrupt({sessionID:realId}).catch(()=>{return});if(stash.deletePending)sessionErrors.delete(realId),await ctx.session.remove({sessionID:realId}).catch(()=>{return})}}async function deferredV2SessionPromptReal(ctx,sessionId,body,text,signal2){if(typeof body.agent==="string"){let switchAgent=ctx.session.switchAgent;if(typeof switchAgent==="function")await switchAgent({sessionID:sessionId,agent:body.agent})}sessionErrors.delete(sessionId),await ctx.session.prompt({sessionID:sessionId,text}),await deferredV2SessionWait(ctx,sessionId,signal2);let entries2=await ctx.session.context({sessionID:sessionId});return{data:await deferredV2SessionTranslate(Array.isArray(entries2)?entries2:[],sessionId)}}function resolveSessionId(id){let stash=placeholderSessions.get(id);if(stash===void 0)return id;return stash.realId}function createV2SessionClient(ctx){let session=ctx?.session;if(!session||typeof session!=="object")return;for(let member of["create","get","remove","prompt","wait","context","interrupt","hook"])if(typeof session[member]!=="function")return;return{session:{create:(args2)=>deferredV2SessionCreate(ctx,args2),prompt:(args2)=>deferredV2SessionPrompt(ctx,args2),abort:(args2)=>{let id=args2?.path?.id,resolved=resolveSessionId(id);if(resolved!==void 0)return ctx.session.interrupt({sessionID:resolved}).catch(()=>{return});let stash=placeholderSessions.get(id);if(stash?.promptStarted)stash.abortPending=!0;return Promise.resolve(void 0)},delete:(args2)=>{let id=args2?.path?.id,stash=placeholderSessions.get(id),resolved=resolveSessionId(id);if(resolved!==void 0)return sessionErrors.delete(resolved),deferredV2SessionRemoveEager(ctx,resolved).then((outcome)=>{if(stash?.eager===!0&&outcome.ok)placeholderSessions.delete(id);else if(stash?.eager===!0)log("v2 session-client: eager delete cleanup failed",{reason:outcome.reason})});if(stash?.promptStarted)stash.deletePending=!0;return Promise.resolve(void 0)},get:(args2)=>{let id=args2?.path?.id,stash=placeholderSessions.get(id),overlayParentID=stash?.eager===!0&&typeof stash.parentID==="string"?stash.parentID:void 0,resolved=resolveSessionId(id);if(resolved===void 0)return Promise.resolve({data:null});return ctx.session.get({sessionID:resolved}).then((info)=>({data:overlayParentID!==void 0&&info&&typeof info==="object"?{...info,parentID:overlayParentID}:info})).catch((error93)=>({data:null,error:error93}))}}}}var MAX_PATH_IN_MESSAGE_CHARS=200;function boundPathForMessage(path321){if(path321===void 0)return"an unverifiable location";if(path321.length<=MAX_PATH_IN_MESSAGE_CHARS)return path321;return`${path321.slice(0,MAX_PATH_IN_MESSAGE_CHARS)}… (truncated)`}var EAGER_CLEANUP_TIMEOUT_MS=1e4;async function deferredV2SessionRemoveEager(ctx,sessionID){try{return await withTimeout(ctx.session.remove({sessionID}),EAGER_CLEANUP_TIMEOUT_MS,Error(`v2 session-client: eager cleanup of session ${sessionID} exceeded ${EAGER_CLEANUP_TIMEOUT_MS}ms`)),{ok:!0}}catch(error93){return{ok:!1,reason:error93 instanceof Error?error93.message:String(error93)}}}async function deferredV2SessionCreateEager(ctx,parentID,title,directory,signal2){let created;try{created=await ctx.session.create({...title!==void 0?{title}:{},location:{directory}})}catch(error93){return{data:null,error:{message:`v2 session-client: eager lane create failed (${error93 instanceof Error?error93.message:String(error93)})`}}}let createdRecord=created,realId=typeof createdRecord?.id==="string"?createdRecord.id:void 0;if(realId===void 0)return{data:null,error:{message:"v2 session-client: eager lane create returned no id (#3169 Phase 3)"}};if(signal2?.aborted){let compensated=await deferredV2SessionRemoveEager(ctx,realId);if(!compensated.ok)log("v2 session-client: aborted eager create compensation failed",{reason:compensated.reason});return{data:null,error:{message:`v2 session-client: eager lane create aborted by the caller; ${compensated.ok?"the created session was removed":`removing session ${realId} also failed (${compensated.reason??"unknown error"}) — remove it manually`}`,...compensated.ok?{}:{sessionID:realId,cleanupFailed:!0}}}}let landed=typeof createdRecord.location?.directory==="string"?createdRecord.location.directory:void 0;if(landed===void 0){let reported=await ctx.session.get({sessionID:realId}).catch(()=>{return});landed=typeof reported?.location?.directory==="string"?reported.location.directory:void 0}if(landed===void 0||!sameDirectoryLexical(landed,directory)){let removed=await deferredV2SessionRemoveEager(ctx,realId);return{data:null,error:{message:`v2 session-client: eager lane create landed in ${boundPathForMessage(landed)}, not the requested ${boundPathForMessage(directory)} (#3169 Phase 3 placement guard; Phase 0 C1)${removed.ok?"":`; cleanup of session ${realId} also failed (${removed.reason??"unknown error"}) — remove it before retrying`}`,...removed.ok?{}:{sessionID:realId,cleanupFailed:!0}}}}return rememberPlaceholder(realId,{parentID,...title!==void 0?{title}:{},directory,realId,eager:!0}),{data:{id:realId}}}async function deferredV2SessionCreate(ctx,args2){let directory=args2?.query?.directory;if(typeof directory!=="string"||directory.length===0)return{data:null,error:{message:"v2 session-client: create requires query.directory (v1 contract)"}};let parentID=args2?.body?.parentID;if(parentID!==void 0){let parentDirectory=await deferredV2SessionGetParentDirectory(ctx,parentID).catch(()=>{return});if(parentDirectory===void 0)return{data:null,error:{message:"v2 session-client: parent session placement unverifiable (get returned no location.directory — live-verification item on #3169 Phase 2)"}};if(!sameDirectoryLexical(parentDirectory,directory))return deferredV2SessionCreateEager(ctx,parentID,args2?.body?.title,directory,args2?.signal)}placeholderCounter+=1;let placeholderId=`v2shim-${placeholderCounter}-${Math.random().toString(36).slice(2,10)}`;return rememberPlaceholder(placeholderId,{...parentID!==void 0?{parentID}:{},...args2?.body?.title!==void 0?{title:args2.body.title}:{},directory}),{data:{id:placeholderId}}}async function deferredV2SessionPromptEager(ctx,realId,body,text,signal2){if(signal2?.aborted)throw Error("v2 session-client: eager prompt aborted before dispatch");let agent=typeof body.agent==="string"?body.agent:void 0;if(agent!==void 0){let switchAgent=ctx.session.switchAgent;if(typeof switchAgent==="function")await switchAgent({sessionID:realId,agent});else log("v2 session-client: eager prompt skipped switchAgent (host lacks it)",{agent})}let model=body.model&&typeof body.model.providerID==="string"&&typeof body.model.modelID==="string"?{id:body.model.modelID,providerID:body.model.providerID}:void 0;if(model!==void 0){let switchModel=ctx.session.switchModel;if(typeof switchModel==="function")await switchModel({sessionID:realId,model});else log("v2 session-client: eager prompt skipped switchModel (host lacks it)",{model})}let system=typeof body.system==="string"?body.system:void 0;sessionErrors.delete(realId);let registration;try{if(system!==void 0||body.tools!==void 0)registration=await ctx.session.hook("context",makeV2SessionContextHandler(realId,system,body.tools));await ctx.session.prompt({sessionID:realId,text}),await deferredV2SessionWait(ctx,realId,signal2);let entries2=await ctx.session.context({sessionID:realId});return{data:await deferredV2SessionTranslate(Array.isArray(entries2)?entries2:[],realId)}}finally{if(registration?.dispose)await registration.dispose().catch(()=>{return})}}async function deferredV2SessionPrompt(ctx,args2){let id=args2?.path?.id;if(typeof id!=="string"||id.length===0)return{data:null,error:{message:"v2 session-client: prompt requires path.id"}};let body=args2?.body??{},text=promptBodyText(body.parts),stash=placeholderSessions.get(id);if(stash!==void 0&&stash.eager===!0&&stash.realId!==void 0)return deferredV2SessionPromptEager(ctx,stash.realId,body,text,args2?.signal);if(stash!==void 0)return deferredV2SessionPromptPlaceholder(ctx,id,stash,body,text,args2?.signal);return deferredV2SessionPromptReal(ctx,id,body,text,args2?.signal)}var V2_EVENT_BATCH_TIMEOUT_MS=60000,UNMAPPED_LOG_LIMIT=20;function envelopePayload(envelope){return envelope.data??envelope.properties??{}}var MAX_TRACKED_TOOL_NAME_CHARS=256,MAX_DISPATCH_ID_CHARS=256;function isBoundedId(value){return value.trim()!==""&&value.length<=MAX_DISPATCH_ID_CHARS}var MAX_TRACKED_TOOL_NAMES=512,toolNameByDispatchKey=new Map;function rememberToolNameFromEnvelope(envelope){if(envelope?.type!=="session.tool.input.started")return;let payload=envelopePayload(envelope),name=typeof payload.name==="string"?payload.name:void 0;if(!name||name.length>MAX_TRACKED_TOOL_NAME_CHARS)return;if(!isV2SubagentToolId(name))return;let sessionID=typeof payload.sessionID==="string"?payload.sessionID:void 0,callID=typeof payload.id==="string"?payload.id:void 0;if(!sessionID||!callID)return;if(!isBoundedId(sessionID)||!isBoundedId(callID))return;let key3=dispatchKey2(sessionID,callID);if(toolNameByDispatchKey.delete(key3),toolNameByDispatchKey.size>=MAX_TRACKED_TOOL_NAMES){let oldest=toolNameByDispatchKey.keys().next().value;if(oldest!==void 0)toolNameByDispatchKey.delete(oldest)}toolNameByDispatchKey.set(key3,name)}function dispatchKey2(sessionID,callID){return`${sessionID.length}#${sessionID}${callID}`}function lookupToolNameForDispatch(sessionID,callID){return toolNameByDispatchKey.get(dispatchKey2(sessionID,callID))}function clearToolNameRegistry(){toolNameByDispatchKey.clear()}function readProgressChildSessionID(data){try{let metadata=data.metadata;if(!isPlainObject9(metadata))return;let child=metadata.sessionID;return typeof child==="string"?child:void 0}catch{return}}function mapV2EventToV1(envelope,lookupToolName){let type=typeof envelope?.type==="string"?envelope.type:void 0;if(type===void 0)return;let data=envelopePayload(envelope),sessionID=typeof data.sessionID==="string"?data.sessionID:void 0;switch(type){case"session.idle":case"session.status.updated":return{type:"session.idle",properties:{...sessionID?{sessionID}:{},...data}};case"session.status":return{type:"session.status",properties:{...sessionID?{sessionID}:{},...data}};case"session.error":case"session.execution.failed":return{type:"session.error",properties:{...sessionID?{sessionID}:{},...data}};case"session.deleted":return{type:"session.deleted",properties:{...sessionID?{sessionID}:{},...data}};case"session.created":return{type:"session.created",properties:{...sessionID?{sessionID}:{},...data}};case"session.text.delta":case"session.tool.called":case"session.tool.input.delta":return{type:"message.part.updated",properties:{...sessionID?{sessionID}:{},...data}};case"session.tool.progress":{let callID=typeof data.id==="string"?data.id:void 0,childSessionID=readProgressChildSessionID(data),drop=(reason)=>{log("v2 subagent progress dropped",{reason});return};if(!lookupToolName)return drop("no-tool-name-lookup");if(typeof sessionID!=="string"||!isBoundedId(sessionID))return drop("invalid-parent-session");if(!callID||!isBoundedId(callID))return drop("invalid-call-id");if(!childSessionID||!isBoundedId(childSessionID))return drop("invalid-child-session");if(childSessionID===sessionID)return drop("self-referencing-child");let toolName=lookupToolName(sessionID,callID);if(!toolName)return drop("untracked-tool-name");if(!isV2SubagentToolId(toolName))return drop("non-subagent-tool");return{type:"message.part.updated",properties:{part:{type:"tool",tool:"task",callID,sessionID,state:{metadata:{sessionId:childSessionID}}}}}}case"session.text.ended":case"session.tool.success":case"session.tool.failed":return{type:"message.updated",properties:{...sessionID?{sessionID}:{},...data}};default:return}}async function deferredDispatch(hooks2,mapped){let handler=hooks2.event;if(typeof handler!=="function")return;await withTimeout(Promise.resolve(handler({event:{type:mapped.type,properties:mapped.properties}})),V2_EVENT_BATCH_TIMEOUT_MS,Error("[opencode-swarm] v2: event dispatch exceeded budget")).catch((err)=>{log("v2 event dispatch failed (non-fatal)",{type:mapped.type,error:err instanceof Error?err.message:String(err)})})}function seedSessionIdentityFromEnvelope(envelope){let type=typeof envelope?.type==="string"?envelope.type:void 0;if(type!=="session.created"&&type!=="session.agent.selected")return;let payload=envelopePayload(envelope),sessionID=typeof payload.sessionID==="string"?payload.sessionID:void 0,agent=typeof payload.agent==="string"?payload.agent:void 0;if(sessionID&&agent)recordSessionChatAgent(sessionID,agent)}function startDeferredEventPump(ctx,hooks2){let stopped=!1,unmappedSeen=new Set;return(async()=>{try{let subscribe2=ctx?.event?.subscribe;if(typeof subscribe2!=="function"){log("v2 event subscribe surface absent; event pump idle (non-fatal)",{});return}let iterable=await withTimeout(Promise.resolve(subscribe2()),V2_EVENT_BATCH_TIMEOUT_MS,Error("[opencode-swarm] v2: event subscribe exceeded budget"));if(!iterable||typeof iterable[Symbol.asyncIterator]!=="function"){log("v2 event subscribe returned a non-iterable; event pump idle (non-fatal)",{});return}for await(let envelope of iterable){if(stopped)break;seedSessionIdentityFromEnvelope(envelope),recordV2SessionErrorFromEnvelope(envelope),rememberToolNameFromEnvelope(envelope);let mapped=mapV2EventToV1(envelope,lookupToolNameForDispatch);if(mapped===void 0){let t=typeof envelope?.type==="string"?envelope.type:"(no type)";if(!unmappedSeen.has(t)&&unmappedSeen.size<UNMAPPED_LOG_LIMIT)unmappedSeen.add(t),log("v2 event type not mapped (ignored)",{type:t});continue}await deferredDispatch(hooks2,mapped)}}catch(err){if(!stopped)log("v2 event pump stopped on error (non-fatal)",{error:err instanceof Error?err.message:String(err)})}})(),()=>{stopped=!0}}init_system_guidance_carrier();init_utils();init_timeout();var V2_GUIDANCE_CHAIN_TIMEOUT_MS=30000;function contentParts(message){return Array.isArray(message.content)?message.content:[]}function toV1MessageView(message,sessionID,originIndex,agentName){let textParts=[];for(let part of contentParts(message))if(part&&typeof part==="object"&&part.type==="text"&&typeof part.text==="string")textParts.push({type:"text",text:part.text});return{info:{id:typeof message.id==="string"?message.id:void 0,role:message.role,sessionID,swarmV2Origin:originIndex,...message.role==="user"&&agentName!==void 0?{agent:agentName}:{}},parts:textParts}}function writeBackTextParts(message,parts){if(!Array.isArray(message.content))return;let texts=parts.filter((p)=>p.type==="text"&&typeof p.text==="string").map((p)=>({type:"text",text:p.text})),content=[],nextText=0,afterLastText=0;for(let part of message.content)if(part&&typeof part==="object"&&part.type==="text"){if(nextText<texts.length)content.push(texts[nextText++]);afterLastText=content.length}else content.push(part);content.splice(afterLastText,0,...texts.slice(nextText)),message.content=content}function hasNonTextParts(message){if(message.content===void 0)return!1;if(!Array.isArray(message.content))return!0;return message.content.some((part)=>!(part&&typeof part==="object"&&part.type==="text"))}function toV1ModelInput(model){if(model&&typeof model==="object")return{providerID:typeof model.providerID==="string"?model.providerID:"unknown",modelID:typeof model.id==="string"?model.id:"unknown"};return{providerID:"unknown",modelID:"unknown"}}async function onV2ContextEvent(event,hooks2,directory){let sessionID=event.sessionID;seedV1SessionState(sessionID,event.agent,directory);let eventAgentName=normalizeV2AgentRef(event.agent),messagesTransform=hooks2["experimental.chat.messages.transform"];if(typeof messagesTransform==="function"){let originalMessages=[...event.messages??[]],views=originalMessages.map((m,i)=>toV1MessageView(m,sessionID,i,eventAgentName)),originalByView=new Map;for(let i=0;i<views.length;i+=1)originalByView.set(views[i],originalMessages[i]);await withTimeout(messagesTransform({},{messages:views}),V2_GUIDANCE_CHAIN_TIMEOUT_MS,Error("[opencode-swarm] v2: messages transform exceeded budget")).catch((err)=>{log("v2 messages transform failed (non-fatal; original messages retained)",{error:err instanceof Error?err.message:String(err)}),views.length=0,originalByView.clear(),originalMessages.forEach((message,i)=>{let view=toV1MessageView(message,sessionID,i,eventAgentName);views.push(view),originalByView.set(view,message)})});let originalById=new Map;for(let message of originalMessages)if(typeof message.id==="string"&&message.id.length>0)originalById.set(message.id,message);let isCarrier=(view)=>typeof view.info.id==="string"&&view.info.id.startsWith(GUIDANCE_CARRIER_ID_PREFIX),resolved=new Map,taken=new Set,resolve124=(view,message)=>{if(taken.has(message))return;taken.add(message),resolved.set(view,message)},unresolved=[];for(let view of views){let id=view.info.id,exact=originalByView.get(view)??(typeof id==="string"&&id.length>0?originalById.get(id):void 0);if(exact)resolve124(view,exact);else unresolved.push(view)}for(let view of unresolved){let origin=view.info.swarmV2Origin;if(typeof origin!=="number"||!Number.isInteger(origin)||origin<0||origin>=originalMessages.length)continue;let original=originalMessages[origin];if(!isCarrier(view)&&view.info.role!==original.role)continue;resolve124(view,original)}let consumed=new Set,claimed=new Map;event.system=event.system??[];for(let view of views){let source=resolved.get(view);if(isCarrier(view)){for(let part of view.parts)if(part.type==="text"&&typeof part.text==="string"&&part.text.length>0)event.system.push({type:"text",text:part.text});if(source)consumed.add(source)}else if(source)claimed.set(source,view.parts)}let kept=[];for(let message of originalMessages){let parts=claimed.get(message);if(parts)writeBackTextParts(message,parts),kept.push(message);else if(!consumed.has(message)&&hasNonTextParts(message))kept.push(message)}event.messages.length=0;for(let message of kept)event.messages.push(message)}let systemTransform=hooks2["experimental.chat.system.transform"];if(typeof systemTransform==="function"){let output={system:[]};await withTimeout(systemTransform({sessionID,model:toV1ModelInput(event.model)},output),V2_GUIDANCE_CHAIN_TIMEOUT_MS,Error("[opencode-swarm] v2: system transform exceeded budget")).catch((err)=>{log("v2 system transform failed (non-fatal)",{error:err instanceof Error?err.message:String(err)})});for(let text of output.system)if(typeof text==="string"&&text.length>0)event.system.push({type:"text",text})}}async function registerV2ContextHook(ctx,hooks2,directory,registrations){let registration=await withTimeout(ctx.session.hook("context",async(event)=>{return onV2ContextEvent(event,hooks2,directory)}),V2_GUIDANCE_CHAIN_TIMEOUT_MS,Error("[opencode-swarm] v2: context hook registration exceeded budget"));registrations.push(registration)}init_utils();init_timeout();var V2_TOOL_EXECUTE_TIMEOUT_MS=600000;function synthesizeV1ToolContext(context,projectRoot,permissionBridge){let agentName=normalizeV2AgentRef(context.agent)??"architect";return{sessionID:context.sessionID,messageID:context.messageID,agent:agentName,directory:projectRoot,worktree:projectRoot,abort:context.signal,metadata:(input)=>{try{let progress=context.progress;if(typeof progress==="function")progress({...input.metadata??{},...input.title!==void 0?{title:input.title}:{}})}catch{}},ask:async(input)=>{if(permissionBridge){await withTimeout(Promise.resolve(permissionBridge(input)),V2_TOOL_EXECUTE_TIMEOUT_MS,Error("[opencode-swarm] v2: permission bridge exceeded budget"));return}throw Error("[opencode-swarm] v2: interactive tool permission request unavailable (no permission surface); denying by default.")}}}function mapV1ToolResult(result){if(typeof result==="string")return{content:result};if(result&&typeof result==="object"){let rec=result;return{...typeof rec.output==="string"?{content:rec.output}:{},...rec.metadata&&typeof rec.metadata==="object"?{metadata:rec.metadata}:{}}}return{content:String(result??"")}}async function registerV2Tools(ctx,hooks2,projectRoot,registrations){let toolMap=hooks2.tool??{},registration=await withTimeout(ctx.tool.transform((editor)=>{for(let[name,definition]of Object.entries(toolMap)){let v1Execute=definition.execute;if(typeof v1Execute!=="function")continue;let info={name,description:definition.description??"",input:v2ToolInputSchema(definition.args),execute:async(input,context)=>{seedV1SessionState(context.sessionID,context.agent,projectRoot);let result=await withTimeout(Promise.resolve(v1Execute(input,synthesizeV1ToolContext(context,projectRoot,buildPermissionBridge(ctx,context)))),V2_TOOL_EXECUTE_TIMEOUT_MS,Error(`[opencode-swarm] v2: tool ${name} exceeded execution budget`));return mapV1ToolResult(result)}};editor.add(info)}}),V2_TOOL_EXECUTE_TIMEOUT_MS,Error("[opencode-swarm] v2: tool transform exceeded budget"));registrations.push(registration)}function buildPermissionBridge(ctx,context){let permission=ctx.permission;if(!permission)return;if(typeof permission.assert==="function"){let assert3=permission.assert,agentName=normalizeV2AgentRef(context.agent)??"architect";return async(input)=>{let askInput=input,action2=normalizeV2PermissionAction(typeof askInput?.permission==="string"?askInput.permission:""),resources=Array.isArray(askInput?.patterns)?askInput.patterns:[];log("v2 permission bridge ask routed through assert",{action:action2,resourceCount:resources.length}),await withTimeout(Promise.resolve(assert3({sessionID:context.sessionID,agent:agentName,action:action2,resources})),V2_TOOL_EXECUTE_TIMEOUT_MS,Error("[opencode-swarm] v2: permission assert exceeded budget"))}}if(typeof permission.reply==="function"){let reply=permission.reply;return async(input)=>{log("v2 permission bridge invoked (reply-only host; fail-closed)",{permission:typeof input?.permission==="string"?input.permission:"unknown",patternCount:Array.isArray(input?.patterns)?input.patterns.length:0}),await withTimeout(Promise.resolve(reply(input)).then(()=>{throw Error("[opencode-swarm] v2: permission ask denied — the reply surface resolved without a grant decision (fail-closed, #3351).")}),V2_TOOL_EXECUTE_TIMEOUT_MS,Error("[opencode-swarm] v2: permission reply exceeded budget"))}}return}async function deferredV2StartupModelPreflight(directory){let budgetMs=_internals273.preflightConfigTimeoutMs;try{let loaded=await withTimeout(_internals273.loadConfig(directory),_internals273.preflightConfigTimeoutMs,Error(`[opencode-swarm] v2: startup preflight config read exceeded the ${budgetMs}ms budget`));if(setV2OperatorQuiet(loaded?.config?.quiet===!0),loaded?.configHadErrors===!0)addDeferredWarning(`[opencode-swarm] v2: startup model preflight degraded — the config read resolved with errors (configHadErrors) within its ${budgetMs}ms budget; the roster check ran against the degraded configuration.`);let models=collectEnabledAgentModels(loaded?.config).map((entry)=>entry.model).filter((model)=>typeof model==="string"&&model.length>0),quiet=loaded?.config?.quiet===!0;for(let warning of collectModelRosterWarnings(models,VERIFIED_KEYLESS_MODEL_ROSTER))if(addDeferredWarning(warning),!quiet)console.warn(warning)}catch(err){let message=err instanceof Error?err.message:String(err);log("v2 startup model preflight failed (non-fatal)",{error:message}),addDeferredWarning(`[opencode-swarm] v2: startup model preflight failed after the ${budgetMs}ms config budget (${message}); the roster check did not run.`)}}async function deferredV2ConfigureToolBeforeBudget(directory,loadConfig=loadPluginConfigWithMetaAsync){try{let loaded=await withTimeout(loadConfig(directory),V2_PREFLIGHT_CONFIG_TIMEOUT_MS,Error("[opencode-swarm] v2: hook-budget config read exceeded budget"));configureV2ToolBeforeBudget(loaded?.config?.full_auto,directory)}catch(err){resetV2ToolBeforeBudget(directory);let reason=err instanceof Error?err.message:String(err);addDeferredWarning(`[opencode-swarm] v2: could not read full_auto.oversight for the tool.execute.before budget (${reason}); default budgets apply (60 s, or 150 s while Full-Auto runs).`),log("v2 hook-budget config read failed (non-fatal)",{error:reason})}}async function deferredV2RegisterToolHooks(ctx,hooks2,directory,registrations){await Promise.all([deferredV2ConfigureToolBeforeBudget(directory),registerV2ToolHooks(ctx,hooks2,directory,registrations)])}var V2_SETUP_TIMEOUT_MS=60000,V2_REGISTRATION_TIMEOUT_MS=3500,V2_PREFLIGHT_CONFIG_TIMEOUT_MS=2000,_internals273={registrationTimeoutMs:V2_REGISTRATION_TIMEOUT_MS,preflightConfigTimeoutMs:V2_PREFLIGHT_CONFIG_TIMEOUT_MS,loadConfig:loadPluginConfigWithMetaAsync,configureToolBeforeBudget:deferredV2ConfigureToolBeforeBudget};function createRegistrationSink(){let registrations=[],push=registrations.push.bind(registrations),closed=!1;return registrations.push=(...items)=>{if(!closed)return push(...items);for(let item of items)withTimeout(Promise.resolve().then(()=>item.dispose()),V2_SETUP_TIMEOUT_MS,Error("[opencode-swarm] v2 cleanup: late registration dispose exceeded budget")).catch((err)=>{log("v2 late registration dispose failed (non-fatal)",{error:err instanceof Error?err.message:String(err)})});return registrations.length},{registrations,closeRegistrations:()=>{closed=!0}}}function normalizeV2AgentRef(agent){if(typeof agent==="string")return agent;if(agent&&typeof agent==="object"){let rec=agent;if(typeof rec.id==="string"&&rec.id.length>0)return rec.id;if(typeof rec.name==="string"&&rec.name.length>0)return rec.name}return}var v2SetupOwnerCounter=0;function nextV2OwnerToken(){return v2SetupOwnerCounter+=1,`v2-owner-${v2SetupOwnerCounter}`}async function openCodeSwarmV2Setup(ctx,deps){let rawDirectory=ctx?.location?.directory;if(typeof rawDirectory!=="string"||rawDirectory.length===0)throw Error("[opencode-swarm] v2 setup: host Context carried no location.directory; refusing to start (invariant 4).");let ownerToken=nextV2OwnerToken();registerV2ConfigRebuildSourceForOwner(ownerToken,deps.buildV2RegistrationTables),setV2OperatorQuietForOwner(ownerToken,!1);try{let rootDecision=resolveProjectRootDecision(rawDirectory),directory=rootDecision.kind==="redirect"?rootDecision.owningRoot:rootDecision.kind==="root"?rootDecision.directory:rawDirectory,state2=createRegistrationSink(),input={client:createV2SessionClient(ctx),directory,worktree:directory},hooks2=await withTimeout(deps.runInit(input),V2_SETUP_TIMEOUT_MS,Error("[opencode-swarm] v2 setup: initialization exceeded budget")),pendingDomains=new Set,runRegistration=(domain3,register)=>{return pendingDomains.add(domain3),register().catch((err)=>{let message=err instanceof Error?err.message:String(err);log(`v2 ${domain3} registration failed (non-fatal)`,{error:message}),addDeferredWarning(`[opencode-swarm] v2 setup: ${domain3} registration failed (${message}); the domain was not registered.`)}).finally(()=>{pendingDomains.delete(domain3)})};await withTimeout(Promise.all([runRegistration("agent/command",()=>registerV2AgentsAndCommands(ctx,hooks2,directory,state2.registrations,ownerToken)),runRegistration("tool",()=>registerV2Tools(ctx,hooks2,directory,state2.registrations)),runRegistration("context-hook",()=>registerV2ContextHook(ctx,hooks2,directory,state2.registrations)),runRegistration("tool-hook",()=>deferredV2RegisterToolHooks(ctx,hooks2,directory,state2.registrations)),runRegistration("prompt-hook",()=>registerV2SessionHooks(ctx,hooks2,directory,state2.registrations))]),_internals273.registrationTimeoutMs,Error("[opencode-swarm] v2 setup: parallel registration exceeded budget")).catch((err)=>{let pending=[...pendingDomains];log("v2 registration failed (non-fatal)",{error:err instanceof Error?err.message:String(err),pending});let pendingText=pending.length>0?pending.join(", "):"none — domains completed but the stage exceeded budget";addDeferredWarning(`[opencode-swarm] v2 setup: registration still pending after ${_internals273.registrationTimeoutMs}ms (${pendingText}); the plugin loaded with partial registration.`)});let stopPump=startDeferredEventPump(ctx,hooks2);return state2.pumpStop=stopPump,registerV2AgentTransformSurface(ctx,ownerToken),await withTimeout(deferredV2StartupModelPreflight(directory),V2_SETUP_TIMEOUT_MS,Error("[opencode-swarm] v2: startup model preflight exceeded budget")),state2.disposeV1=typeof hooks2.dispose==="function"?hooks2.dispose:void 0,log("[opencode-swarm] v2 setup complete",{directory,tools:Object.keys(hooks2.tool??{}).length}),async function(){if(state2.closeRegistrations(),typeof state2.pumpStop==="function")state2.pumpStop();clearV2SessionClientState(),clearV2AgentTransformSurface(ownerToken),clearToolNameRegistry(),registerV2ConfigRebuildSourceForOwner(ownerToken,void 0),setV2OperatorQuietForOwner(ownerToken,void 0),clearV2OwnerRegistrationSnapshot(ownerToken),clearV2CtxOwnerBinding(ctx);for(let registration of state2.registrations)try{await withTimeout(registration.dispose(),V2_SETUP_TIMEOUT_MS,Error("[opencode-swarm] v2 cleanup: registration dispose exceeded budget"))}catch(err){log("v2 registration dispose failed (non-fatal)",{error:err instanceof Error?err.message:String(err)})}if(state2.disposeV1)await withTimeout(state2.disposeV1(),V2_SETUP_TIMEOUT_MS,Error("[opencode-swarm] v2 cleanup: v1 dispose exceeded budget")).catch((err)=>{log("v1 dispose during v2 cleanup failed (non-fatal)",{error:err instanceof Error?err.message:String(err)})})}}catch(err){throw registerV2ConfigRebuildSourceForOwner(ownerToken,void 0),setV2OperatorQuietForOwner(ownerToken,void 0),clearV2OwnerRegistrationSnapshot(ownerToken),clearV2AgentTransformSurface(ownerToken),clearV2CtxOwnerBinding(ctx),err}}function seedV1SessionState(sessionID,agentRef,directory){if(typeof sessionID!=="string"||sessionID.length===0)return;let agentName=normalizeV2AgentRef(agentRef);if(agentName===void 0)return sessionID;recordPrimaryOwner(sessionID,agentName);try{let session=ensureAgentSession(sessionID,agentName,directory);session.lastAgentEventTime=Date.now()}catch{}return swarmState.activeAgent.set(sessionID,agentName),sessionID}function v2ToolInputSchema(args2){try{if(args2&&typeof args2==="object")return exports_external.toJSONSchema(exports_external.object(args2))}catch{}return{type:"object"}}init_manifest_files();init_p_limit();init_knowledge_curator();init_knowledge_reinforcement();init_knowledge_store();init_knowledge_validator();init_micro_reflector();init_logger();init_timeout();init_candidate_queue();init_provenance();var SCREENING_TOKEN_ESTIMATE=400,SCREENING_PROMPT_CAP=1200;function unionSourceKnowledgeIds(entry,ids){let next=entry.source_knowledge_ids;for(let id of ids)next=unionInsightMarker(next,id);entry.source_knowledge_ids=next??[]}function findActiveEntryWithMarker(entries2,marker){return entries2.find((entry)=>isActiveSwarmKnowledgeEntry(entry)&&(entry.source_knowledge_ids??[]).includes(marker))}function buildScreeningPrompt(candidate2){return["A subagent proposed this durable procedural lesson for the shared knowledge store.","Answer with exactly one word: ADMIT or REJECT.","REJECT when the lesson is task-specific trivia, a transient environment failure, or not generalizable.","",`LESSON: ${candidate2.lesson}`,`CATEGORY: ${candidate2.category}`,`SCOPE: agents=${(candidate2.applies_to_agents??[]).join(",")} tools=${(candidate2.applies_to_tools??[]).join(",")}`].join(`
|
|
7472
|
+
`)}async function deferredV2SessionPromptPlaceholder(ctx,_placeholderId,stash,body,text,signal2){if(stash.promptStarted=!0,signal2?.aborted)throw Error("v2 session-client: prompt wait aborted");let previousRealId=stash.realId;if(previousRealId!==void 0)stash.realId=void 0,stash.abortPending=!1,stash.deletePending=!1,await ctx.session.remove({sessionID:previousRealId}).catch(()=>{return});let agent=typeof body.agent==="string"?body.agent:void 0,model=body.model&&typeof body.model.providerID==="string"&&typeof body.model.modelID==="string"?{id:body.model.modelID,providerID:body.model.providerID}:void 0,system=typeof body.system==="string"?body.system:void 0,createdRecord=await ctx.session.create({...stash.parentID!==void 0?{parentID:stash.parentID}:{},...stash.title!==void 0?{title:stash.title}:{},...agent!==void 0?{agent}:{},...model!==void 0?{model}:{},location:{directory:stash.directory},permissions:readOnlyToolsToV2Permissions(body.tools)}),realId=typeof createdRecord?.id==="string"?createdRecord.id:void 0;if(realId===void 0)throw Error("v2 session-client: session create returned no id");let echoedDirectory=typeof createdRecord.location?.directory==="string"?createdRecord.location.directory:void 0;if(echoedDirectory!==void 0&&!sameDirectoryLexical(echoedDirectory,stash.directory))throw await ctx.session.remove({sessionID:realId}).catch(()=>{return}),Error(`v2 session-client: created session landed in ${echoedDirectory}, not the requested ${stash.directory} (#3169 Phase 0 C1)`);sessionErrors.delete(realId);let registration;try{if(system!==void 0||body.tools!==void 0)registration=await ctx.session.hook("context",makeV2SessionContextHandler(realId,system,body.tools));await ctx.session.prompt({sessionID:realId,text}),await deferredV2SessionWait(ctx,realId,signal2);let entries2=await ctx.session.context({sessionID:realId});return{data:await deferredV2SessionTranslate(Array.isArray(entries2)?entries2:[],realId)}}finally{if(stash.realId=realId,registration?.dispose)await registration.dispose().catch(()=>{return});if(stash.abortPending)await ctx.session.interrupt({sessionID:realId}).catch(()=>{return});if(stash.deletePending)sessionErrors.delete(realId),await ctx.session.remove({sessionID:realId}).catch(()=>{return})}}async function deferredV2SessionPromptReal(ctx,sessionId,body,text,signal2){if(typeof body.agent==="string"){let switchAgent=ctx.session.switchAgent;if(typeof switchAgent==="function")await switchAgent({sessionID:sessionId,agent:body.agent})}sessionErrors.delete(sessionId),await ctx.session.prompt({sessionID:sessionId,text}),await deferredV2SessionWait(ctx,sessionId,signal2);let entries2=await ctx.session.context({sessionID:sessionId});return{data:await deferredV2SessionTranslate(Array.isArray(entries2)?entries2:[],sessionId)}}function resolveSessionId(id){let stash=placeholderSessions.get(id);if(stash===void 0)return id;return stash.realId}function createV2SessionClient(ctx){let session=ctx?.session;if(!session||typeof session!=="object")return;for(let member of["create","get","remove","prompt","wait","context","interrupt","hook"])if(typeof session[member]!=="function")return;return{session:{create:(args2)=>deferredV2SessionCreate(ctx,args2),prompt:(args2)=>deferredV2SessionPrompt(ctx,args2),abort:(args2)=>{let id=args2?.path?.id,resolved=resolveSessionId(id);if(resolved!==void 0)return ctx.session.interrupt({sessionID:resolved}).catch(()=>{return});let stash=placeholderSessions.get(id);if(stash?.promptStarted)stash.abortPending=!0;return Promise.resolve(void 0)},delete:(args2)=>{let id=args2?.path?.id,stash=placeholderSessions.get(id),resolved=resolveSessionId(id);if(resolved!==void 0)return sessionErrors.delete(resolved),deferredV2SessionRemoveEager(ctx,resolved).then((outcome)=>{if(stash?.eager===!0&&outcome.ok)placeholderSessions.delete(id);else if(stash?.eager===!0)log("v2 session-client: eager delete cleanup failed",{reason:outcome.reason})});if(stash?.promptStarted)stash.deletePending=!0;return Promise.resolve(void 0)},get:(args2)=>{let id=args2?.path?.id,stash=placeholderSessions.get(id),overlayParentID=stash?.eager===!0&&typeof stash.parentID==="string"?stash.parentID:void 0,resolved=resolveSessionId(id);if(resolved===void 0)return Promise.resolve({data:null});return ctx.session.get({sessionID:resolved}).then((info)=>({data:overlayParentID!==void 0&&info&&typeof info==="object"?{...info,parentID:overlayParentID}:info})).catch((error93)=>({data:null,error:error93}))}}}}var MAX_PATH_IN_MESSAGE_CHARS=200;function boundPathForMessage(path321){if(path321===void 0)return"an unverifiable location";if(path321.length<=MAX_PATH_IN_MESSAGE_CHARS)return path321;return`${path321.slice(0,MAX_PATH_IN_MESSAGE_CHARS)}… (truncated)`}var EAGER_CLEANUP_TIMEOUT_MS=1e4;async function deferredV2SessionRemoveEager(ctx,sessionID){try{return await withTimeout(ctx.session.remove({sessionID}),EAGER_CLEANUP_TIMEOUT_MS,Error(`v2 session-client: eager cleanup of session ${sessionID} exceeded ${EAGER_CLEANUP_TIMEOUT_MS}ms`)),{ok:!0}}catch(error93){return{ok:!1,reason:error93 instanceof Error?error93.message:String(error93)}}}async function deferredV2SessionCreateEager(ctx,parentID,title,directory,signal2){let created;try{created=await ctx.session.create({...title!==void 0?{title}:{},location:{directory}})}catch(error93){return{data:null,error:{message:`v2 session-client: eager lane create failed (${error93 instanceof Error?error93.message:String(error93)})`}}}let createdRecord=created,realId=typeof createdRecord?.id==="string"?createdRecord.id:void 0;if(realId===void 0)return{data:null,error:{message:"v2 session-client: eager lane create returned no id (#3169 Phase 3)"}};if(signal2?.aborted){let compensated=await deferredV2SessionRemoveEager(ctx,realId);if(!compensated.ok)log("v2 session-client: aborted eager create compensation failed",{reason:compensated.reason});return{data:null,error:{message:`v2 session-client: eager lane create aborted by the caller; ${compensated.ok?"the created session was removed":`removing session ${realId} also failed (${compensated.reason??"unknown error"}) — remove it manually`}`,...compensated.ok?{}:{sessionID:realId,cleanupFailed:!0}}}}let landed=typeof createdRecord.location?.directory==="string"?createdRecord.location.directory:void 0;if(landed===void 0){let reported=await ctx.session.get({sessionID:realId}).catch(()=>{return});landed=typeof reported?.location?.directory==="string"?reported.location.directory:void 0}if(landed===void 0||!sameDirectoryLexical(landed,directory)){let removed=await deferredV2SessionRemoveEager(ctx,realId);return{data:null,error:{message:`v2 session-client: eager lane create landed in ${boundPathForMessage(landed)}, not the requested ${boundPathForMessage(directory)} (#3169 Phase 3 placement guard; Phase 0 C1)${removed.ok?"":`; cleanup of session ${realId} also failed (${removed.reason??"unknown error"}) — remove it before retrying`}`,...removed.ok?{}:{sessionID:realId,cleanupFailed:!0}}}}return rememberPlaceholder(realId,{parentID,...title!==void 0?{title}:{},directory,realId,eager:!0}),{data:{id:realId}}}async function deferredV2SessionCreate(ctx,args2){let directory=args2?.query?.directory;if(typeof directory!=="string"||directory.length===0)return{data:null,error:{message:"v2 session-client: create requires query.directory (v1 contract)"}};let parentID=args2?.body?.parentID;if(parentID!==void 0){let parentDirectory=await deferredV2SessionGetParentDirectory(ctx,parentID).catch(()=>{return});if(parentDirectory===void 0)return{data:null,error:{message:"v2 session-client: parent session placement unverifiable (get returned no location.directory — live-verification item on #3169 Phase 2)"}};if(!sameDirectoryLexical(parentDirectory,directory))return deferredV2SessionCreateEager(ctx,parentID,args2?.body?.title,directory,args2?.signal)}placeholderCounter+=1;let placeholderId=`v2shim-${placeholderCounter}-${Math.random().toString(36).slice(2,10)}`;return rememberPlaceholder(placeholderId,{...parentID!==void 0?{parentID}:{},...args2?.body?.title!==void 0?{title:args2.body.title}:{},directory}),{data:{id:placeholderId}}}async function deferredV2SessionPromptEager(ctx,realId,body,text,signal2){if(signal2?.aborted)throw Error("v2 session-client: eager prompt aborted before dispatch");let agent=typeof body.agent==="string"?body.agent:void 0;if(agent!==void 0){let switchAgent=ctx.session.switchAgent;if(typeof switchAgent==="function")await switchAgent({sessionID:realId,agent});else log("v2 session-client: eager prompt skipped switchAgent (host lacks it)",{agent})}let model=body.model&&typeof body.model.providerID==="string"&&typeof body.model.modelID==="string"?{id:body.model.modelID,providerID:body.model.providerID}:void 0;if(model!==void 0){let switchModel=ctx.session.switchModel;if(typeof switchModel==="function")await switchModel({sessionID:realId,model});else log("v2 session-client: eager prompt skipped switchModel (host lacks it)",{model})}let system=typeof body.system==="string"?body.system:void 0;sessionErrors.delete(realId);let registration;try{if(system!==void 0||body.tools!==void 0)registration=await ctx.session.hook("context",makeV2SessionContextHandler(realId,system,body.tools));await ctx.session.prompt({sessionID:realId,text}),await deferredV2SessionWait(ctx,realId,signal2);let entries2=await ctx.session.context({sessionID:realId});return{data:await deferredV2SessionTranslate(Array.isArray(entries2)?entries2:[],realId)}}finally{if(registration?.dispose)await registration.dispose().catch(()=>{return})}}async function deferredV2SessionPrompt(ctx,args2){let id=args2?.path?.id;if(typeof id!=="string"||id.length===0)return{data:null,error:{message:"v2 session-client: prompt requires path.id"}};let body=args2?.body??{},text=promptBodyText(body.parts),stash=placeholderSessions.get(id);if(stash!==void 0&&stash.eager===!0&&stash.realId!==void 0)return deferredV2SessionPromptEager(ctx,stash.realId,body,text,args2?.signal);if(stash!==void 0)return deferredV2SessionPromptPlaceholder(ctx,id,stash,body,text,args2?.signal);return deferredV2SessionPromptReal(ctx,id,body,text,args2?.signal)}var V2_EVENT_BATCH_TIMEOUT_MS=60000,UNMAPPED_LOG_LIMIT=20;function envelopePayload(envelope){return envelope.data??envelope.properties??{}}var MAX_TRACKED_TOOL_NAME_CHARS=256,MAX_DISPATCH_ID_CHARS=256;function isBoundedId(value){return value.trim()!==""&&value.length<=MAX_DISPATCH_ID_CHARS}var MAX_TRACKED_TOOL_NAMES=512,toolNameByDispatchKey=new Map;function rememberToolNameFromEnvelope(envelope){if(envelope?.type!=="session.tool.input.started")return;let payload=envelopePayload(envelope),name=typeof payload.name==="string"?payload.name:void 0;if(!name||name.length>MAX_TRACKED_TOOL_NAME_CHARS)return;if(!isV2SubagentToolId(name))return;let sessionID=typeof payload.sessionID==="string"?payload.sessionID:void 0,callID=typeof payload.id==="string"?payload.id:void 0;if(!sessionID||!callID)return;if(!isBoundedId(sessionID)||!isBoundedId(callID))return;let key3=dispatchKey2(sessionID,callID);if(toolNameByDispatchKey.delete(key3),toolNameByDispatchKey.size>=MAX_TRACKED_TOOL_NAMES){let oldest=toolNameByDispatchKey.keys().next().value;if(oldest!==void 0)toolNameByDispatchKey.delete(oldest)}toolNameByDispatchKey.set(key3,name)}function dispatchKey2(sessionID,callID){return`${sessionID.length}#${sessionID}${callID}`}function lookupToolNameForDispatch(sessionID,callID){return toolNameByDispatchKey.get(dispatchKey2(sessionID,callID))}function clearToolNameRegistry(){toolNameByDispatchKey.clear()}function readProgressChildSessionID(data){try{let metadata=data.metadata;if(!isPlainObject9(metadata))return;let child=metadata.sessionID;return typeof child==="string"?child:void 0}catch{return}}function mapV2EventToV1(envelope,lookupToolName){let type=typeof envelope?.type==="string"?envelope.type:void 0;if(type===void 0)return;let data=envelopePayload(envelope),sessionID=typeof data.sessionID==="string"?data.sessionID:void 0;switch(type){case"session.idle":case"session.status.updated":return{type:"session.idle",properties:{...sessionID?{sessionID}:{},...data}};case"session.status":return{type:"session.status",properties:{...sessionID?{sessionID}:{},...data}};case"session.error":case"session.execution.failed":return{type:"session.error",properties:{...sessionID?{sessionID}:{},...data}};case"session.deleted":return{type:"session.deleted",properties:{...sessionID?{sessionID}:{},...data}};case"session.created":return{type:"session.created",properties:{...sessionID?{sessionID}:{},...data}};case"session.text.delta":case"session.tool.called":case"session.tool.input.delta":return{type:"message.part.updated",properties:{...sessionID?{sessionID}:{},...data}};case"session.tool.progress":{let callID=typeof data.id==="string"?data.id:void 0,childSessionID=readProgressChildSessionID(data),drop=(reason)=>{log("v2 subagent progress dropped",{reason});return};if(!lookupToolName)return drop("no-tool-name-lookup");if(typeof sessionID!=="string"||!isBoundedId(sessionID))return drop("invalid-parent-session");if(!callID||!isBoundedId(callID))return drop("invalid-call-id");if(!childSessionID||!isBoundedId(childSessionID))return drop("invalid-child-session");if(childSessionID===sessionID)return drop("self-referencing-child");let toolName=lookupToolName(sessionID,callID);if(!toolName)return drop("untracked-tool-name");if(!isV2SubagentToolId(toolName))return drop("non-subagent-tool");return{type:"message.part.updated",properties:{part:{type:"tool",tool:"task",callID,sessionID,state:{metadata:{sessionId:childSessionID}}}}}}case"session.text.ended":case"session.tool.success":case"session.tool.failed":return{type:"message.updated",properties:{...sessionID?{sessionID}:{},...data}};default:return}}async function deferredDispatch(hooks2,mapped){let handler=hooks2.event;if(typeof handler!=="function")return;await withTimeout(Promise.resolve(handler({event:{type:mapped.type,properties:mapped.properties}})),V2_EVENT_BATCH_TIMEOUT_MS,Error("[opencode-swarm] v2: event dispatch exceeded budget")).catch((err)=>{log("v2 event dispatch failed (non-fatal)",{type:mapped.type,error:err instanceof Error?err.message:String(err)})})}function seedSessionIdentityFromEnvelope(envelope){let type=typeof envelope?.type==="string"?envelope.type:void 0;if(type!=="session.created"&&type!=="session.agent.selected")return;let payload=envelopePayload(envelope),sessionID=typeof payload.sessionID==="string"?payload.sessionID:void 0,agent=typeof payload.agent==="string"?payload.agent:void 0;if(sessionID&&agent)recordSessionChatAgent(sessionID,agent)}function startDeferredEventPump(ctx,hooks2){let stopped=!1,unmappedSeen=new Set;return(async()=>{try{let subscribe2=ctx?.event?.subscribe;if(typeof subscribe2!=="function"){log("v2 event subscribe surface absent; event pump idle (non-fatal)",{});return}let iterable=await withTimeout(Promise.resolve(subscribe2()),V2_EVENT_BATCH_TIMEOUT_MS,Error("[opencode-swarm] v2: event subscribe exceeded budget"));if(!iterable||typeof iterable[Symbol.asyncIterator]!=="function"){log("v2 event subscribe returned a non-iterable; event pump idle (non-fatal)",{});return}for await(let envelope of iterable){if(stopped)break;seedSessionIdentityFromEnvelope(envelope),recordV2SessionErrorFromEnvelope(envelope),rememberToolNameFromEnvelope(envelope);let mapped=mapV2EventToV1(envelope,lookupToolNameForDispatch);if(mapped===void 0){let t=typeof envelope?.type==="string"?envelope.type:"(no type)";if(!unmappedSeen.has(t)&&unmappedSeen.size<UNMAPPED_LOG_LIMIT)unmappedSeen.add(t),log("v2 event type not mapped (ignored)",{type:t});continue}await deferredDispatch(hooks2,mapped)}}catch(err){if(!stopped)log("v2 event pump stopped on error (non-fatal)",{error:err instanceof Error?err.message:String(err)})}})(),()=>{stopped=!0}}init_system_guidance_carrier();init_utils();init_timeout();var V2_GUIDANCE_CHAIN_TIMEOUT_MS=30000;function contentParts(message){return Array.isArray(message.content)?message.content:[]}function toV1MessageView(message,sessionID,originIndex,agentName){let textParts=[];for(let part of contentParts(message))if(part&&typeof part==="object"&&part.type==="text"&&typeof part.text==="string")textParts.push({type:"text",text:part.text});return{info:{id:typeof message.id==="string"?message.id:void 0,role:message.role,sessionID,swarmV2Origin:originIndex,...message.role==="user"&&agentName!==void 0?{agent:agentName}:{}},parts:textParts}}function writeBackTextParts(message,parts){if(!Array.isArray(message.content))return;let texts=parts.filter((p)=>p.type==="text"&&typeof p.text==="string").map((p)=>({type:"text",text:p.text})),content=[],nextText=0,afterLastText=0;for(let part of message.content)if(part&&typeof part==="object"&&part.type==="text"){if(nextText<texts.length)content.push(texts[nextText++]);afterLastText=content.length}else content.push(part);content.splice(afterLastText,0,...texts.slice(nextText)),message.content=content}function hasNonTextParts(message){if(message.content===void 0)return!1;if(!Array.isArray(message.content))return!0;return message.content.some((part)=>!(part&&typeof part==="object"&&part.type==="text"))}function toV1ModelInput(model){if(model&&typeof model==="object")return{providerID:typeof model.providerID==="string"?model.providerID:"unknown",modelID:typeof model.id==="string"?model.id:"unknown"};return{providerID:"unknown",modelID:"unknown"}}async function onV2ContextEvent(event,hooks2,directory){let sessionID=event.sessionID;seedV1SessionState(sessionID,event.agent,directory);let eventAgentName=normalizeV2AgentRef(event.agent),messagesTransform=hooks2["experimental.chat.messages.transform"];if(typeof messagesTransform==="function"){let originalMessages=[...event.messages??[]],views=originalMessages.map((m,i)=>toV1MessageView(m,sessionID,i,eventAgentName)),originalByView=new Map;for(let i=0;i<views.length;i+=1)originalByView.set(views[i],originalMessages[i]);await withTimeout(messagesTransform({},{messages:views}),V2_GUIDANCE_CHAIN_TIMEOUT_MS,Error("[opencode-swarm] v2: messages transform exceeded budget")).catch((err)=>{log("v2 messages transform failed (non-fatal; original messages retained)",{error:err instanceof Error?err.message:String(err)}),views.length=0,originalByView.clear(),originalMessages.forEach((message,i)=>{let view=toV1MessageView(message,sessionID,i,eventAgentName);views.push(view),originalByView.set(view,message)})});let originalById=new Map;for(let message of originalMessages)if(typeof message.id==="string"&&message.id.length>0)originalById.set(message.id,message);let isCarrier=(view)=>typeof view.info.id==="string"&&view.info.id.startsWith(GUIDANCE_CARRIER_ID_PREFIX),resolved=new Map,taken=new Set,resolve124=(view,message)=>{if(taken.has(message))return;taken.add(message),resolved.set(view,message)},unresolved=[];for(let view of views){let id=view.info.id,exact=originalByView.get(view)??(typeof id==="string"&&id.length>0?originalById.get(id):void 0);if(exact)resolve124(view,exact);else unresolved.push(view)}for(let view of unresolved){let origin=view.info.swarmV2Origin;if(typeof origin!=="number"||!Number.isInteger(origin)||origin<0||origin>=originalMessages.length)continue;let original=originalMessages[origin];if(!isCarrier(view)&&view.info.role!==original.role)continue;resolve124(view,original)}let consumed=new Set,claimed=new Map;event.system=event.system??[];for(let view of views){let source=resolved.get(view);if(isCarrier(view)){for(let part of view.parts)if(part.type==="text"&&typeof part.text==="string"&&part.text.length>0)event.system.push({type:"text",text:part.text});if(source)consumed.add(source)}else if(source)claimed.set(source,view.parts)}let kept=[];for(let message of originalMessages){let parts=claimed.get(message);if(parts)writeBackTextParts(message,parts),kept.push(message);else if(!consumed.has(message)&&hasNonTextParts(message))kept.push(message)}event.messages.length=0;for(let message of kept)event.messages.push(message)}let systemTransform=hooks2["experimental.chat.system.transform"];if(typeof systemTransform==="function"){let output={system:[]};await withTimeout(systemTransform({sessionID,model:toV1ModelInput(event.model)},output),V2_GUIDANCE_CHAIN_TIMEOUT_MS,Error("[opencode-swarm] v2: system transform exceeded budget")).catch((err)=>{log("v2 system transform failed (non-fatal)",{error:err instanceof Error?err.message:String(err)})});for(let text of output.system)if(typeof text==="string"&&text.length>0)event.system.push({type:"text",text})}}async function registerV2ContextHook(ctx,hooks2,directory,registrations){let registration=await withTimeout(ctx.session.hook("context",async(event)=>{return onV2ContextEvent(event,hooks2,directory)}),V2_GUIDANCE_CHAIN_TIMEOUT_MS,Error("[opencode-swarm] v2: context hook registration exceeded budget"));registrations.push(registration)}init_utils();init_timeout();var V2_TOOL_EXECUTE_TIMEOUT_MS=600000;function synthesizeV1ToolContext(context,projectRoot,permissionBridge){let agentName=normalizeV2AgentRef(context.agent)??"architect";return{sessionID:context.sessionID,messageID:context.messageID,agent:agentName,directory:projectRoot,worktree:projectRoot,abort:context.signal,metadata:(input)=>{try{let progress=context.progress;if(typeof progress==="function")progress({...input.metadata??{},...input.title!==void 0?{title:input.title}:{}})}catch{}},ask:async(input)=>{if(permissionBridge){await withTimeout(Promise.resolve(permissionBridge(input)),V2_TOOL_EXECUTE_TIMEOUT_MS,Error("[opencode-swarm] v2: permission bridge exceeded budget"));return}throw Error("[opencode-swarm] v2: interactive tool permission request unavailable (no permission surface); denying by default.")}}}function mapV1ToolResult(result){if(typeof result==="string")return{content:result};if(result&&typeof result==="object"){let rec=result;return{...typeof rec.output==="string"?{content:rec.output}:{},...rec.metadata&&typeof rec.metadata==="object"?{metadata:rec.metadata}:{}}}return{content:String(result??"")}}async function registerV2Tools(ctx,hooks2,projectRoot,registrations){let toolMap=hooks2.tool??{},registration=await withTimeout(ctx.tool.transform((editor)=>{for(let[name,definition]of Object.entries(toolMap)){let v1Execute=definition.execute;if(typeof v1Execute!=="function")continue;let info={name,description:definition.description??"",input:v2ToolInputSchema(definition.args),execute:async(input,context)=>{seedV1SessionState(context.sessionID,context.agent,projectRoot);let result=await withTimeout(Promise.resolve(v1Execute(input,synthesizeV1ToolContext(context,projectRoot,buildPermissionBridge(ctx,context)))),V2_TOOL_EXECUTE_TIMEOUT_MS,Error(`[opencode-swarm] v2: tool ${name} exceeded execution budget`));return mapV1ToolResult(result)}};editor.add(info)}}),V2_TOOL_EXECUTE_TIMEOUT_MS,Error("[opencode-swarm] v2: tool transform exceeded budget"));registrations.push(registration)}function buildPermissionBridge(ctx,context){let permission=ctx.permission;if(!permission)return;if(typeof permission.assert==="function"){let assert3=permission.assert,agentName=normalizeV2AgentRef(context.agent)??"architect";return async(input)=>{let askInput=input,action2=normalizeV2PermissionAction(typeof askInput?.permission==="string"?askInput.permission:""),resources=Array.isArray(askInput?.patterns)?askInput.patterns:[];log("v2 permission bridge ask routed through assert",{action:action2,resourceCount:resources.length}),await withTimeout(Promise.resolve(assert3({sessionID:context.sessionID,agent:agentName,action:action2,resources})),V2_TOOL_EXECUTE_TIMEOUT_MS,Error("[opencode-swarm] v2: permission assert exceeded budget"))}}if(typeof permission.reply==="function"){let reply=permission.reply;return async(input)=>{log("v2 permission bridge invoked (reply-only host; fail-closed)",{permission:typeof input?.permission==="string"?input.permission:"unknown",patternCount:Array.isArray(input?.patterns)?input.patterns.length:0}),await withTimeout(Promise.resolve(reply(input)).then(()=>{throw Error("[opencode-swarm] v2: permission ask denied — the reply surface resolved without a grant decision (fail-closed, #3351).")}),V2_TOOL_EXECUTE_TIMEOUT_MS,Error("[opencode-swarm] v2: permission reply exceeded budget"))}}return}async function deferredV2StartupModelPreflight(directory){let budgetMs=_internals273.preflightConfigTimeoutMs;try{let loaded=await withTimeout(_internals273.loadConfig(directory),_internals273.preflightConfigTimeoutMs,Error(`[opencode-swarm] v2: startup preflight config read exceeded the ${budgetMs}ms budget`));if(setV2OperatorQuiet(loaded?.config?.quiet===!0),loaded?.configHadErrors===!0)addDeferredWarning(`[opencode-swarm] v2: startup model preflight degraded — the config read resolved with errors (configHadErrors) within its ${budgetMs}ms budget; the roster check ran against the degraded configuration.`);let models=collectEnabledAgentModels(loaded?.config).map((entry)=>entry.model).filter((model)=>typeof model==="string"&&model.length>0),quiet=loaded?.config?.quiet===!0;for(let warning of collectModelRosterWarnings(models,VERIFIED_KEYLESS_MODEL_ROSTER))if(addDeferredWarning(warning),!quiet)console.warn(warning)}catch(err){let message=err instanceof Error?err.message:String(err);log("v2 startup model preflight failed (non-fatal)",{error:message}),addDeferredWarning(`[opencode-swarm] v2: startup model preflight failed after the ${budgetMs}ms config budget (${message}); the roster check did not run.`)}}async function deferredV2ConfigureToolBeforeBudget(directory,loadConfig=loadPluginConfigWithMetaAsync){try{let loaded=await withTimeout(loadConfig(directory),V2_PREFLIGHT_CONFIG_TIMEOUT_MS,Error("[opencode-swarm] v2: hook-budget config read exceeded budget"));configureV2ToolBeforeBudget(loaded?.config?.full_auto,directory)}catch(err){resetV2ToolBeforeBudget(directory);let reason=err instanceof Error?err.message:String(err);addDeferredWarning(`[opencode-swarm] v2: could not read full_auto.oversight for the tool.execute.before budget (${reason}); default budgets apply (60 s, or 150 s while Full-Auto runs).`),log("v2 hook-budget config read failed (non-fatal)",{error:reason})}}async function deferredV2RegisterToolHooks(ctx,hooks2,directory,registrations){await Promise.all([deferredV2ConfigureToolBeforeBudget(directory),registerV2ToolHooks(ctx,hooks2,directory,registrations)])}var V2_SETUP_TIMEOUT_MS=60000,V2_REGISTRATION_TIMEOUT_MS=3500,V2_PREFLIGHT_CONFIG_TIMEOUT_MS=2000,_internals273={registrationTimeoutMs:V2_REGISTRATION_TIMEOUT_MS,preflightConfigTimeoutMs:V2_PREFLIGHT_CONFIG_TIMEOUT_MS,loadConfig:loadPluginConfigWithMetaAsync,configureToolBeforeBudget:deferredV2ConfigureToolBeforeBudget};function createRegistrationSink(){let registrations=[],push=registrations.push.bind(registrations),closed=!1;return registrations.push=(...items)=>{if(!closed)return push(...items);for(let item of items)withTimeout(Promise.resolve().then(()=>item.dispose()),V2_SETUP_TIMEOUT_MS,Error("[opencode-swarm] v2 cleanup: late registration dispose exceeded budget")).catch((err)=>{log("v2 late registration dispose failed (non-fatal)",{error:err instanceof Error?err.message:String(err)})});return registrations.length},{registrations,closeRegistrations:()=>{closed=!0}}}function normalizeV2AgentRef(agent){if(typeof agent==="string")return agent;if(agent&&typeof agent==="object"){let rec=agent;if(typeof rec.id==="string"&&rec.id.length>0)return rec.id;if(typeof rec.name==="string"&&rec.name.length>0)return rec.name}return}var v2SetupOwnerCounter=0;function nextV2OwnerToken(){return v2SetupOwnerCounter+=1,`v2-owner-${v2SetupOwnerCounter}`}async function openCodeSwarmV2Setup(ctx,deps){let rawDirectory=ctx?.location?.directory;if(typeof rawDirectory!=="string"||rawDirectory.length===0)throw Error("[opencode-swarm] v2 setup: host Context carried no location.directory; refusing to start (invariant 4).");let ownerToken=nextV2OwnerToken();registerV2ConfigRebuildSourceForOwner(ownerToken,deps.buildV2RegistrationTables),setV2OperatorQuietForOwner(ownerToken,!1);try{let rootDecision=resolveProjectRootDecision(rawDirectory),directory=rootDecision.kind==="redirect"?rootDecision.owningRoot:rootDecision.kind==="root"?rootDecision.directory:rawDirectory,state2=createRegistrationSink(),input={client:createV2SessionClient(ctx),directory,worktree:directory},hooks2=await withTimeout(deps.runInit(input),V2_SETUP_TIMEOUT_MS,Error("[opencode-swarm] v2 setup: initialization exceeded budget")),pendingDomains=new Set,runRegistration=(domain3,register)=>{return pendingDomains.add(domain3),register().catch((err)=>{let message=err instanceof Error?err.message:String(err);log(`v2 ${domain3} registration failed (non-fatal)`,{error:message}),addDeferredWarning(`[opencode-swarm] v2 setup: ${domain3} registration failed (${message}); the domain was not registered.`)}).finally(()=>{pendingDomains.delete(domain3)})};await withTimeout(Promise.all([runRegistration("agent/command",()=>registerV2AgentsAndCommands(ctx,hooks2,directory,state2.registrations,ownerToken)),runRegistration("tool",()=>registerV2Tools(ctx,hooks2,directory,state2.registrations)),runRegistration("context-hook",()=>registerV2ContextHook(ctx,hooks2,directory,state2.registrations)),runRegistration("tool-hook",()=>deferredV2RegisterToolHooks(ctx,hooks2,directory,state2.registrations)),runRegistration("prompt-hook",()=>registerV2SessionHooks(ctx,hooks2,directory,state2.registrations)),runRegistration("shell-observer",()=>registerV2ShellHooks(ctx,state2.registrations))]),_internals273.registrationTimeoutMs,Error("[opencode-swarm] v2 setup: parallel registration exceeded budget")).catch((err)=>{let pending=[...pendingDomains];log("v2 registration failed (non-fatal)",{error:err instanceof Error?err.message:String(err),pending});let pendingText=pending.length>0?pending.join(", "):"none — domains completed but the stage exceeded budget";addDeferredWarning(`[opencode-swarm] v2 setup: registration still pending after ${_internals273.registrationTimeoutMs}ms (${pendingText}); the plugin loaded with partial registration.`)});let stopPump=startDeferredEventPump(ctx,hooks2);return state2.pumpStop=stopPump,registerV2AgentTransformSurface(ctx,ownerToken),await withTimeout(deferredV2StartupModelPreflight(directory),V2_SETUP_TIMEOUT_MS,Error("[opencode-swarm] v2: startup model preflight exceeded budget")),state2.disposeV1=typeof hooks2.dispose==="function"?hooks2.dispose:void 0,log("[opencode-swarm] v2 setup complete",{directory,tools:Object.keys(hooks2.tool??{}).length}),async function(){if(state2.closeRegistrations(),typeof state2.pumpStop==="function")state2.pumpStop();clearV2SessionClientState(),clearV2AgentTransformSurface(ownerToken),clearToolNameRegistry(),registerV2ConfigRebuildSourceForOwner(ownerToken,void 0),setV2OperatorQuietForOwner(ownerToken,void 0),clearV2OwnerRegistrationSnapshot(ownerToken),clearV2CtxOwnerBinding(ctx);for(let registration of state2.registrations)try{await withTimeout(registration.dispose(),V2_SETUP_TIMEOUT_MS,Error("[opencode-swarm] v2 cleanup: registration dispose exceeded budget"))}catch(err){log("v2 registration dispose failed (non-fatal)",{error:err instanceof Error?err.message:String(err)})}if(state2.disposeV1)await withTimeout(state2.disposeV1(),V2_SETUP_TIMEOUT_MS,Error("[opencode-swarm] v2 cleanup: v1 dispose exceeded budget")).catch((err)=>{log("v1 dispose during v2 cleanup failed (non-fatal)",{error:err instanceof Error?err.message:String(err)})})}}catch(err){throw registerV2ConfigRebuildSourceForOwner(ownerToken,void 0),setV2OperatorQuietForOwner(ownerToken,void 0),clearV2OwnerRegistrationSnapshot(ownerToken),clearV2AgentTransformSurface(ownerToken),clearV2CtxOwnerBinding(ctx),err}}function seedV1SessionState(sessionID,agentRef,directory){if(typeof sessionID!=="string"||sessionID.length===0)return;let agentName=normalizeV2AgentRef(agentRef);if(agentName===void 0)return sessionID;recordPrimaryOwner(sessionID,agentName);try{let session=ensureAgentSession(sessionID,agentName,directory);session.lastAgentEventTime=Date.now()}catch{}return swarmState.activeAgent.set(sessionID,agentName),sessionID}function v2ToolInputSchema(args2){try{if(args2&&typeof args2==="object")return exports_external.toJSONSchema(exports_external.object(args2))}catch{}return{type:"object"}}init_manifest_files();init_p_limit();init_knowledge_curator();init_knowledge_reinforcement();init_knowledge_store();init_knowledge_validator();init_micro_reflector();init_logger();init_timeout();init_candidate_queue();init_provenance();var SCREENING_TOKEN_ESTIMATE=400,SCREENING_PROMPT_CAP=1200;function unionSourceKnowledgeIds(entry,ids){let next=entry.source_knowledge_ids;for(let id of ids)next=unionInsightMarker(next,id);entry.source_knowledge_ids=next??[]}function findActiveEntryWithMarker(entries2,marker){return entries2.find((entry)=>isActiveSwarmKnowledgeEntry(entry)&&(entry.source_knowledge_ids??[]).includes(marker))}function buildScreeningPrompt(candidate2){return["A subagent proposed this durable procedural lesson for the shared knowledge store.","Answer with exactly one word: ADMIT or REJECT.","REJECT when the lesson is task-specific trivia, a transient environment failure, or not generalizable.","",`LESSON: ${candidate2.lesson}`,`CATEGORY: ${candidate2.category}`,`SCOPE: agents=${(candidate2.applies_to_agents??[]).join(",")} tools=${(candidate2.applies_to_tools??[]).join(",")}`].join(`
|
|
7473
7473
|
`).slice(0,SCREENING_PROMPT_CAP)}async function screenCandidate(candidate2,deps){let perCandidateMs=deps.llmTimeoutMs??0;if(!deps.llmDelegate||perCandidateMs<=0||!deps.sessionID)return!0;let llmDelegate=deps.llmDelegate;if(!deps.llmBudget)return!0;let remainingMs2=deps.remainingBudgetMs?.()??Number.POSITIVE_INFINITY,timeoutMs=Math.min(perCandidateMs,Math.max(0,remainingMs2));if(timeoutMs<=0)return!0;if(!reserveLlmBudget(deps.sessionID,SCREENING_TOKEN_ESTIMATE,deps.llmBudget))return!0;return!/\bREJECT\b/i.test(await withTimeoutSignal((signal2)=>llmDelegate("",buildScreeningPrompt(candidate2),signal2),timeoutMs,Error(`Knowledge admission screening timed out after ${timeoutMs}ms`)))}async function admitCandidate(directory,candidate2,deps){let candidateId2=resolveInsightCandidateId(candidate2),marker=insightAdmissionMarker(candidateId2),now2=deps.now??(()=>Date.now());if(!validateActionableFields({applies_to_agents:candidate2.applies_to_agents,applies_to_tools:candidate2.applies_to_tools,required_actions:candidate2.required_actions,forbidden_actions:candidate2.forbidden_actions,verification_checks:candidate2.verification_checks,triggers:candidate2.triggers,directive_priority:candidate2.directive_priority}).valid)return{outcome:"rejected",reason:"invalid_shape",marker};let actionability=validateActionability({applies_to_agents:candidate2.applies_to_agents,applies_to_tools:candidate2.applies_to_tools,required_actions:candidate2.required_actions,forbidden_actions:candidate2.forbidden_actions,verification_checks:candidate2.verification_checks});if(!actionability.actionable)return{outcome:"rejected",reason:actionability.reason??"unactionable",marker};if(!await screenCandidate(candidate2,deps))return{outcome:"rejected",reason:"screened_out",marker};let provenance=stampLearningProvenance({mechanism:candidate2.source?.kind==="prm_pattern"?"prm_pattern":"micro_reflection",sourceKnowledgeIds:[marker],sourceTaskIds:candidate2.source?.task_id?[candidate2.source.task_id]:[],sourceEvidenceRefs:candidate2.source_refs??[]},{sessionId:deps.sessionID,agentRole:candidate2.source?.agent,producedAt:new Date(now2()).toISOString()}),knowledgePath=(deps.resolveKnowledgePath??resolveSwarmKnowledgePath)(directory),entry=insightCandidateToEntry(candidate2,deps.projectName,deps.phaseNumber,deps.knowledgeConfig);if(unionSourceKnowledgeIds(entry,provenance.sourceKnowledgeIds),provenance.sourceEvidenceRefs.length>0){let refs=new Set([...entry.source_refs??[],...provenance.sourceEvidenceRefs]);entry.source_refs=[...refs]}let outcome="rejected",reason="no_change",entryId;if(await transactKnowledge(knowledgePath,(current)=>{if(findActiveEntryWithMarker(current,marker))return outcome="rejected",reason="already_admitted",null;let duplicate=findActiveSwarmNearDuplicate(entry.lesson,current,deps.knowledgeConfig.dedup_threshold);if(duplicate){let result=reinforceSwarmKnowledgeEntry(duplicate,{phase_number:deps.phaseNumber,confirmed_at:new Date(now2()).toISOString(),project_name:deps.projectName});return unionSourceKnowledgeIds(duplicate,[marker]),outcome="reinforced",reason=result.reason,entryId=duplicate.id,current}return current.push(entry),outcome="admitted",reason=void 0,entryId=entry.id,current}),outcome!=="rejected")deps.onKnowledgeChanged?.();return{outcome,reason,entryId,marker,provenance}}async function realtimeAdmissionAfter(directory,input,config3,resolveDeps){if(!isTaskTool(input.tool))return;if(!config3?.enabled)return;let sessionID=typeof input.sessionID==="string"&&input.sessionID.length>0?input.sessionID:void 0;if(!sessionID)return;if(getQueueDepth(sessionID)===0)return;let deps=await resolveDeps();return drainSessionQueue(directory,sessionID,config3,deps)}function emptySummary(){return{attempted:0,admitted:0,reinforced:0,rejected:0,deferred:0,failed:0,retries:0}}async function drainSessionQueue(directory,sessionID,config3,deps){let summary=emptySummary();if(!config3.enabled)return summary;let now2=deps.now??(()=>Date.now()),stats2=getQueueStats(sessionID);if(stats2.depth===0)return summary;let velocity=computeArrivalVelocity(stats2,now2()),size=computeDrainSize(stats2.depth,velocity,{minDrain:config3.min_drain,maxDrain:config3.max_drain,drainDepthFactor:config3.drain_depth_factor,drainVelocityFactor:config3.drain_velocity_factor});if(size<=0)return summary;let batch=takeDrainBatch(sessionID,size);if(batch.length===0)return summary;summary.attempted=batch.length;let startedAt=now2(),wallTimeMs=Math.max(0,Number(config3.max_drain_wall_time_ms)||0),deadline=wallTimeMs>0?startedAt+wallTimeMs:Number.POSITIVE_INFINITY,budgetExhausted=()=>now2()>=deadline,maxRetries=Math.max(0,Math.floor(Number(config3.max_retries_per_candidate)||0)),limit=pLimit(Math.max(1,Math.floor(Number(config3.max_concurrent_admissions)||1))),admissionDeps={...deps,sessionID,llmTimeoutMs:config3.max_llm_calls_per_session>0?deps.llmTimeoutMs??config3.per_candidate_llm_timeout_ms:0,llmBudget:deps.llmBudget??{maxLlmCallsPerSession:config3.max_llm_calls_per_session,maxTokensPerSession:config3.max_tokens_per_session},remainingBudgetMs:()=>deadline-now2()},deferOrAbandon=(item)=>{if(item.attempts>=MAX_CANDIDATE_DRAIN_ATTEMPTS){summary.failed++,warn(`[learning-admission] candidate abandoned after ${item.attempts} drain attempt(s) without completing`);return}requeueCandidate(sessionID,item,{maxQueueSize:config3.max_queue_size}),summary.deferred++};return await Promise.all(batch.map((item)=>limit(async()=>{if(budgetExhausted()){deferOrAbandon(item);return}for(let attempt=0;;attempt++)try{let result=await admitCandidate(directory,item.candidate,admissionDeps);if(result.outcome==="admitted")summary.admitted++;else if(result.outcome==="reinforced")summary.reinforced++;else summary.rejected++;return}catch(err){if(attempt>=maxRetries){warn(`[learning-admission] candidate failed after ${attempt+1} attempt(s): ${isAbortError(err)?"cancelled":err instanceof Error?err.message:String(err)}`),deferOrAbandon(item);return}if(summary.retries++,recordRetry(sessionID),budgetExhausted()){deferOrAbandon(item);return}}}))),summary}init_memory();init_provider_pool();init_task_model_routing();init_observability();init_otlp_exporter();init_startup_contract();init_manager();init_prm();init_trajectory_store();init_sweep();init_ephemeral_agent_dispatcher();function createReviewModelDispatcher(client,pricing){return{dispatch:(request)=>dispatchEphemeralAgent({client,directory:request.directory,parentSessionId:request.parentSessionId,agentName:request.agentName,model:request.model,system:request.system,prompt:request.prompt,readOnlyTools:request.tools??DEFAULT_READ_ONLY_TOOLS,title:request.title,timeoutMs:request.timeoutMs&&request.timeoutMs>0?request.timeoutMs:DEFAULT_EPHEMERAL_TIMEOUT_MS,promptByteLimit:request.promptByteLimit,responseByteLimit:request.responseByteLimit,abortSignal:request.abortSignal,pricing})}}init_finding_validator();init_runtime3();init_effective_spec();init_compaction_service();init_config_doctor();init_cost_accounting();init_injection_budget();init_model_preflight();init_version_check();init_snapshot_coordination_init();init_snapshot_reader();init_snapshot_store();init_snapshot_writer();init_state();init_telemetry();init_startup_contract();init_zod();init_lifecycle();init_loader();init_ephemeral_agent_dispatcher();init_gate_evidence();init_utils2();init_ledger();init_manager();init_utils3();init_runtime3();init_atomic_write();init_logger();init_model_dispatch_fallback();init_provider_error_classification();init_swarm_artifact_cache();init_config();init_lifecycle();init_next_wave_format();import{createHash as createHash106}from"node:crypto";import*as fs187 from"node:fs";import*as path321 from"node:path";var EPIC_PHASE_REVIEW_FILENAME="epic-phase-review.json",EPIC_PHASE_REVIEW_TTL_MS=86400000,EPIC_PHASE_REVIEW_FORWARD_SKEW_MS=300000,EPIC_PHASE_REVIEW_DISPATCH_TIMEOUT_MS=300000;function resolveEpicPhaseReviewTimeoutMs(directory){try{let configured=resolveEpicConfig(loadPluginConfigWithMeta(directory).config)?.phase_review?.timeout_ms;return typeof configured==="number"?configured:EPIC_PHASE_REVIEW_DISPATCH_TIMEOUT_MS}catch{return EPIC_PHASE_REVIEW_DISPATCH_TIMEOUT_MS}}var EPIC_PHASE_REVIEW_TOOL="epic_phase_review",EPIC_PHASE_REVIEW_BASH_RETRY_NOTE="You have a `bash` tool for this review. Use it only to read and inspect (for example cat, ls, grep, git log, git diff, git show). Never run a command that creates, modifies or deletes files, changes git state (checkout, stash, reset, commit), installs packages, or runs tests.",EPIC_PHASE_REVIEW_BASH_RETRY_TOOLS=Object.freeze(Object.fromEntries(Object.entries(DEFAULT_READ_ONLY_TOOLS).filter(([name])=>name!=="bash"))),MAX_REASON_CHARS=2000;function sha25612(text){return createHash106("sha256").update(text,"utf8").digest("hex")}function taskEvidenceFingerprint(directory,taskId){if(!isValidTaskId(taskId))return"invalid-task-id";try{let bytes=fs187.readFileSync(path321.join(directory,".swarm","evidence",`${taskId}.json`));return createHash106("sha256").update(bytes).digest("hex")}catch(error93){let code=error93.code;return code==="ENOENT"||code==="ENAMETOOLONG"?"missing":"unreadable"}}function currentEpicKey(directory){try{return _internals274.getOpenEpic(directory)?.epicKey??null}catch{return null}}function computeEpicPhaseBinding(directory,plan,phase){let target=plan.phases.find((item)=>item.id===phase);if(!target)return{ok:!1,reason:`phase ${phase} is not in the current plan`};let tasks=[...target.tasks].sort((a,b)=>a.id<b.id?-1:a.id>b.id?1:0),taskIds=tasks.map((task2)=>task2.id);return{ok:!0,incompleteTaskIds:tasks.filter((task2)=>task2.status!=="completed"&&task2.status!=="closed").map((task2)=>task2.id),binding:{epic_key:currentEpicKey(directory),plan_id:derivePlanId(plan),plan_structure_hash:computePlanStructureHash(plan),phase_task_ids:taskIds,phase_tasks_digest:sha25612(JSON.stringify(tasks.map((task2)=>[task2.id,task2.status]))),task_evidence_digest:sha25612(JSON.stringify(taskIds.map((id)=>[id,_internals274.taskEvidenceFingerprint(directory,id)])))}}}function evidencePath(directory,phase){return validateSwarmPath(directory,path321.posix.join("evidence",String(phase),EPIC_PHASE_REVIEW_FILENAME))}var VERDICTS=new Set(["APPROVED","NEEDS_REVISION","REJECTED"]);function isRoleVerdict(value,role){if(!value||typeof value!=="object"||Array.isArray(value))return!1;let v=value;return v.role===role&&typeof v.agent==="string"&&v.agent.length>0&&typeof v.verdict==="string"&&VERDICTS.has(v.verdict)&&(v.reason===null||typeof v.reason==="string")&&(v.dispatch==="completed"||v.dispatch==="unparseable"||v.dispatch==="failed")&&(v.tool_profile===void 0||v.tool_profile==="read-only"||v.tool_profile==="read-only-with-bash")&&typeof v.dispatched_at==="string"}function isBinding(value){if(!value||typeof value!=="object"||Array.isArray(value))return!1;let v=value;return(v.epic_key===void 0||v.epic_key===null||typeof v.epic_key==="string")&&typeof v.plan_id==="string"&&typeof v.plan_structure_hash==="string"&&Array.isArray(v.phase_task_ids)&&v.phase_task_ids.every((id)=>typeof id==="string")&&typeof v.phase_tasks_digest==="string"&&typeof v.task_evidence_digest==="string"}function parseEpicPhaseReviewEvidence(raw){if(!raw||typeof raw!=="object"||Array.isArray(raw))return null;let v=raw;if(v.schema_version!==1||v.kind!=="epic_phase_review"||typeof v.phase!=="number"||!Number.isInteger(v.phase)||typeof v.reviewed_at!=="string"||typeof v.parent_session_id!=="string"||!isBinding(v.binding)||!isRoleVerdict(v.reviewer,"reviewer")||!(v.critic===null||isRoleVerdict(v.critic,"critic")))return null;return raw}function readEpicPhaseReviewEvidence(directory,phase){let text;try{text=fs187.readFileSync(evidencePath(directory,phase),"utf-8")}catch(error93){if(error93.code==="ENOENT")return{status:"missing"};return{status:"invalid",detail:error93 instanceof Error?error93.message:String(error93)}}let parsed;try{parsed=JSON.parse(text)}catch{return{status:"invalid",detail:"evidence is not valid JSON"}}let evidence2=parseEpicPhaseReviewEvidence(parsed);return evidence2?{status:"found",evidence:evidence2}:{status:"invalid",detail:"evidence does not match schema v1"}}function rerunHint(phase){return`Call ${EPIC_PHASE_REVIEW_TOOL}({ phase: ${phase} }) — it dispatches the phase reviewer and then the phase critic and records both verdicts — then retry phase_complete.`}function openEpicWavesForPhase(record3,phase){return record3.waves.filter((wave)=>wave.phase===phase&&wave.status==="issued").map((wave)=>wave.seq)}function describeOpenEpicWaves(directory,phase){let record3;try{record3=_internals274.getOpenEpic(directory)}catch(error93){return`the open epic's record is unreadable (${error93 instanceof Error?error93.message:String(error93)}), so its waves cannot be verified (fail closed). Ask the user to run \`/swarm epic status\`.`}if(!record3)return null;let open11=openEpicWavesForPhase(record3,phase);if(open11.length===0)return null;return`wave ${open11.join(", ")} of phase ${phase} is still open. Call epic_next_wave — it closes a wave once every task in it is resolved — until it returns phase-ready-for-review.`}async function verifyEpicPhaseReadiness(directory,phase,nowMs3){let openWaves=describeOpenEpicWaves(directory,phase);if(openWaves!==null)return{ok:!1,code:"EPIC_PHASE_WAVES_OPEN",reason:`Phase ${phase} cannot complete: ${openWaves}`};let read=_internals274.readEvidence(directory,phase),rel3=`.swarm/evidence/${phase}/${EPIC_PHASE_REVIEW_FILENAME}`;if(read.status==="missing")return{ok:!1,code:"EPIC_PHASE_REVIEW_MISSING",reason:`Epic Mode requires an APPROVED phase reviewer and phase critic before phase ${phase} can complete, but ${rel3} does not exist. ${rerunHint(phase)}`};if(read.status==="invalid")return{ok:!1,code:"EPIC_PHASE_REVIEW_INVALID",reason:`Epic phase review evidence ${rel3} is unreadable or malformed (${read.detail}). Do not edit it by hand. ${rerunHint(phase)}`};let evidence2=read.evidence;if(evidence2.phase!==phase)return{ok:!1,code:"EPIC_PHASE_REVIEW_INVALID",reason:`Epic phase review evidence at ${rel3} records phase ${evidence2.phase}, not phase ${phase}. ${rerunHint(phase)}`};if(evidence2.reviewer.verdict!=="APPROVED")return{ok:!1,code:"EPIC_PHASE_REVIEWER_NOT_APPROVED",reason:`Epic phase reviewer (${evidence2.reviewer.agent}) returned ${evidence2.reviewer.verdict} for phase ${phase}${evidence2.reviewer.reason?`: ${evidence2.reviewer.reason}`:""}. ${epicPhaseFixPath(phase)} Then retry phase_complete.`};if(!evidence2.critic)return{ok:!1,code:"EPIC_PHASE_CRITIC_MISSING",reason:`Epic phase critic verdict is missing for phase ${phase}. ${rerunHint(phase)}`};if(evidence2.critic.verdict!=="APPROVED")return{ok:!1,code:"EPIC_PHASE_CRITIC_NOT_APPROVED",reason:`Epic phase critic (${evidence2.critic.agent}) returned ${evidence2.critic.verdict} for phase ${phase}${evidence2.critic.reason?`: ${evidence2.critic.reason}`:""}. ${epicPhaseFixPath(phase)} Then retry phase_complete.`};let reviewedAtMs=Date.parse(evidence2.reviewed_at);if(!Number.isFinite(reviewedAtMs))return{ok:!1,code:"EPIC_PHASE_REVIEW_INVALID",reason:`Epic phase review evidence for phase ${phase} has an invalid reviewed_at timestamp. ${rerunHint(phase)}`};let age=nowMs3-reviewedAtMs;if(age<-EPIC_PHASE_REVIEW_FORWARD_SKEW_MS)return{ok:!1,code:"EPIC_PHASE_REVIEW_STALE",reason:`Epic phase review evidence for phase ${phase} is future-dated (${evidence2.reviewed_at}); rejected as forged or clock-skewed. ${rerunHint(phase)}`};if(age>EPIC_PHASE_REVIEW_TTL_MS)return{ok:!1,code:"EPIC_PHASE_REVIEW_STALE",reason:`Epic phase review evidence for phase ${phase} is older than 24h. ${rerunHint(phase)}`};let plan;try{plan=await _internals274.loadPlan(directory)}catch{plan=null}if(!plan)return{ok:!1,code:"EPIC_PHASE_PLAN_UNREADABLE",reason:`Cannot verify Epic phase review freshness for phase ${phase}: the plan could not be loaded.`};let current=computeEpicPhaseBinding(directory,plan,phase);if(!current.ok)return{ok:!1,code:"EPIC_PHASE_PLAN_UNREADABLE",reason:`Cannot verify Epic phase review freshness: ${current.reason}.`};let recorded=evidence2.binding,drift=[];if((recorded.epic_key??null)!==current.binding.epic_key)drift.push("epic instance");if(recorded.plan_id!==current.binding.plan_id)drift.push("plan identity");if(recorded.plan_structure_hash!==current.binding.plan_structure_hash)drift.push("plan structure");if(recorded.phase_tasks_digest!==current.binding.phase_tasks_digest)drift.push("phase task set/status");if(recorded.task_evidence_digest!==current.binding.task_evidence_digest)drift.push("task gate evidence (rework after review)");if(drift.length>0)return{ok:!1,code:"EPIC_PHASE_REVIEW_STALE",reason:`Epic phase review evidence for phase ${phase} is stale — ${drift.join(", ")} changed after the review. ${rerunHint(phase)}`};return{ok:!0,evidence:evidence2}}function parseEpicPhaseVerdict(text){let lines=text.split(/\r?\n/),found=[];for(let i=0;i<lines.length;i++){let match=/^\s*(?:\*\*)?VERDICT(?:\*\*)?\s*:\s*(?:\*\*)?\s*(APPROVED|NEEDS_REVISION|REJECTED)\s*(?:\*\*)?\s*$/i.exec(lines[i]);if(match)found.push({verdict:match[1].toUpperCase(),index:i})}if(found.length===0)return null;if(new Set(found.map((item)=>item.verdict)).size>1)return null;let last=found[found.length-1],reason=null;for(let i=last.index+1;i<Math.min(lines.length,last.index+4);i++){let reasonMatch=/^\s*(?:\*\*)?REASON(?:\*\*)?\s*:\s*(.+)$/i.exec(lines[i]);if(reasonMatch){reason=reasonMatch[1].trim().slice(0,MAX_REASON_CHARS);break}}return{verdict:last.verdict,reason}}function buildReviewPackage(directory,plan,phase){let target=plan.phases.find((item)=>item.id===phase),tasks=target?.tasks??[],outcomes={};try{outcomes=_internals274.getOpenEpic(directory)?.tasks??{}}catch(error93){warn(`[epic-phase-readiness] epic record unreadable; reviewing without divergence: ${error93 instanceof Error?error93.message:String(error93)}`)}let filesChanged=new Set,packaged=tasks.map((task2)=>{let outcome=Object.hasOwn(outcomes,task2.id)?outcomes[task2.id]:void 0,divergence=outcome&&outcome.resolution!=="removed"?outcome:void 0,attributed=divergence?.attribution==="session"||divergence?.attribution==="git-single-task";for(let file3 of divergence&&attributed?[...divergence.declared,...divergence.undeclared]:[...divergence?.declared??[],...task2.files_touched])filesChanged.add(file3);return{id:task2.id,status:task2.status,description:task2.description,...task2.acceptance?{acceptance:task2.acceptance}:{},files_touched:[...task2.files_touched],depends:[...task2.depends],...divergence?{divergence:{declared_scope:[...divergence.declared],undeclared:[...divergence.undeclared],attribution:divergence.attribution}}:{}}});return{phase,phase_name:target?.name??`Phase ${phase}`,tasks:packaged,files_changed:[...filesChanged].sort()}}var VERDICT_FOOTER=`Conclude with exactly ONE verdict line followed by a REASON line:
|
|
7474
7474
|
|
|
7475
7475
|
VERDICT: APPROVED
|
|
@@ -7637,7 +7637,7 @@ ${hint}`}]}return{file:targetPath,status:"error",hunks:hunksTotal,hunksApplied:0
|
|
|
7637
7637
|
Evidence:
|
|
7638
7638
|
${evidence2}`:""}`;if(blockOnThreshold)return{status:"exceeded",blocked:!0,advisory:!1,count:count4,max,message:`${summary}
|
|
7639
7639
|
${repairStep()}`};return{status:"exceeded",blocked:!1,advisory:!0,count:count4,max,message:`${summary}
|
|
7640
|
-
${repairStep()}`}}init_logger();init_task_id();init_create_tool();init_resolve_working_directory();var EVIDENCE_DIR=".swarm/evidence";function isValidTaskId4(taskId){return isStrictTaskId(taskId)}function isPathWithinSwarm(filePath,workspaceRoot){let normalizedWorkspace=path332.resolve(workspaceRoot),swarmPath3=path332.join(normalizedWorkspace,".swarm","evidence");return path332.resolve(filePath).startsWith(swarmPath3)}function readEvidenceFile(evidencePath2){if(!fs195.existsSync(evidencePath2))return null;let content;try{content=fs195.readFileSync(evidencePath2,"utf-8")}catch{return null}let parsed;try{parsed=JSON.parse(content)}catch{return null}if(parsed&&typeof parsed==="object"&&Array.isArray(parsed.required_gates)&&typeof parsed.gates==="object"&&parsed.gates!==null)return parsed;return null}var check_gate_status=createSwarmTool({description:"Read-only tool to check the gate status of a specific task. Reads .swarm/evidence/{taskId}.json and returns structured JSON describing required, passed, and missing gates.",args:{task_id:exports_external.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/,'Task ID must be in N.M or N.M.P format (e.g., "1.1", "1.2.3", "1.2.3.4")').describe('The task ID to check gate status for (e.g., "1.1", "2.3.1")'),working_directory:exports_external.string().optional().describe("Explicit project root directory. When provided, .swarm/evidence/ is resolved relative to this path instead of the plugin context directory. Use this when CWD differs from the actual project root.")},async execute(args2,directory){let taskIdInput,workingDirInput;try{if(args2&&typeof args2==="object"){let obj=args2;taskIdInput=typeof obj.task_id==="string"?obj.task_id:void 0,workingDirInput=typeof obj.working_directory==="string"?obj.working_directory:void 0}}catch{}let dirResult=resolveWorkingDirectory(workingDirInput,directory);if(!dirResult.success){let errorResult={taskId:taskIdInput??"",status:"no_evidence",required_gates:[],passed_gates:[],missing_gates:[],gates:{},message:dirResult.message,todo_scan:null};return JSON.stringify(errorResult,null,2)}directory=dirResult.directory;let todoGateConfig;try{todoGateConfig=loadPluginConfigWithMeta(directory).config.todo_gate}catch(configError){log("check_gate_status: todo_gate config load threw; TODO gate evaluation skipped",configError)}if(!taskIdInput)return JSON.stringify({taskId:"",status:"no_evidence",required_gates:[],passed_gates:[],missing_gates:[],gates:{},message:"Invalid task_id: task_id is required",todo_scan:null},null,2);if(!isValidTaskId4(taskIdInput)){let errorResult={taskId:taskIdInput,status:"no_evidence",required_gates:[],passed_gates:[],missing_gates:[],gates:{},message:`Invalid task_id format: "${taskIdInput}". Must match N.M or N.M.P (e.g. "1.1", "1.2.3", "1.2.3.4")`,todo_scan:null};return JSON.stringify(errorResult,null,2)}let evidencePath2=path332.join(directory,EVIDENCE_DIR,`${taskIdInput}.json`);if(!isPathWithinSwarm(evidencePath2,directory))return JSON.stringify({taskId:taskIdInput,status:"no_evidence",required_gates:[],passed_gates:[],missing_gates:[],gates:{},message:"Invalid path: evidence path validation failed",todo_scan:null},null,2);let evidenceData=readEvidenceFile(evidencePath2);if(!evidenceData){let errorResult={taskId:taskIdInput,status:"no_evidence",required_gates:[],passed_gates:[],missing_gates:[],gates:{},message:`No evidence file found for task "${taskIdInput}" at ${evidencePath2}. Evidence file may be missing or invalid.`,todo_scan:null};return JSON.stringify(errorResult,null,2)}let gatesMap=evidenceData.gates||{},authoritativeWorkflow=evidenceData.workflow?.schema===TASK_WORKFLOW_SCHEMA_MARKER,derivedGates=deriveApplicableGateSet(evidenceData,authoritativeWorkflow?{currentDeclaredFiles:readCurrentTaskDeclaredFiles(directory,taskIdInput)}:void 0),requiredGates=derivedGates.requiredGates,passedGates=derivedGates.satisfiedGates,missingGates=derivedGates.missingGates,readOnlyNoMutation=derivedGates.readOnlyNoMutation;try{let externalPlanPath=path332.join(directory,".swarm","plan.json"),externalPlanRaw=fs195.readFileSync(externalPlanPath,"utf-8"),externalPlan=JSON.parse(externalPlanRaw),declaredTask=(externalPlan.phases??[]).flatMap((phase)=>phase.tasks??[]).find((task2)=>task2.id===taskIdInput);if(declaredTask&&declaredTask.evidence_class==="external_git"&&typeof externalPlan.title==="string"&&typeof externalPlan.swarm==="string"){let proofCurrent=externalProofCurrent({title:externalPlan.title,swarm:externalPlan.swarm},declaredTask,evidenceData),externalWorkflowMeta=evidenceData.workflow&&typeof evidenceData.workflow==="object"&&typeof evidenceData.workflow.state==="string"?{state:evidenceData.workflow.state,generation:typeof evidenceData.workflow.generation==="number"?evidenceData.workflow.generation:0}:null,externalResult=proofCurrent?{taskId:taskIdInput,status:"all_passed",required_gates:["external_attest"],passed_gates:["external_attest"],missing_gates:[],gates:gatesMap,message:`External evidence attested: task "${taskIdInput}" is satisfied by its pinned external_git anchors (issue #3422).`,todo_scan:evidenceData.todo_scan??null,workflow:externalWorkflowMeta}:{taskId:taskIdInput,status:"incomplete",required_gates:["external_attest"],passed_gates:[],missing_gates:["external_attest"],gates:gatesMap,message:`Task "${taskIdInput}" declares external_git evidence but no matched attestation exists yet. Run /swarm attest ${taskIdInput} (or re-plan it as a thin coder dispatch).`,todo_scan:evidenceData.todo_scan??null,workflow:externalWorkflowMeta};return JSON.stringify(externalResult,null,2)}}catch{}let status2=missingGates.length===0&&(readOnlyNoMutation||evidenceData.workflow?.state==="tests_run"||evidenceData.workflow?.state==="complete")?"all_passed":"incomplete",message;if(status2==="all_passed")message=`All required gates have passed for task "${taskIdInput}".`;else if(requiredGates.length===0)message=`Task "${taskIdInput}" is incomplete. No required gates are configured for this task generation.`;else message=`Task "${taskIdInput}" is incomplete. Missing gates: ${missingGates.join(", ")}.`;let secretscanVerdict="not_run";try{let evidenceResult=await loadEvidence(directory,taskIdInput);if(evidenceResult.status==="found"){let secretscanEntries=evidenceResult.bundle.entries.filter((entry)=>entry.type==="secretscan");if(secretscanEntries.length>0){let lastSecretscan=secretscanEntries[secretscanEntries.length-1];if(isSecretscanEvidence(lastSecretscan)){let{incomplete_files:incompleteFiles,incomplete_paths:incompletePaths}=lastSecretscan,findingsCount=lastSecretscan.findings_count??0,hasIncompleteCoverage=incompleteFiles>0||incompletePaths.length>0,newFindingsRaw=lastSecretscan.new_findings_count,preexistingRaw=lastSecretscan.preexisting_findings_count,newFindingsValid=typeof newFindingsRaw==="number"&&Number.isSafeInteger(newFindingsRaw)&&newFindingsRaw>=0,preexistingValid=typeof preexistingRaw==="number"&&Number.isSafeInteger(preexistingRaw)&&preexistingRaw>=0,newFindingsBasis=newFindingsValid?newFindingsRaw:findingsCount;if(newFindingsValid&&preexistingValid&&newFindingsRaw+preexistingRaw!==findingsCount)newFindingsBasis=findingsCount;let hasNewFindings=newFindingsBasis>0,policySkipped=lastSecretscan.policy_skipped_files,requestedFilesCount=lastSecretscan.requested_files,vacuousCoverage=lastSecretscan.files_scanned===0&&typeof policySkipped==="number"&&Number.isSafeInteger(policySkipped)&&policySkipped>=0&&typeof requestedFilesCount==="number"&&Number.isSafeInteger(requestedFilesCount)&&requestedFilesCount>0&&policySkipped>=requestedFilesCount&&findingsCount===0&&incompleteFiles===0&&incompletePaths.length===0,hasZeroCoverage=lastSecretscan.files_scanned===0&&!vacuousCoverage;if(hasIncompleteCoverage||hasNewFindings||hasZeroCoverage||lastSecretscan.verdict==="fail"||lastSecretscan.verdict==="rejected")if(secretscanVerdict="fail",hasIncompleteCoverage&&!hasNewFindings){if(missingGates.push("secretscan (BLOCKED — incomplete coverage)"),status2==="all_passed")status2="incomplete";message=`BLOCKED: Secretscan incomplete coverage in prior scan. ${message}`}else if(hasNewFindings&&hasIncompleteCoverage){if(missingGates.push("secretscan (BLOCKED — secrets detected; incomplete coverage)"),status2==="all_passed")status2="incomplete";message=`BLOCKED: Secretscan found secrets and incomplete coverage in prior scan (${newFindingsBasis} new on changed lines). ${message}`}else if(hasNewFindings){if(missingGates.push("secretscan (BLOCKED — secrets detected)"),status2==="all_passed")status2="incomplete";message=`BLOCKED: Secretscan found secrets in prior scan (${newFindingsBasis} new on changed lines${findingsCount>newFindingsBasis?`, ${findingsCount} total`:""}). ${message}`}else if(hasZeroCoverage){if(missingGates.push("secretscan (BLOCKED — zero coverage)"),status2==="all_passed")status2="incomplete";message=`BLOCKED: Secretscan scanned zero files in prior scan. ${message}`}else{if(missingGates.push("secretscan (BLOCKED — zero coverage)"),status2==="all_passed")status2="incomplete";message=`BLOCKED: Secretscan verdict failed without new findings or coverage gaps (possible truncation or tampering). ${message}`}else if(lastSecretscan.verdict==="pass"||lastSecretscan.verdict==="approved"||lastSecretscan.verdict==="info"){if(secretscanVerdict="pass",vacuousCoverage)message+=` Advisory: Secretscan coverage was vacuous (${lastSecretscan.policy_skipped_files} of ${lastSecretscan.requested_files} requested file(s) skipped by scan policy).`;else if(findingsCount>0)message+=` Advisory: ${findingsCount} pre-existing secret finding(s) remain visible (non-gating; secretscan green = zero new secrets on changed lines).`}}}else message+=" Advisory: No secretscan evidence found for this task. Consider running secretscan."}else if(evidenceResult.status==="invalid_schema")secretscanVerdict="fail",missingGates.push("secretscan (BLOCKED — invalid evidence)"),status2="incomplete",message=`BLOCKED: Secretscan evidence is invalid and cannot prove complete coverage. ${message}`}catch{}let todoScan=evidenceData.todo_scan,todoVerdict=evaluateTodoGate(todoScan,todoGateConfig);if(todoVerdict.status==="exceeded")if(todoVerdict.blocked){if(missingGates.push(`todo_gate (BLOCKED — ${todoVerdict.count} high-priority TODOs exceed max ${todoVerdict.max})`),status2==="all_passed")status2="incomplete";message=`BLOCKED: TODO gate threshold exceeded. ${todoVerdict.message} ${message}`}else message+=` Advisory: todo_gate threshold exceeded — ${todoVerdict.count} high-priority TODOs (FIXME/HACK/XXX) exceed max_high_priority=${todoVerdict.max}.`;let workflowMeta=evidenceData.workflow&&typeof evidenceData.workflow==="object"&&typeof evidenceData.workflow.state==="string"?{state:evidenceData.workflow.state,generation:typeof evidenceData.workflow.generation==="number"?evidenceData.workflow.generation:0}:null,workflowAttributionHint;if(status2==="incomplete"&&workflowMeta?.state==="coder_delegated"&&!gatesMap.pre_check)workflowAttributionHint="Task is settled at coder_delegated but Stage A (pre_check_batch) was never attributed — "+`reviewer/test_engineer dispatches will be denied with TASK_WORKFLOW_STAGE_A_REQUIRED. Run pre_check_batch on the task's changed files; if it passes without advancing this task, run /swarm recover ${taskIdInput}.`,message+=` ${workflowAttributionHint}`;let result={taskId:taskIdInput,status:status2,required_gates:requiredGates,passed_gates:passedGates,missing_gates:missingGates,gates:gatesMap,message,todo_scan:todoScan??null,secretscan_verdict:secretscanVerdict,workflow:workflowMeta,...workflowAttributionHint?{workflow_attribution_hint:workflowAttributionHint}:{}};return JSON.stringify(result,null,2)}});init_checkpoint();init_co_change_analyzer();init_zod();init_loader();init_pr_workflow_gate();init_create_tool();var CompletePrWorkflowArgsSchema=exports_external.object({mode:exports_external.enum(["PR_REVIEW","PR_FEEDBACK"]),pr_head_sha:exports_external.string().trim().min(1).max(80),report_verdict:exports_external.enum(["APPROVE","REQUEST_CHANGES","INCOMPLETE"]).optional()}).strict().superRefine((value,ctx)=>{if(value.mode==="PR_REVIEW"&&value.report_verdict===void 0)ctx.addIssue({code:"custom",path:["report_verdict"],message:"is required for PR_REVIEW completion (issue #2383 terminal report)"})});async function executeCompletePrWorkflow(args2,directory,context={}){let parsed=CompletePrWorkflowArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid PR workflow completion: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`});if(!context.sessionID?.trim())return JSON.stringify({success:!1,message:"PR workflow completion requires an active sessionID"});let staleDisclosure={},laneLiveness;try{let config3=loadPluginConfig(directory),hooks2=config3.hooks;laneLiveness={laneLivenessWatchdog:config3.lane_liveness_watchdog,backgroundPendingTimeoutMs:hooks2?.background_pending_timeout_minutes!==void 0?hooks2.background_pending_timeout_minutes*60000:void 0}}catch{}try{let settlement=await _internals288.settlePresumedStalePrWorkflowLanes(directory,context.sessionID,laneLiveness);if(settlement.presumedStaleLaneIds.length>0)staleDisclosure={presumed_stale_lanes:settlement.presumedStaleLaneIds,presumed_stale_disclosure:settlement.disclosure};if(settlement.probedAliveLaneIds?.length)staleDisclosure.probe_retained_lanes=settlement.probedAliveLaneIds;if(settlement.probeDegradedReason)staleDisclosure.probe_status=settlement.probeDegradedReason;if(settlement.horizonConflictNote)staleDisclosure.horizon_conflict=settlement.horizonConflictNote}catch{}let amendmentDisclosure={};try{let gateState=await _internals288.readPrWorkflowGateState(directory,context.sessionID);if(gateState?.prFeedbackInventoryAmendments?.length)amendmentDisclosure={inventory_amendments:gateState.prFeedbackInventoryAmendments}}catch{}try{let terminalReport;if(parsed.data.mode==="PR_REVIEW"){let coverage=null;try{coverage=await _internals288.readPrReviewTerminalCoverageForReport(directory,context.sessionID)}catch{}if(coverage){let findingPolicy;try{findingPolicy=await _internals288.readPrReviewFinalFindingPolicyForReport(directory,context.sessionID)}catch{}terminalReport={kind:coverage.kind,covered_dimensions:coverage.coveredDimensions,unresolved_dimensions:coverage.unresolvedDimensions,live_dimensions:coverage.liveDimensions,allowed_verdicts:findingPolicy?.permittedVerdicts??coverage.allowedVerdicts,...findingPolicy?{finding_policy_version:findingPolicy.policyVersion,blocking_finding_ids:findingPolicy.blockingFindingIds}:{},report_verdict:parsed.data.report_verdict,...((summary)=>summary?{findings_summary:summary}:{})(await findingsSummaryForReportSafe(directory,context.sessionID)),coverage_degradations:await coverageDegradationsForReportSafe(directory,context.sessionID),verdict_settlement:await verdictSettlementSummaryForReportSafe(directory,context.sessionID)}}}let status2=await _internals288.completePrWorkflow(directory,context.sessionID,parsed.data.mode,parsed.data.pr_head_sha,parsed.data.mode==="PR_REVIEW"?{reportVerdict:parsed.data.report_verdict,...laneLiveness?{laneLiveness}:{}}:laneLiveness?{laneLiveness}:void 0),checkoutRestoreRequired=!1,checkoutRestoreReceipts=[];if(status2==="completed"){if(parsed.data.mode==="PR_REVIEW"&&parsed.data.report_verdict==="INCOMPLETE"&&terminalReport)terminalReport.allowed_verdicts=["INCOMPLETE"];try{checkoutRestoreReceipts=await _internals288.listPendingPrWorkflowCheckoutRestores(directory,context.sessionID),checkoutRestoreRequired=checkoutRestoreReceipts.length>0}catch{checkoutRestoreRequired=!0}}return JSON.stringify({success:!0,mode:parsed.data.mode,pr_head_sha:parsed.data.pr_head_sha,status:status2,ready_to_publish:status2==="ready-to-publish",verified_no_change:status2==="verified-no-change",gate_cleared:status2==="completed"||status2==="verified-no-change",checkout_restore_required:checkoutRestoreRequired,checkout_restore_receipts:checkoutRestoreReceipts,...terminalReport?{terminal_report:terminalReport}:{},...staleDisclosure,...amendmentDisclosure})}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:String(error93),...staleDisclosure,...amendmentDisclosure})}}var complete_pr_workflow=createSwarmTool({description:"Validate terminal PR workflow coverage. After the ordered PR_FEEDBACK gates permit one standalone commit, the first call requires a clean tree and a non-merge direct child of intake HEAD, then binds its structured upstream target; the second clears only after both the local tracking ref and an actual-remote query point to that exact commit. A cleared result reports checkout_restore_required when preserved pre-workflow changes must be restored.",args:{mode:CompletePrWorkflowArgsSchema.shape.mode,pr_head_sha:CompletePrWorkflowArgsSchema.shape.pr_head_sha,report_verdict:CompletePrWorkflowArgsSchema.shape.report_verdict},execute:executeCompletePrWorkflow}),_internals288={completePrWorkflow,listPendingPrWorkflowCheckoutRestores,readPrWorkflowGateState,readPrReviewTerminalCoverageForReport,readPrReviewFinalFindingPolicyForReport,settlePresumedStalePrWorkflowLanes,verdictSettlementSummaryForReportSafe};async function verdictSettlementSummaryForReport(directory,sessionID){let{readPrReviewVerdictSettlementReceiptItems:readPrReviewVerdictSettlementReceiptItems2}=await Promise.resolve().then(() => (init_pr_workflow_gate(),exports_pr_workflow_gate));return readPrReviewVerdictSettlementReceiptItems2(directory,sessionID)}async function verdictSettlementSummaryForReportSafe(directory,sessionID){try{return await verdictSettlementSummaryForReport(directory,sessionID)}catch{return}}async function findingsSummaryForReport(directory,sessionID){let{readAuthoritativeFindingPolicy:readAuthoritativeFindingPolicy2}=await Promise.resolve().then(() => (init_pr_workflow_gate(),exports_pr_workflow_gate)),state2=await readPrWorkflowGateState(directory,sessionID);if(!state2)throw Error("BLOCKED: no active PR workflow gate state");let{policyFindings}=await readAuthoritativeFindingPolicy2(directory,state2),severityAxes=new Set(["CRITICAL","HIGH","MEDIUM","LOW","INFO","NONE"]),bySeverity={};for(let finding of policyFindings){let axis=severityAxes.has(finding.severity)?finding.severity:"OTHER";bySeverity[axis]=(bySeverity[axis]??0)+1}return{total:policyFindings.length,by_severity:bySeverity}}async function findingsSummaryForReportSafe(directory,sessionID){try{return await findingsSummaryForReport(directory,sessionID)}catch{return}}var MAX_TERMINAL_COVERAGE_DEGRADATIONS=10,MAX_TERMINAL_DEGRADATION_REASON_CHARS=200,MAX_TERMINAL_DEGRADATION_ID_CHARS=200;function boundTerminalText(value,max){return value.slice(0,max)}function redactTerminalCleanLiteral(value){return value.includes("CLEAN")?value.split("CLEAN").join("clean-attestation"):value}async function coverageDegradationsForReport(directory,sessionID){let state2=await readPrWorkflowGateState(directory,sessionID);if(!state2)return[];let{readPrReviewTriggerReceiptForGate:readPrReviewTriggerReceiptForGate2}=await Promise.resolve().then(() => (init_pr_review_trigger_receipt_reader(),exports_pr_review_trigger_receipt_reader)),read=readPrReviewTriggerReceiptForGate2(directory,state2.prReviewTriggerEvalPath??null);if("noReceipt"in read)return[];return read.receipt.coverageDegradations.slice(0,MAX_TERMINAL_COVERAGE_DEGRADATIONS).map((degradation)=>({trigger_id:degradation.trigger_id,source_batch_id:boundTerminalText(redactTerminalCleanLiteral(degradation.source_batch_id),MAX_TERMINAL_DEGRADATION_ID_CHARS),source_lane_id:boundTerminalText(redactTerminalCleanLiteral(degradation.source_lane_id),MAX_TERMINAL_DEGRADATION_ID_CHARS),reason:boundTerminalText(redactTerminalCleanLiteral(degradation.reason),MAX_TERMINAL_DEGRADATION_REASON_CHARS)}))}async function coverageDegradationsForReportSafe(directory,sessionID){try{return await coverageDegradationsForReport(directory,sessionID)}catch{return[]}}init_zod();init_utils2();init_state();init_swarm_artifact_cache();init_create_tool();init_resolve_working_directory();import*as fs196 from"node:fs";import*as path333 from"node:path";function extractMatches(regex,text){return Array.from(text.matchAll(regex))}function parseIdentifiers(description){let identifiers=new Set,backtickRegex=/`([^`]+)`/g;for(let match of extractMatches(backtickRegex,description))identifiers.add(match[1]);let camelCaseRegex=/\b([a-z][a-zA-Z0-9]{2,})\b/g;for(let match of extractMatches(camelCaseRegex,description)){let word=match[1];if(word==="the"||word==="and"||word==="for"||word==="have"||word==="this"||word==="with"||word==="from"||word==="they"||word==="been"||word==="will"||word==="your"||word==="also")continue;identifiers.add(word)}let pascalCaseRegex=/\b([A-Z][a-zA-Z0-9]{2,})\b/g;for(let match of extractMatches(pascalCaseRegex,description))identifiers.add(match[1]);let configKeyRegex=/\b([a-z][a-zA-Z0-9]*(?:\.[a-z][a-zA-Z0-9]*)+)\b/g;for(let match of extractMatches(configKeyRegex,description))identifiers.add(match[1]);let quotedPathRegex=/['"](\.{0,3}(?:src|lib|test)[/\\][^'"]+)['"]/g;for(let match of extractMatches(quotedPathRegex,description))identifiers.add(match[1]);return Array.from(identifiers)}function parseFilePaths(description,filesTouched){if(filesTouched&&Array.isArray(filesTouched)&&filesTouched.length>0)return filesTouched;let filePaths=[],srcPathRegex=/\b(?:src|lib|test|app|packages?)[/\\][a-zA-Z0-9_./-]+\.(?:ts|tsx|js|jsx|mjs|cjs)\b/g;for(let match of extractMatches(srcPathRegex,description))filePaths.push(match[0]);let genericPathRegex=/\b[a-zA-Z0-9_./-]+[/\\][a-zA-Z0-9_./-]+\.[a-zA-Z0-9]+(?=\s|$|[.,;])/g;for(let match of extractMatches(genericPathRegex,description)){let pathStr=match[0];if(pathStr.includes("src/")||pathStr.includes("src\\")||pathStr.includes("lib/")||pathStr.includes("lib\\")||pathStr.includes("test/")||pathStr.includes("test\\"))filePaths.push(pathStr)}return filePaths}function buildVerifySummary(tasksChecked,tasksSkipped,tasksBlocked){if(tasksBlocked>0)return`Blocked: ${tasksBlocked} task(s) with missing identifiers`;let verified=tasksChecked-tasksSkipped;if(tasksSkipped===tasksChecked)return`All ${tasksChecked} completed task(s) skipped — research/inventory tasks`;if(tasksSkipped>0)return`${verified} task(s) verified, ${tasksSkipped} skipped (research tasks)`;return`All ${tasksChecked} completed tasks verified successfully`}async function executeCompletionVerify(args2,directory){let phase=Number(args2.phase);if(Number.isNaN(phase)||phase<1||!Number.isFinite(phase))return JSON.stringify({success:!1,phase,status:"blocked",reason:"Invalid phase number",tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]},null,2);if(hasActiveTurboMode(args2.sessionID))return JSON.stringify({success:!0,phase,status:"passed",reason:"Turbo Mode active — completion verification bypassed",tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]},null,2);let plan;try{let planPath=validateSwarmPath(directory,"plan.json"),planRaw=fs196.readFileSync(planPath,"utf-8");plan=JSON.parse(planRaw)}catch{return JSON.stringify({success:!0,phase,status:"passed",reason:"Cannot verify without plan.json",tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]},null,2)}let targetPhase=plan.phases.find((p)=>p.id===phase);if(!targetPhase){let result2={success:!1,phase,status:"blocked",reason:`Phase ${phase} not found in plan.json`,tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]};return JSON.stringify(result2,null,2)}let tasksChecked=0,tasksSkipped=0,tasksBlocked=0,blockedTasks=[];for(let task2 of targetPhase.tasks){if(task2.status!=="completed")continue;tasksChecked++;let fileTargets=parseFilePaths(task2.description,task2.files_touched),identifiers=parseIdentifiers(task2.description);if(fileTargets.length===0){tasksSkipped++;continue}if(identifiers.length===0){blockedTasks.push({task_id:task2.id,identifier:"",file_path:"",reason:"No identifiers — cannot verify completion without identifiers"}),tasksBlocked++;continue}let foundIdentifiers=new Set,hasFileReadFailure=!1;for(let filePath of fileTargets){let normalizedPath=filePath.replace(/\\/g,"/"),resolvedPath=path333.resolve(directory,normalizedPath),projectRoot=path333.resolve(directory),relative88=path333.relative(projectRoot,resolvedPath);if(!(relative88===""||!relative88.startsWith("..")&&!path333.isAbsolute(relative88))){blockedTasks.push({task_id:task2.id,identifier:"",file_path:filePath,reason:`File path '${filePath}' escapes the project directory — cannot verify completion`}),hasFileReadFailure=!0;continue}let fileContent;try{fileContent=fs196.readFileSync(resolvedPath,"utf-8")}catch{blockedTasks.push({task_id:task2.id,identifier:"",file_path:filePath,reason:`File '${filePath}' not found — cannot verify completion`}),hasFileReadFailure=!0;continue}for(let identifier of identifiers)if(fileContent.includes(identifier))foundIdentifiers.add(identifier)}let foundCount=foundIdentifiers.size;if(hasFileReadFailure||foundCount===0){if(!hasFileReadFailure)blockedTasks.push({task_id:task2.id,identifier:"",file_path:"",reason:"No identifiers found in target files"});tasksBlocked++}}let now2=new Date().toISOString(),result={success:tasksBlocked===0,phase,status:tasksBlocked===0?"passed":"blocked",reason:tasksBlocked>0?`COMPLETION_INCOMPLETE: ${tasksBlocked} task(s) blocked — missing identifiers or target files`:void 0,tasksChecked,tasksSkipped,tasksBlocked,blockedTasks};if(args2.writeEvidence!==!1)try{let evidenceDir=path333.join(directory,".swarm","evidence",`${phase}`),evidencePath2=path333.join(evidenceDir,"completion-verify.json");fs196.mkdirSync(evidenceDir,{recursive:!0});let evidenceBundle={schema_version:"1.0.0",task_id:"completion-verify",created_at:now2,entries:[{task_id:"completion-verify",type:"completion_verify",timestamp:now2,agent:"completion_verify",verdict:tasksBlocked===0?"pass":"fail",summary:buildVerifySummary(tasksChecked,tasksSkipped,tasksBlocked),phase,tasks_checked:tasksChecked,tasks_skipped:tasksSkipped,tasks_blocked:tasksBlocked,blocked_tasks:blockedTasks}]};fs196.writeFileSync(evidencePath2,JSON.stringify(evidenceBundle,null,2),"utf-8"),invalidateCachedArtifact(evidencePath2)}catch{}return JSON.stringify(result,null,2)}var completion_verify=createSwarmTool({description:"Deterministic pre-check verifying that plan task identifiers exist in their target source files before phase completion. Blocks if obviously incomplete.",args:{phase:exports_external.number().describe("The phase number to check"),sessionID:exports_external.string().optional().describe("Session ID for tracking state (auto-provided by plugin context)"),working_directory:exports_external.string().optional().describe("Explicit project root directory. When provided, .swarm/ is resolved relative to this path instead of the plugin context directory. Use this when CWD differs from the actual project root.")},execute:async(args2,directory)=>{let parsedArgs;try{if(args2&&typeof args2==="object"){let obj=args2;parsedArgs={phase:typeof obj.phase==="number"?obj.phase:typeof obj.phase==="string"?Number(obj.phase):0,sessionID:typeof obj.sessionID==="string"?obj.sessionID:void 0,working_directory:typeof obj.working_directory==="string"?obj.working_directory:void 0}}else parsedArgs={phase:0}}catch{return JSON.stringify({success:!1,phase:0,status:"blocked",reason:"Invalid arguments",tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]},null,2)}let dirResult=resolveWorkingDirectory(parsedArgs.working_directory,directory);if(!dirResult.success)return JSON.stringify({success:!1,phase:parsedArgs.phase,status:"blocked",reason:dirResult.message,tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]},null,2);return executeCompletionVerify(parsedArgs,dirResult.directory)}});init_zod();init_metrics();init_bun_compat();init_git_executable();init_create_tool();init_path_security();import{Buffer as Buffer4}from"node:buffer";import*as fs197 from"node:fs";import*as path334 from"node:path";var MAX_FILE_SIZE_BYTES5=262144,DEFAULT_DAYS=90,DEFAULT_TOP_N2=20,DEFAULT_EXTENSIONS="ts,tsx,js,jsx,py,rs,ps1",SHELL_METACHAR_REGEX=/[;&|%$`\\]/;function validateDays(days){if(typeof days>"u")return{valid:!0,value:DEFAULT_DAYS,error:null};if(typeof days!=="number"||!Number.isInteger(days))return{valid:!1,value:0,error:"days must be an integer"};if(days<1||days>365)return{valid:!1,value:0,error:"days must be between 1 and 365"};return{valid:!0,value:days,error:null}}function validateTopN(topN){if(typeof topN>"u")return{valid:!0,value:DEFAULT_TOP_N2,error:null};if(typeof topN!=="number"||!Number.isInteger(topN))return{valid:!1,value:0,error:"top_n must be an integer"};if(topN<1||topN>100)return{valid:!1,value:0,error:"top_n must be between 1 and 100"};return{valid:!0,value:topN,error:null}}function validateExtensions(extensions){if(typeof extensions>"u")return{valid:!0,value:DEFAULT_EXTENSIONS,error:null};if(typeof extensions!=="string")return{valid:!1,value:"",error:"extensions must be a string"};if(containsControlChars(extensions))return{valid:!1,value:"",error:"extensions contains control characters"};if(SHELL_METACHAR_REGEX.test(extensions))return{valid:!1,value:"",error:"extensions contains shell metacharacters (;|&%$`\\)"};if(!/^[a-zA-Z0-9,.]+$/.test(extensions))return{valid:!1,value:"",error:"extensions contains invalid characters (only alphanumeric, commas, dots allowed)"};return{valid:!0,value:extensions,error:null}}var _internals289={bunSpawn,resolveGitExecutable},GIT_CHURN_TIMEOUT_MS=1e4,GIT_CHURN_MAX_BUFFER_BYTES=5242880;async function getGitChurn(days,directory,abortSignal){let churnMap=new Map,proc=_internals289.bunSpawn([_internals289.resolveGitExecutable(),"log",`--since=${days} days ago`,"--name-only","--pretty=format:"],{stdout:"pipe",stderr:"pipe",stdin:"ignore",cwd:directory,timeout:GIT_CHURN_TIMEOUT_MS,maxBuffer:GIT_CHURN_MAX_BUFFER_BYTES,killProcessTree:!0,env:{...process.env,GIT_TERMINAL_PROMPT:"0"}}),churnTimeout,churnAbortCleanup,racers=[Promise.all([proc.stdout.text(),proc.exited]).then((churnOutput)=>churnOutput),new Promise((resolve132)=>{churnTimeout=setTimeout(()=>resolve132([null,"timeout"]),GIT_CHURN_TIMEOUT_MS)})];if(abortSignal!==void 0)racers.push(new Promise((resolve132)=>{let settle2=()=>resolve132([null,"aborted"]);if(abortSignal.aborted){settle2();return}let onAbort=()=>settle2();abortSignal.addEventListener("abort",onAbort,{once:!0}),churnAbortCleanup=()=>{abortSignal.removeEventListener("abort",onAbort)}}));try{let[stdout,outcome]=await Promise.race(racers);if(typeof churnTimeout<"u")clearTimeout(churnTimeout);if(outcome==="timeout")throw Error(`git churn analysis failed: git log did not finish within ${GIT_CHURN_TIMEOUT_MS} ms (bounded; child tree killed)`);if(outcome==="aborted")throw Error(`git churn analysis failed: aborted by host cancellation (ctx.abort fired before the ${GIT_CHURN_TIMEOUT_MS} ms deadline; child tree killed)`);if(proc.spawnError)throw Error(`git churn analysis failed: ${proc.spawnError.message}`);if(proc.signalCode)throw Error(`git churn analysis failed: git log was killed by ${proc.signalCode} after exceeding the ${GIT_CHURN_TIMEOUT_MS} ms / ${GIT_CHURN_MAX_BUFFER_BYTES}-byte bound`);if(Buffer4.byteLength(stdout)>=GIT_CHURN_MAX_BUFFER_BYTES)throw Error(`git churn analysis failed: git log output reached the ${GIT_CHURN_MAX_BUFFER_BYTES}-byte buffer limit`);let lines=stdout.split(/\r?\n/);for(let line of lines){let normalizedPath=line.replace(/\\/g,"/");if(!normalizedPath||normalizedPath.trim()==="")continue;if(normalizedPath.includes("node_modules")||normalizedPath.includes("/.git/")||normalizedPath.includes("/dist/")||normalizedPath.includes("/build/")||normalizedPath.includes("__tests__"))continue;if(normalizedPath.includes(".test.")||normalizedPath.includes(".spec."))continue;churnMap.set(normalizedPath,(churnMap.get(normalizedPath)||0)+1)}}finally{if(typeof churnTimeout<"u")clearTimeout(churnTimeout);churnAbortCleanup?.();try{proc.kill()}catch{}}return churnMap}function getComplexityForFile2(filePath){try{if(fs197.statSync(filePath).size>MAX_FILE_SIZE_BYTES5)return null;let content=fs197.readFileSync(filePath,"utf-8");return estimateCyclomaticComplexity(content)}catch{return null}}async function analyzeHotspots(days,topN,extensions,directory,abortSignal){let churnMap=await getGitChurn(days,directory,abortSignal),extSet=new Set(extensions.map((e)=>e.startsWith(".")?e:`.${e}`)),filteredChurn=new Map;for(let[file3,count4]of churnMap){let ext=path334.extname(file3).toLowerCase();if(extSet.has(ext))filteredChurn.set(file3,count4)}let hotspots=[],cwd=directory,analyzedFiles=0;for(let[file3,churnCount]of filteredChurn){let fullPath=file3;if(!fs197.existsSync(fullPath))fullPath=path334.join(cwd,file3);let complexity=getComplexityForFile2(fullPath);if(complexity!==null){analyzedFiles++;let riskScore=Math.round(churnCount*Math.log2(Math.max(complexity,1))*10)/10,recommendation;if(riskScore>=50)recommendation="full_gates";else if(riskScore>=30)recommendation="security_review";else if(riskScore>=15)recommendation="enhanced_review";else recommendation="standard";hotspots.push({file:file3,churnCount,complexity,riskScore,recommendation})}}hotspots.sort((a,b)=>b.riskScore-a.riskScore);let topHotspots=hotspots.slice(0,topN),summary={fullGates:topHotspots.filter((h)=>h.recommendation==="full_gates").length,securityReview:topHotspots.filter((h)=>h.recommendation==="security_review").length,enhancedReview:topHotspots.filter((h)=>h.recommendation==="enhanced_review").length,standard:topHotspots.filter((h)=>h.recommendation==="standard").length};return{analyzedFiles,period:`${days} days`,hotspots:topHotspots,summary}}var complexity_hotspots=createSwarmTool({description:"Identify high-risk code hotspots by combining git churn frequency with cyclomatic complexity estimates. Returns files with their churn count, complexity score, risk score, and recommended review level.",args:{days:exports_external.number().optional().describe("Number of days of git history to analyze (default: 90, valid range: 1-365)"),top_n:exports_external.number().optional().describe("Number of top hotspots to return (default: 20, valid range: 1-100)"),extensions:exports_external.string().optional().describe('Comma-separated extensions to include (default: "ts,tsx,js,jsx,py,rs,ps1")')},async execute(args2,directory,ctx){if(!directory||typeof directory!=="string"||directory.trim()==="")return JSON.stringify({error:"project directory is required but was not provided",analyzedFiles:0,period:"0 days",hotspots:[],summary:{fullGates:0,securityReview:0,enhancedReview:0,standard:0}},null,2);let daysInput,topNInput,extensionsInput;try{if(args2&&typeof args2==="object"){let obj=args2;daysInput=typeof obj.days==="number"?obj.days:void 0,topNInput=typeof obj.top_n==="number"?obj.top_n:void 0,extensionsInput=typeof obj.extensions==="string"?obj.extensions:void 0}}catch{}let daysValidation=validateDays(daysInput);if(!daysValidation.valid){let errorResult={error:`invalid days: ${daysValidation.error}`,analyzedFiles:0,period:"0 days",hotspots:[],summary:{fullGates:0,securityReview:0,enhancedReview:0,standard:0}};return JSON.stringify(errorResult,null,2)}let topNValidation=validateTopN(topNInput);if(!topNValidation.valid){let errorResult={error:`invalid top_n: ${topNValidation.error}`,analyzedFiles:0,period:"0 days",hotspots:[],summary:{fullGates:0,securityReview:0,enhancedReview:0,standard:0}};return JSON.stringify(errorResult,null,2)}let extensionsValidation=validateExtensions(extensionsInput);if(!extensionsValidation.valid){let errorResult={error:`invalid extensions: ${extensionsValidation.error}`,analyzedFiles:0,period:"0 days",hotspots:[],summary:{fullGates:0,securityReview:0,enhancedReview:0,standard:0}};return JSON.stringify(errorResult,null,2)}let days=daysValidation.value,topN=topNValidation.value,extensions=extensionsValidation.value.split(",").map((e)=>e.trim());try{let result=await analyzeHotspots(days,topN,extensions,directory,ctx?.abort);return JSON.stringify(result,null,2)}catch(e){let errorResult={error:e instanceof Error?`analysis failed: ${e.message}`:"analysis failed: unknown error",analyzedFiles:0,period:`${days} days`,hotspots:[],summary:{fullGates:0,securityReview:0,enhancedReview:0,standard:0}};return JSON.stringify(errorResult,null,2)}}});init_zod();init_config2();init_schema();init_miner();init_miner();init_store4();async function mineAndStoreConsensusV1(options){let priorFingerprints=options.deps.priorFingerprints??await listConsensusProposalFingerprints(options.directory),result=await mineConsensus(options.directory,options.request,{...options.deps,priorFingerprints}),report=await writeConsensusReport(options.directory,result.report);return{...result,report}}init_store4();init_memory();init_recommendation_ledger();init_state();init_logger();init_create_tool();var MAX_FILTER_ENTRIES=200,FilterListSchema=exports_external.array(exports_external.string().min(1).max(512)).max(MAX_FILTER_ENTRIES),MAX_INLINE_ATTRIBUTES=25;function countSummaries(attributes,inlineLimit){let total=0,shown=0;for(let[index,attribute]of attributes.entries()){if(attribute.llmSummary===void 0)continue;if(total+=1,index<inlineLimit)shown+=1}return{total,hidden:total-shown}}function buildMinerRecommendationCandidates(report,sessionId){return report.proposals.map((proposal)=>({kind:"miner",target:proposal.target,statement:proposal.intent,scopeKeys:[],provenance:{mechanism:"consensus_mine",sourceEvidenceRefs:proposal.evidenceRefs,sourceRunIds:proposal.provenance.sourceRunIds,sourceModelIds:proposal.provenance.sourceModelIds,sourceTaskIds:proposal.provenance.sourceTaskIds},origin:{agentRole:"consensus_mine",...sessionId?{sessionId}:{},producedAt:report.generatedAt}}))}var MIRRORED_PROPOSAL_KIND="todo";async function mirrorProposalsToMemory(options){if(options.memoryConfig?.enabled!==!0)return{enabled:!1,attempted:0,proposed:0,rejected:0,failed:0};let proposals=options.report.proposals;if(proposals.length===0)return{enabled:!0,attempted:0,proposed:0,rejected:0,failed:0};let gateway;try{gateway=_internals290.createMemoryGateway({directory:options.directory,...options.sessionId?{sessionID:options.sessionId,runId:options.sessionId}:{},agentRole:"consensus_mine"},{config:options.memoryConfig})}catch(err){let message=err instanceof Error?err.message:String(err);return warn(`[consensus_mine] memory mirror unavailable (fail-open): ${message}`),{enabled:!0,attempted:proposals.length,proposed:0,rejected:0,failed:proposals.length,error:message}}let proposed=0,rejected2=0,failed=0,error93;try{for(let proposal of proposals)try{if((await gateway.propose({operation:"add",kind:MIRRORED_PROPOSAL_KIND,text:proposal.intent,rationale:`consensus_mine proposal from report ${options.report.reportId}, attribute ${proposal.sourceAttributeId} (target ${proposal.target}, confidence ${proposal.confidence})`,evidenceRefs:proposal.evidenceRefs})).status==="rejected")rejected2+=1;else proposed+=1}catch(err){failed+=1,error93??=err instanceof Error?err.message:String(err)}}finally{try{await gateway.dispose()}catch(err){warn(`[consensus_mine] memory gateway dispose failed: ${err instanceof Error?err.message:String(err)}`)}}if(error93!==void 0)warn(`[consensus_mine] memory mirror partially failed: ${error93}`);return{enabled:!0,attempted:proposals.length,proposed,rejected:rejected2,failed,...error93?{error:error93}:{}}}var _internals290={createMemoryGateway};var consensus_mine=createSwarmTool({description:"Mine cross-run consensus from existing .swarm evidence — evaluation runs, gate audits, gate "+"ground truth, task trajectories, PRM sessions, skill usage, knowledge outcomes, evidence "+"bundles, and curated failures (nine sources) — and persist an immutable report of "+`agreed-upon attributes plus proposals-only recommendations. It never activates a skill, writes a knowledge entry, admits a durable memory record, edits a project file, or mutates any evidence it reads. It is NOT otherwise write-minimal, so plan for these effects: it DELETES its own older reports past consensus.report_retention (default 50) on every run; it rewrites the shared recommendation dedup ledger whole, with FIFO eviction that can drop another producer's oldest entries; it leaves one never-removed lock sentinel per report id under .swarm/locks/; when memory.enabled is true it mirrors each proposal into a PENDING swarm-memory proposal (curator review still required); and when consensus.llm_summarization_enabled is true (the default) it issues up to ${MAX_LLM_SUMMARIES} session.create plus session.prompt calls. Under a knowledge or memory link the ledger and the memory store resolve to the shared cohort root, outside this project's .swarm/.`,args:{run_ids:FilterListSchema.optional().describe("Restrict mining to these run ids (raw or namespaced). Omit for all runs."),task_categories:FilterListSchema.optional().describe("Restrict to these evaluation task categories. Omit for all categories."),agent_roles:FilterListSchema.optional().describe("Restrict to these agent roles. Omit for all roles."),model_ids:FilterListSchema.optional().describe("Restrict to these model ids. Omit for all models."),min_support:exports_external.number().int().min(1).max(1e4).optional().describe("Distinct runs required to emit an attribute. Defaults to consensus.default_min_support."),min_successful_runs:exports_external.number().int().min(0).max(1e4).optional().describe("Successful runs required. Defaults to consensus.default_min_successful_runs."),max_evidence_items:exports_external.number().int().min(1).max(1e4).optional().describe("Cap on corpus observations read. Defaults to consensus.default_max_evidence_items.")},execute:async(args2,directory,ctx)=>{let input=args2??{},loaded=loadPluginConfigWithMeta(directory),config3=ConsensusConfigSchema.parse(loaded.config.consensus??{});if(!config3.enabled)return JSON.stringify({success:!1,disabled:!0,message:"Consensus mining is disabled (consensus.enabled = false). No report was written."},null,2);let request={...input.run_ids?{runIds:input.run_ids}:{},...input.task_categories?{taskCategories:input.task_categories}:{},...input.agent_roles?{agentRoles:input.agent_roles}:{},...input.model_ids?{modelIds:input.model_ids}:{},minSupport:input.min_support??config3.default_min_support,minSuccessfulRuns:input.min_successful_runs??config3.default_min_successful_runs,maxEvidenceItems:input.max_evidence_items??config3.default_max_evidence_items},client=swarmState.opencodeClient,dispatcher=config3.llm_summarization_enabled&&client?createEvaluationModelDispatcher(client):void 0,result=await mineAndStoreConsensusV1({directory,request,deps:{config:config3,...dispatcher?{dispatcher}:{},...ctx?.sessionID?{sessionId:ctx.sessionID}:{},agentRole:"consensus_mine"}}),report=result.report,ledger=await recordEmittedRecommendations(directory,buildMinerRecommendationCandidates(report,ctx?.sessionID),{producedAt:report.generatedAt});if(ledger.degraded)warn("[consensus_mine] recommendation ledger write degraded; proposals were not recorded for cross-producer dedup");let memoryMirror=await mirrorProposalsToMemory({directory,memoryConfig:loaded.config.memory,report,...ctx?.sessionID?{sessionId:ctx.sessionID}:{}}),pruned=await pruneConsensusReports(directory,config3.report_retention),pruningEnabled=config3.report_retention>0,summaries=countSummaries(report.attributes,MAX_INLINE_ATTRIBUTES);return JSON.stringify({success:!0,report_id:report.reportId,report_path:`.swarm/evolution/consensus/${report.reportId}.json`,generated_at:report.generatedAt,integrity_hash:report.integrityHash,config_hash:report.configHash,redaction_policy_version:report.redactionPolicyVersion,thresholds:{min_support:request.minSupport,min_successful_runs:request.minSuccessfulRuns,max_evidence_items:request.maxEvidenceItems,min_task_diversity:MIN_TASK_DIVERSITY_FOR_PROPOSAL,min_support_for_proposal:MIN_SUPPORT_FOR_PROPOSAL},input_run_count:report.inputIds.length,corpus:report.corpusHashes.map((entry)=>({source:entry.source,observations:entry.observations})),corpus_truncated:result.truncated,truncation:{corpus:report.truncation.corpus,observations_tallied:report.truncation.observations,input_ids_truncated:report.truncation.inputIds,total_input_ids:report.truncation.totalInputIds,attributes_dropped:report.truncation.attributesDropped},unreadable_sources:result.unreadableSources,attribute_count:report.attributes.length,investigation_note_count:result.investigationNoteCount,proposal_count:report.proposals.length,deduped_proposal_count:result.dedupedProposalCount,recommendation_ledger:{recorded:ledger.recorded,duplicate_recommendation_count:ledger.suppressed,evicted:ledger.evicted,degraded:ledger.degraded},memory_mirror:memoryMirror,summarized_count:summaries.total,summarized_but_not_shown:summaries.hidden,restatements_accepted_this_run:result.summarizedCount,...result.summarizationSkippedReason?{summarization_skipped_reason:result.summarizationSkippedReason}:{},attributes:report.attributes.slice(0,MAX_INLINE_ATTRIBUTES).map((attribute)=>({id:attribute.id,statement:attribute.statement,...attribute.llmSummary?{llm_summary:attribute.llmSummary}:{},support:attribute.support,success_support:attribute.successSupport,failure_support:attribute.failureSupport,task_diversity:attribute.taskDiversity,model_diversity:attribute.modelDiversity,confidence:attribute.confidence,proposed_target:attribute.proposedTarget,counterexample_count:attribute.counterexampleRefs.length})),attributes_truncated:report.attributes.length>MAX_INLINE_ATTRIBUTES,retention:pruningEnabled?{configured:config3.report_retention,pruning_enabled:!0,deleted:pruned.deleted.length,retained:pruned.retained.length,failed:pruned.failed.length,corrupt:pruned.corrupt.length}:{configured:config3.report_retention,pruning_enabled:!1,deleted:0,failed:0},guarantees:["proposals only — no skill activation, no knowledge write, no durable memory record, and no mutation of any evidence read",'model_diversity 0 means "not measurable from this corpus", never "measured as none"',`attributes below task diversity ${MIN_TASK_DIVERSITY_FOR_PROPOSAL} or below support ${MIN_SUPPORT_FOR_PROPOSAL} are investigation notes, never proposals`,"an attribute counting failing runs always carries counterexample refs (schema-enforced)","truncation is not biased toward successes, but it is still a cut: it balances per source, and drops whole sources once the budget is spent","statement is deterministic; llm_summary is an optional restatement excluded from integrity_hash","reproducible: identical corpus, request, config_hash, and prior proposals yield the same integrity_hash and report_id; model wording never moves it",'truncation is declared on the report; read failure_support 0 on a truncated report as "none survived the cut"']},null,2)}});init_config2();init_model_limits();init_state();init_create_tool();var _internals291={loadPluginConfig,fetchSessionMessages:async(sessionID,directory,limit=100)=>{if(!swarmState.opencodeClient?.session)return null;try{return(await swarmState.opencodeClient.session.messages({path:{id:sessionID},query:{directory,limit}})).data??null}catch{return null}}};function computeContextHeadroom(messages,warnThreshold=0.7,criticalThreshold=0.9,modelLimitsConfig={},liveContextLimit,modelIdentity,directory){let{modelID,providerID}=modelIdentity??extractModelInfo(messages),modelLimitResolution=resolveModelLimit(modelID,providerID,modelLimitsConfig,liveContextLimit,directory),modelLimit=modelLimitResolution.limit,usage=computeContextUsage(messages),usagePercent=usage.tokensUsed/modelLimit,thresholdCrossed="none";if(usagePercent>criticalThreshold)thresholdCrossed="critical";else if(usagePercent>warnThreshold)thresholdCrossed="warn";return{tokensUsed:usage.tokensUsed,usageSource:usage.source,modelLimit,modelLimitSource:modelLimitResolution.source,modelLimitResolution:modelLimitResolution.resolution,fallbackActive:modelLimitResolution.source==="provider_cap"||modelLimitResolution.source==="native"||modelLimitResolution.source==="fallback",usagePercent,thresholdCrossed,modelId:modelID??null,provider:providerID??null}}var context_status=createSwarmTool({allowWorkingDirectoryOverride:!0,description:"Report current context-window headroom for the active session. Returns tokens-used, usageSource (provider|estimated), model-limit with provenance (modelLimitSource: host|override|provider_cap|native|fallback; modelLimitResolution: user_provider_model|user_model|user_default|live_model_limit|static_provider_cap|static_native|static_default; fallbackActive: true when the denominator came from a static table or the flat 128k default — treat headroom as uncertain), usage-percent, threshold-state (none|warn|critical), model name, and provider. Pure read-only — no state mutation, no warning injection. Works whether context_budget.enabled is true or false.",args:{},async execute(_args,directory,ctx){let config3=_internals291.loadPluginConfig(directory),warnThreshold=config3.context_budget?.warn_threshold??0.7,criticalThreshold=config3.context_budget?.critical_threshold??0.9,modelLimitsConfig=config3.context_budget?.model_limits??{},messages=[];if(ctx?.sessionID){let sessionMessages=await _internals291.fetchSessionMessages(ctx.sessionID,directory);if(sessionMessages)messages=sessionMessages}let{modelID,providerID}=getLiveContextModelIdentity(ctx?.sessionID)??extractModelInfo(messages),headroom=computeContextHeadroom(messages,warnThreshold,criticalThreshold,modelLimitsConfig,getLiveContextWindow(ctx?.sessionID,{modelID,providerID}),{modelID,providerID},directory);return JSON.stringify(headroom,null,2)}});init_zod();init_loader();function pushCouncilAdvisory(session,synthesis){let dedupKey=`council:${synthesis.taskId}:${synthesis.roundNumber}`;if(synthesis.overallVerdict==="APPROVE"&&synthesis.advisoryFindings.length===0)return;if(session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.some((m)=>m.includes(dedupKey)))return;let blocking=synthesis.overallVerdict==="REJECT",header=`[${dedupKey}] (priority=HIGH, blocking=${blocking})`,body=synthesis.unifiedFeedbackMd;pushAdvisory(session,`${header}
|
|
7640
|
+
${repairStep()}`}}init_logger();init_task_id();init_create_tool();init_resolve_working_directory();var EVIDENCE_DIR=".swarm/evidence";function isValidTaskId4(taskId){return isStrictTaskId(taskId)}function isPathWithinSwarm(filePath,workspaceRoot){let normalizedWorkspace=path332.resolve(workspaceRoot),swarmPath3=path332.join(normalizedWorkspace,".swarm","evidence");return path332.resolve(filePath).startsWith(swarmPath3)}function readEvidenceFile(evidencePath2){if(!fs195.existsSync(evidencePath2))return null;let content;try{content=fs195.readFileSync(evidencePath2,"utf-8")}catch{return null}let parsed;try{parsed=JSON.parse(content)}catch{return null}if(parsed&&typeof parsed==="object"&&Array.isArray(parsed.required_gates)&&typeof parsed.gates==="object"&&parsed.gates!==null)return parsed;return null}var check_gate_status=createSwarmTool({description:"Read-only tool to check the gate status of a specific task. Reads .swarm/evidence/{taskId}.json and returns structured JSON describing required, passed, and missing gates.",args:{task_id:exports_external.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/,'Task ID must be in N.M or N.M.P format (e.g., "1.1", "1.2.3", "1.2.3.4")').describe('The task ID to check gate status for (e.g., "1.1", "2.3.1")'),working_directory:exports_external.string().optional().describe("Explicit project root directory. When provided, .swarm/evidence/ is resolved relative to this path instead of the plugin context directory. Use this when CWD differs from the actual project root.")},async execute(args2,directory){let taskIdInput,workingDirInput;try{if(args2&&typeof args2==="object"){let obj=args2;taskIdInput=typeof obj.task_id==="string"?obj.task_id:void 0,workingDirInput=typeof obj.working_directory==="string"?obj.working_directory:void 0}}catch{}let dirResult=resolveWorkingDirectory(workingDirInput,directory);if(!dirResult.success){let errorResult={taskId:taskIdInput??"",status:"no_evidence",required_gates:[],passed_gates:[],missing_gates:[],gates:{},message:dirResult.message,todo_scan:null};return JSON.stringify(errorResult,null,2)}directory=dirResult.directory;let todoGateConfig;try{todoGateConfig=loadPluginConfigWithMeta(directory).config.todo_gate}catch(configError){log("check_gate_status: todo_gate config load threw; TODO gate evaluation skipped",configError)}if(!taskIdInput)return JSON.stringify({taskId:"",status:"no_evidence",required_gates:[],passed_gates:[],missing_gates:[],gates:{},message:"Invalid task_id: task_id is required",todo_scan:null},null,2);if(!isValidTaskId4(taskIdInput)){let errorResult={taskId:taskIdInput,status:"no_evidence",required_gates:[],passed_gates:[],missing_gates:[],gates:{},message:`Invalid task_id format: "${taskIdInput}". Must match N.M or N.M.P (e.g. "1.1", "1.2.3", "1.2.3.4")`,todo_scan:null};return JSON.stringify(errorResult,null,2)}let evidencePath2=path332.join(directory,EVIDENCE_DIR,`${taskIdInput}.json`);if(!isPathWithinSwarm(evidencePath2,directory))return JSON.stringify({taskId:taskIdInput,status:"no_evidence",required_gates:[],passed_gates:[],missing_gates:[],gates:{},message:"Invalid path: evidence path validation failed",todo_scan:null},null,2);let evidenceData=readEvidenceFile(evidencePath2);if(!evidenceData){let errorResult={taskId:taskIdInput,status:"no_evidence",required_gates:[],passed_gates:[],missing_gates:[],gates:{},message:`No evidence file found for task "${taskIdInput}" at ${evidencePath2}. Evidence file may be missing or invalid.`,todo_scan:null};return JSON.stringify(errorResult,null,2)}let gatesMap=evidenceData.gates||{},authoritativeWorkflow=evidenceData.workflow?.schema===TASK_WORKFLOW_SCHEMA_MARKER,derivedGates=deriveApplicableGateSet(evidenceData,authoritativeWorkflow?{currentDeclaredFiles:readCurrentTaskDeclaredFiles(directory,taskIdInput)}:void 0),requiredGates=derivedGates.requiredGates,passedGates=derivedGates.satisfiedGates,missingGates=derivedGates.missingGates,readOnlyNoMutation=derivedGates.readOnlyNoMutation;try{let externalPlanPath=path332.join(directory,".swarm","plan.json"),externalPlanRaw=fs195.readFileSync(externalPlanPath,"utf-8"),externalPlan=JSON.parse(externalPlanRaw),declaredTask=(externalPlan.phases??[]).flatMap((phase)=>phase.tasks??[]).find((task2)=>task2.id===taskIdInput);if(declaredTask&&declaredTask.evidence_class==="external_git"&&typeof externalPlan.title==="string"&&typeof externalPlan.swarm==="string"){let proofCurrent=externalProofCurrent({title:externalPlan.title,swarm:externalPlan.swarm},declaredTask,evidenceData),externalWorkflowMeta=evidenceData.workflow&&typeof evidenceData.workflow==="object"&&typeof evidenceData.workflow.state==="string"?{state:evidenceData.workflow.state,generation:typeof evidenceData.workflow.generation==="number"?evidenceData.workflow.generation:0}:null,externalResult=proofCurrent?{taskId:taskIdInput,status:"all_passed",required_gates:["external_attest"],passed_gates:["external_attest"],missing_gates:[],gates:gatesMap,message:`External evidence attested: task "${taskIdInput}" is satisfied by its pinned external_git anchors (issue #3422).`,todo_scan:evidenceData.todo_scan??null,workflow:externalWorkflowMeta}:{taskId:taskIdInput,status:"incomplete",required_gates:["external_attest"],passed_gates:[],missing_gates:["external_attest"],gates:gatesMap,message:`Task "${taskIdInput}" declares external_git evidence but no matched attestation exists yet. Run /swarm attest ${taskIdInput} (or re-plan it as a thin coder dispatch).`,todo_scan:evidenceData.todo_scan??null,workflow:externalWorkflowMeta};return JSON.stringify(externalResult,null,2)}}catch{}let status2=missingGates.length===0&&(readOnlyNoMutation||evidenceData.workflow?.state==="tests_run"||evidenceData.workflow?.state==="complete")?"all_passed":"incomplete",message;if(status2==="all_passed")message=`All required gates have passed for task "${taskIdInput}".`;else if(requiredGates.length===0)message=`Task "${taskIdInput}" is incomplete. No required gates are configured for this task generation.`;else message=`Task "${taskIdInput}" is incomplete. Missing gates: ${missingGates.join(", ")}.`;let secretscanVerdict="not_run";try{let evidenceResult=await loadEvidence(directory,taskIdInput);if(evidenceResult.status==="found"){let secretscanEntries=evidenceResult.bundle.entries.filter((entry)=>entry.type==="secretscan");if(secretscanEntries.length>0){let lastSecretscan=secretscanEntries[secretscanEntries.length-1];if(isSecretscanEvidence(lastSecretscan)){let{incomplete_files:incompleteFiles,incomplete_paths:incompletePaths}=lastSecretscan,findingsCount=lastSecretscan.findings_count??0,hasIncompleteCoverage=incompleteFiles>0||incompletePaths.length>0,newFindingsRaw=lastSecretscan.new_findings_count,preexistingRaw=lastSecretscan.preexisting_findings_count,newFindingsValid=typeof newFindingsRaw==="number"&&Number.isSafeInteger(newFindingsRaw)&&newFindingsRaw>=0,preexistingValid=typeof preexistingRaw==="number"&&Number.isSafeInteger(preexistingRaw)&&preexistingRaw>=0,newFindingsBasis=newFindingsValid?newFindingsRaw:findingsCount;if(newFindingsValid&&preexistingValid&&newFindingsRaw+preexistingRaw!==findingsCount)newFindingsBasis=findingsCount;let hasNewFindings=newFindingsBasis>0,policySkipped=lastSecretscan.policy_skipped_files,requestedFilesCount=lastSecretscan.requested_files,vacuousCoverage=lastSecretscan.files_scanned===0&&typeof policySkipped==="number"&&Number.isSafeInteger(policySkipped)&&policySkipped>=0&&typeof requestedFilesCount==="number"&&Number.isSafeInteger(requestedFilesCount)&&requestedFilesCount>0&&policySkipped>=requestedFilesCount&&findingsCount===0&&incompleteFiles===0&&incompletePaths.length===0,hasZeroCoverage=lastSecretscan.files_scanned===0&&!vacuousCoverage;if(hasIncompleteCoverage||hasNewFindings||hasZeroCoverage||lastSecretscan.verdict==="fail"||lastSecretscan.verdict==="rejected")if(secretscanVerdict="fail",hasIncompleteCoverage&&!hasNewFindings){if(missingGates.push("secretscan (BLOCKED — incomplete coverage)"),status2==="all_passed")status2="incomplete";message=`BLOCKED: Secretscan incomplete coverage in prior scan. ${message}`}else if(hasNewFindings&&hasIncompleteCoverage){if(missingGates.push("secretscan (BLOCKED — secrets detected; incomplete coverage)"),status2==="all_passed")status2="incomplete";message=`BLOCKED: Secretscan found secrets and incomplete coverage in prior scan (${newFindingsBasis} new on changed lines). ${message}`}else if(hasNewFindings){if(missingGates.push("secretscan (BLOCKED — secrets detected)"),status2==="all_passed")status2="incomplete";message=`BLOCKED: Secretscan found secrets in prior scan (${newFindingsBasis} new on changed lines${findingsCount>newFindingsBasis?`, ${findingsCount} total`:""}). ${message}`}else if(hasZeroCoverage){if(missingGates.push("secretscan (BLOCKED — zero coverage)"),status2==="all_passed")status2="incomplete";message=`BLOCKED: Secretscan scanned zero files in prior scan. ${message}`}else{if(missingGates.push("secretscan (BLOCKED — zero coverage)"),status2==="all_passed")status2="incomplete";message=`BLOCKED: Secretscan verdict failed without new findings or coverage gaps (possible truncation or tampering). ${message}`}else if(lastSecretscan.verdict==="pass"||lastSecretscan.verdict==="approved"||lastSecretscan.verdict==="info"){if(secretscanVerdict="pass",vacuousCoverage)message+=` Advisory: Secretscan coverage was vacuous (${lastSecretscan.policy_skipped_files} of ${lastSecretscan.requested_files} requested file(s) skipped by scan policy).`;else if(findingsCount>0)message+=` Advisory: ${findingsCount} pre-existing secret finding(s) remain visible (non-gating; secretscan green = zero new secrets on changed lines).`}}}else message+=" Advisory: No secretscan evidence found for this task. Consider running secretscan."}else if(evidenceResult.status==="invalid_schema")secretscanVerdict="fail",missingGates.push("secretscan (BLOCKED — invalid evidence)"),status2="incomplete",message=`BLOCKED: Secretscan evidence is invalid and cannot prove complete coverage. ${message}`}catch{}let todoScan=evidenceData.todo_scan,todoVerdict=evaluateTodoGate(todoScan,todoGateConfig);if(todoVerdict.status==="exceeded")if(todoVerdict.blocked){if(missingGates.push(`todo_gate (BLOCKED — ${todoVerdict.count} high-priority TODOs exceed max ${todoVerdict.max})`),status2==="all_passed")status2="incomplete";message=`BLOCKED: TODO gate threshold exceeded. ${todoVerdict.message} ${message}`}else message+=` Advisory: todo_gate threshold exceeded — ${todoVerdict.count} high-priority TODOs (FIXME/HACK/XXX) exceed max_high_priority=${todoVerdict.max}.`;let workflowMeta=evidenceData.workflow&&typeof evidenceData.workflow==="object"&&typeof evidenceData.workflow.state==="string"?{state:evidenceData.workflow.state,generation:typeof evidenceData.workflow.generation==="number"?evidenceData.workflow.generation:0}:null,currentPlanIdentity=resolveCurrentPlanIdentitySync(dirResult.directory),evidencePlanIdentityHash=evidenceData?.planIdentityHash,priorCampaignEvidence;if(currentPlanIdentity!=null&&evidencePlanIdentityHash!==void 0&&evidencePlanIdentityHash!==currentPlanIdentity.planIdentityHash)priorCampaignEvidence="Evidence for this task predates the current plan campaign (plan-identity stamp names a different plan). Its gates may not satisfy the current campaign receipts (status above is unchanged and advisory only); run repair_gate_evidence for this task to rebuild current-campaign evidence.",message+=` ${priorCampaignEvidence}`;let workflowAttributionHint;if(status2==="incomplete"&&workflowMeta?.state==="coder_delegated"&&!gatesMap.pre_check)workflowAttributionHint="Task is settled at coder_delegated but Stage A (pre_check_batch) was never attributed — "+`reviewer/test_engineer dispatches will be denied with TASK_WORKFLOW_STAGE_A_REQUIRED. Run pre_check_batch on the task's changed files; if it passes without advancing this task, run /swarm recover ${taskIdInput}.`,message+=` ${workflowAttributionHint}`;let result={taskId:taskIdInput,status:status2,required_gates:requiredGates,passed_gates:passedGates,missing_gates:missingGates,gates:gatesMap,message,todo_scan:todoScan??null,secretscan_verdict:secretscanVerdict,workflow:workflowMeta,...workflowAttributionHint?{workflow_attribution_hint:workflowAttributionHint}:{},...priorCampaignEvidence?{prior_campaign_evidence:priorCampaignEvidence}:{}};return JSON.stringify(result,null,2)}});init_checkpoint();init_co_change_analyzer();init_zod();init_loader();init_pr_workflow_gate();init_create_tool();var CompletePrWorkflowArgsSchema=exports_external.object({mode:exports_external.enum(["PR_REVIEW","PR_FEEDBACK"]),pr_head_sha:exports_external.string().trim().min(1).max(80),report_verdict:exports_external.enum(["APPROVE","REQUEST_CHANGES","INCOMPLETE"]).optional()}).strict().superRefine((value,ctx)=>{if(value.mode==="PR_REVIEW"&&value.report_verdict===void 0)ctx.addIssue({code:"custom",path:["report_verdict"],message:"is required for PR_REVIEW completion (issue #2383 terminal report)"})});async function executeCompletePrWorkflow(args2,directory,context={}){let parsed=CompletePrWorkflowArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid PR workflow completion: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`});if(!context.sessionID?.trim())return JSON.stringify({success:!1,message:"PR workflow completion requires an active sessionID"});let staleDisclosure={},laneLiveness;try{let config3=loadPluginConfig(directory),hooks2=config3.hooks;laneLiveness={laneLivenessWatchdog:config3.lane_liveness_watchdog,backgroundPendingTimeoutMs:hooks2?.background_pending_timeout_minutes!==void 0?hooks2.background_pending_timeout_minutes*60000:void 0}}catch{}try{let settlement=await _internals288.settlePresumedStalePrWorkflowLanes(directory,context.sessionID,laneLiveness);if(settlement.presumedStaleLaneIds.length>0)staleDisclosure={presumed_stale_lanes:settlement.presumedStaleLaneIds,presumed_stale_disclosure:settlement.disclosure};if(settlement.probedAliveLaneIds?.length)staleDisclosure.probe_retained_lanes=settlement.probedAliveLaneIds;if(settlement.probeDegradedReason)staleDisclosure.probe_status=settlement.probeDegradedReason;if(settlement.horizonConflictNote)staleDisclosure.horizon_conflict=settlement.horizonConflictNote}catch{}let amendmentDisclosure={};try{let gateState=await _internals288.readPrWorkflowGateState(directory,context.sessionID);if(gateState?.prFeedbackInventoryAmendments?.length)amendmentDisclosure={inventory_amendments:gateState.prFeedbackInventoryAmendments}}catch{}try{let terminalReport;if(parsed.data.mode==="PR_REVIEW"){let coverage=null;try{coverage=await _internals288.readPrReviewTerminalCoverageForReport(directory,context.sessionID)}catch{}if(coverage){let findingPolicy;try{findingPolicy=await _internals288.readPrReviewFinalFindingPolicyForReport(directory,context.sessionID)}catch{}terminalReport={kind:coverage.kind,covered_dimensions:coverage.coveredDimensions,unresolved_dimensions:coverage.unresolvedDimensions,live_dimensions:coverage.liveDimensions,allowed_verdicts:findingPolicy?.permittedVerdicts??coverage.allowedVerdicts,...findingPolicy?{finding_policy_version:findingPolicy.policyVersion,blocking_finding_ids:findingPolicy.blockingFindingIds}:{},report_verdict:parsed.data.report_verdict,...((summary)=>summary?{findings_summary:summary}:{})(await findingsSummaryForReportSafe(directory,context.sessionID)),coverage_degradations:await coverageDegradationsForReportSafe(directory,context.sessionID),verdict_settlement:await verdictSettlementSummaryForReportSafe(directory,context.sessionID)}}}let status2=await _internals288.completePrWorkflow(directory,context.sessionID,parsed.data.mode,parsed.data.pr_head_sha,parsed.data.mode==="PR_REVIEW"?{reportVerdict:parsed.data.report_verdict,...laneLiveness?{laneLiveness}:{}}:laneLiveness?{laneLiveness}:void 0),checkoutRestoreRequired=!1,checkoutRestoreReceipts=[];if(status2==="completed"){if(parsed.data.mode==="PR_REVIEW"&&parsed.data.report_verdict==="INCOMPLETE"&&terminalReport)terminalReport.allowed_verdicts=["INCOMPLETE"];try{checkoutRestoreReceipts=await _internals288.listPendingPrWorkflowCheckoutRestores(directory,context.sessionID),checkoutRestoreRequired=checkoutRestoreReceipts.length>0}catch{checkoutRestoreRequired=!0}}return JSON.stringify({success:!0,mode:parsed.data.mode,pr_head_sha:parsed.data.pr_head_sha,status:status2,ready_to_publish:status2==="ready-to-publish",verified_no_change:status2==="verified-no-change",gate_cleared:status2==="completed"||status2==="verified-no-change",checkout_restore_required:checkoutRestoreRequired,checkout_restore_receipts:checkoutRestoreReceipts,...terminalReport?{terminal_report:terminalReport}:{},...staleDisclosure,...amendmentDisclosure})}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:String(error93),...staleDisclosure,...amendmentDisclosure})}}var complete_pr_workflow=createSwarmTool({description:"Validate terminal PR workflow coverage. After the ordered PR_FEEDBACK gates permit one standalone commit, the first call requires a clean tree and a non-merge direct child of intake HEAD, then binds its structured upstream target; the second clears only after both the local tracking ref and an actual-remote query point to that exact commit. A cleared result reports checkout_restore_required when preserved pre-workflow changes must be restored.",args:{mode:CompletePrWorkflowArgsSchema.shape.mode,pr_head_sha:CompletePrWorkflowArgsSchema.shape.pr_head_sha,report_verdict:CompletePrWorkflowArgsSchema.shape.report_verdict},execute:executeCompletePrWorkflow}),_internals288={completePrWorkflow,listPendingPrWorkflowCheckoutRestores,readPrWorkflowGateState,readPrReviewTerminalCoverageForReport,readPrReviewFinalFindingPolicyForReport,settlePresumedStalePrWorkflowLanes,verdictSettlementSummaryForReportSafe};async function verdictSettlementSummaryForReport(directory,sessionID){let{readPrReviewVerdictSettlementReceiptItems:readPrReviewVerdictSettlementReceiptItems2}=await Promise.resolve().then(() => (init_pr_workflow_gate(),exports_pr_workflow_gate));return readPrReviewVerdictSettlementReceiptItems2(directory,sessionID)}async function verdictSettlementSummaryForReportSafe(directory,sessionID){try{return await verdictSettlementSummaryForReport(directory,sessionID)}catch{return}}async function findingsSummaryForReport(directory,sessionID){let{readAuthoritativeFindingPolicy:readAuthoritativeFindingPolicy2}=await Promise.resolve().then(() => (init_pr_workflow_gate(),exports_pr_workflow_gate)),state2=await readPrWorkflowGateState(directory,sessionID);if(!state2)throw Error("BLOCKED: no active PR workflow gate state");let{policyFindings}=await readAuthoritativeFindingPolicy2(directory,state2),severityAxes=new Set(["CRITICAL","HIGH","MEDIUM","LOW","INFO","NONE"]),bySeverity={};for(let finding of policyFindings){let axis=severityAxes.has(finding.severity)?finding.severity:"OTHER";bySeverity[axis]=(bySeverity[axis]??0)+1}return{total:policyFindings.length,by_severity:bySeverity}}async function findingsSummaryForReportSafe(directory,sessionID){try{return await findingsSummaryForReport(directory,sessionID)}catch{return}}var MAX_TERMINAL_COVERAGE_DEGRADATIONS=10,MAX_TERMINAL_DEGRADATION_REASON_CHARS=200,MAX_TERMINAL_DEGRADATION_ID_CHARS=200;function boundTerminalText(value,max){return value.slice(0,max)}function redactTerminalCleanLiteral(value){return value.includes("CLEAN")?value.split("CLEAN").join("clean-attestation"):value}async function coverageDegradationsForReport(directory,sessionID){let state2=await readPrWorkflowGateState(directory,sessionID);if(!state2)return[];let{readPrReviewTriggerReceiptForGate:readPrReviewTriggerReceiptForGate2}=await Promise.resolve().then(() => (init_pr_review_trigger_receipt_reader(),exports_pr_review_trigger_receipt_reader)),read=readPrReviewTriggerReceiptForGate2(directory,state2.prReviewTriggerEvalPath??null);if("noReceipt"in read)return[];return read.receipt.coverageDegradations.slice(0,MAX_TERMINAL_COVERAGE_DEGRADATIONS).map((degradation)=>({trigger_id:degradation.trigger_id,source_batch_id:boundTerminalText(redactTerminalCleanLiteral(degradation.source_batch_id),MAX_TERMINAL_DEGRADATION_ID_CHARS),source_lane_id:boundTerminalText(redactTerminalCleanLiteral(degradation.source_lane_id),MAX_TERMINAL_DEGRADATION_ID_CHARS),reason:boundTerminalText(redactTerminalCleanLiteral(degradation.reason),MAX_TERMINAL_DEGRADATION_REASON_CHARS)}))}async function coverageDegradationsForReportSafe(directory,sessionID){try{return await coverageDegradationsForReport(directory,sessionID)}catch{return[]}}init_zod();init_utils2();init_state();init_swarm_artifact_cache();init_create_tool();init_resolve_working_directory();import*as fs196 from"node:fs";import*as path333 from"node:path";function extractMatches(regex,text){return Array.from(text.matchAll(regex))}function parseIdentifiers(description){let identifiers=new Set,backtickRegex=/`([^`]+)`/g;for(let match of extractMatches(backtickRegex,description))identifiers.add(match[1]);let camelCaseRegex=/\b([a-z][a-zA-Z0-9]{2,})\b/g;for(let match of extractMatches(camelCaseRegex,description)){let word=match[1];if(word==="the"||word==="and"||word==="for"||word==="have"||word==="this"||word==="with"||word==="from"||word==="they"||word==="been"||word==="will"||word==="your"||word==="also")continue;identifiers.add(word)}let pascalCaseRegex=/\b([A-Z][a-zA-Z0-9]{2,})\b/g;for(let match of extractMatches(pascalCaseRegex,description))identifiers.add(match[1]);let configKeyRegex=/\b([a-z][a-zA-Z0-9]*(?:\.[a-z][a-zA-Z0-9]*)+)\b/g;for(let match of extractMatches(configKeyRegex,description))identifiers.add(match[1]);let quotedPathRegex=/['"](\.{0,3}(?:src|lib|test)[/\\][^'"]+)['"]/g;for(let match of extractMatches(quotedPathRegex,description))identifiers.add(match[1]);return Array.from(identifiers)}function parseFilePaths(description,filesTouched){if(filesTouched&&Array.isArray(filesTouched)&&filesTouched.length>0)return filesTouched;let filePaths=[],srcPathRegex=/\b(?:src|lib|test|app|packages?)[/\\][a-zA-Z0-9_./-]+\.(?:ts|tsx|js|jsx|mjs|cjs)\b/g;for(let match of extractMatches(srcPathRegex,description))filePaths.push(match[0]);let genericPathRegex=/\b[a-zA-Z0-9_./-]+[/\\][a-zA-Z0-9_./-]+\.[a-zA-Z0-9]+(?=\s|$|[.,;])/g;for(let match of extractMatches(genericPathRegex,description)){let pathStr=match[0];if(pathStr.includes("src/")||pathStr.includes("src\\")||pathStr.includes("lib/")||pathStr.includes("lib\\")||pathStr.includes("test/")||pathStr.includes("test\\"))filePaths.push(pathStr)}return filePaths}function buildVerifySummary(tasksChecked,tasksSkipped,tasksBlocked){if(tasksBlocked>0)return`Blocked: ${tasksBlocked} task(s) with missing identifiers`;let verified=tasksChecked-tasksSkipped;if(tasksSkipped===tasksChecked)return`All ${tasksChecked} completed task(s) skipped — research/inventory tasks`;if(tasksSkipped>0)return`${verified} task(s) verified, ${tasksSkipped} skipped (research tasks)`;return`All ${tasksChecked} completed tasks verified successfully`}async function executeCompletionVerify(args2,directory){let phase=Number(args2.phase);if(Number.isNaN(phase)||phase<1||!Number.isFinite(phase))return JSON.stringify({success:!1,phase,status:"blocked",reason:"Invalid phase number",tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]},null,2);if(hasActiveTurboMode(args2.sessionID))return JSON.stringify({success:!0,phase,status:"passed",reason:"Turbo Mode active — completion verification bypassed",tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]},null,2);let plan;try{let planPath=validateSwarmPath(directory,"plan.json"),planRaw=fs196.readFileSync(planPath,"utf-8");plan=JSON.parse(planRaw)}catch{return JSON.stringify({success:!0,phase,status:"passed",reason:"Cannot verify without plan.json",tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]},null,2)}let targetPhase=plan.phases.find((p)=>p.id===phase);if(!targetPhase){let result2={success:!1,phase,status:"blocked",reason:`Phase ${phase} not found in plan.json`,tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]};return JSON.stringify(result2,null,2)}let tasksChecked=0,tasksSkipped=0,tasksBlocked=0,blockedTasks=[];for(let task2 of targetPhase.tasks){if(task2.status!=="completed")continue;tasksChecked++;let fileTargets=parseFilePaths(task2.description,task2.files_touched),identifiers=parseIdentifiers(task2.description);if(fileTargets.length===0){tasksSkipped++;continue}if(identifiers.length===0){blockedTasks.push({task_id:task2.id,identifier:"",file_path:"",reason:"No identifiers — cannot verify completion without identifiers"}),tasksBlocked++;continue}let foundIdentifiers=new Set,hasFileReadFailure=!1;for(let filePath of fileTargets){let normalizedPath=filePath.replace(/\\/g,"/"),resolvedPath=path333.resolve(directory,normalizedPath),projectRoot=path333.resolve(directory),relative88=path333.relative(projectRoot,resolvedPath);if(!(relative88===""||!relative88.startsWith("..")&&!path333.isAbsolute(relative88))){blockedTasks.push({task_id:task2.id,identifier:"",file_path:filePath,reason:`File path '${filePath}' escapes the project directory — cannot verify completion`}),hasFileReadFailure=!0;continue}let fileContent;try{fileContent=fs196.readFileSync(resolvedPath,"utf-8")}catch{blockedTasks.push({task_id:task2.id,identifier:"",file_path:filePath,reason:`File '${filePath}' not found — cannot verify completion`}),hasFileReadFailure=!0;continue}for(let identifier of identifiers)if(fileContent.includes(identifier))foundIdentifiers.add(identifier)}let foundCount=foundIdentifiers.size;if(hasFileReadFailure||foundCount===0){if(!hasFileReadFailure)blockedTasks.push({task_id:task2.id,identifier:"",file_path:"",reason:"No identifiers found in target files"});tasksBlocked++}}let now2=new Date().toISOString(),result={success:tasksBlocked===0,phase,status:tasksBlocked===0?"passed":"blocked",reason:tasksBlocked>0?`COMPLETION_INCOMPLETE: ${tasksBlocked} task(s) blocked — missing identifiers or target files`:void 0,tasksChecked,tasksSkipped,tasksBlocked,blockedTasks};if(args2.writeEvidence!==!1)try{let evidenceDir=path333.join(directory,".swarm","evidence",`${phase}`),evidencePath2=path333.join(evidenceDir,"completion-verify.json");fs196.mkdirSync(evidenceDir,{recursive:!0});let evidenceBundle={schema_version:"1.0.0",task_id:"completion-verify",created_at:now2,entries:[{task_id:"completion-verify",type:"completion_verify",timestamp:now2,agent:"completion_verify",verdict:tasksBlocked===0?"pass":"fail",summary:buildVerifySummary(tasksChecked,tasksSkipped,tasksBlocked),phase,tasks_checked:tasksChecked,tasks_skipped:tasksSkipped,tasks_blocked:tasksBlocked,blocked_tasks:blockedTasks}]};fs196.writeFileSync(evidencePath2,JSON.stringify(evidenceBundle,null,2),"utf-8"),invalidateCachedArtifact(evidencePath2)}catch{}return JSON.stringify(result,null,2)}var completion_verify=createSwarmTool({description:"Deterministic pre-check verifying that plan task identifiers exist in their target source files before phase completion. Blocks if obviously incomplete.",args:{phase:exports_external.number().describe("The phase number to check"),sessionID:exports_external.string().optional().describe("Session ID for tracking state (auto-provided by plugin context)"),working_directory:exports_external.string().optional().describe("Explicit project root directory. When provided, .swarm/ is resolved relative to this path instead of the plugin context directory. Use this when CWD differs from the actual project root.")},execute:async(args2,directory)=>{let parsedArgs;try{if(args2&&typeof args2==="object"){let obj=args2;parsedArgs={phase:typeof obj.phase==="number"?obj.phase:typeof obj.phase==="string"?Number(obj.phase):0,sessionID:typeof obj.sessionID==="string"?obj.sessionID:void 0,working_directory:typeof obj.working_directory==="string"?obj.working_directory:void 0}}else parsedArgs={phase:0}}catch{return JSON.stringify({success:!1,phase:0,status:"blocked",reason:"Invalid arguments",tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]},null,2)}let dirResult=resolveWorkingDirectory(parsedArgs.working_directory,directory);if(!dirResult.success)return JSON.stringify({success:!1,phase:parsedArgs.phase,status:"blocked",reason:dirResult.message,tasksChecked:0,tasksSkipped:0,tasksBlocked:0,blockedTasks:[]},null,2);return executeCompletionVerify(parsedArgs,dirResult.directory)}});init_zod();init_metrics();init_bun_compat();init_git_executable();init_create_tool();init_path_security();import{Buffer as Buffer4}from"node:buffer";import*as fs197 from"node:fs";import*as path334 from"node:path";var MAX_FILE_SIZE_BYTES5=262144,DEFAULT_DAYS=90,DEFAULT_TOP_N2=20,DEFAULT_EXTENSIONS="ts,tsx,js,jsx,py,rs,ps1",SHELL_METACHAR_REGEX=/[;&|%$`\\]/;function validateDays(days){if(typeof days>"u")return{valid:!0,value:DEFAULT_DAYS,error:null};if(typeof days!=="number"||!Number.isInteger(days))return{valid:!1,value:0,error:"days must be an integer"};if(days<1||days>365)return{valid:!1,value:0,error:"days must be between 1 and 365"};return{valid:!0,value:days,error:null}}function validateTopN(topN){if(typeof topN>"u")return{valid:!0,value:DEFAULT_TOP_N2,error:null};if(typeof topN!=="number"||!Number.isInteger(topN))return{valid:!1,value:0,error:"top_n must be an integer"};if(topN<1||topN>100)return{valid:!1,value:0,error:"top_n must be between 1 and 100"};return{valid:!0,value:topN,error:null}}function validateExtensions(extensions){if(typeof extensions>"u")return{valid:!0,value:DEFAULT_EXTENSIONS,error:null};if(typeof extensions!=="string")return{valid:!1,value:"",error:"extensions must be a string"};if(containsControlChars(extensions))return{valid:!1,value:"",error:"extensions contains control characters"};if(SHELL_METACHAR_REGEX.test(extensions))return{valid:!1,value:"",error:"extensions contains shell metacharacters (;|&%$`\\)"};if(!/^[a-zA-Z0-9,.]+$/.test(extensions))return{valid:!1,value:"",error:"extensions contains invalid characters (only alphanumeric, commas, dots allowed)"};return{valid:!0,value:extensions,error:null}}var _internals289={bunSpawn,resolveGitExecutable},GIT_CHURN_TIMEOUT_MS=1e4,GIT_CHURN_MAX_BUFFER_BYTES=5242880;async function getGitChurn(days,directory,abortSignal){let churnMap=new Map,proc=_internals289.bunSpawn([_internals289.resolveGitExecutable(),"log",`--since=${days} days ago`,"--name-only","--pretty=format:"],{stdout:"pipe",stderr:"pipe",stdin:"ignore",cwd:directory,timeout:GIT_CHURN_TIMEOUT_MS,maxBuffer:GIT_CHURN_MAX_BUFFER_BYTES,killProcessTree:!0,env:{...process.env,GIT_TERMINAL_PROMPT:"0"}}),churnTimeout,churnAbortCleanup,racers=[Promise.all([proc.stdout.text(),proc.exited]).then((churnOutput)=>churnOutput),new Promise((resolve132)=>{churnTimeout=setTimeout(()=>resolve132([null,"timeout"]),GIT_CHURN_TIMEOUT_MS)})];if(abortSignal!==void 0)racers.push(new Promise((resolve132)=>{let settle2=()=>resolve132([null,"aborted"]);if(abortSignal.aborted){settle2();return}let onAbort=()=>settle2();abortSignal.addEventListener("abort",onAbort,{once:!0}),churnAbortCleanup=()=>{abortSignal.removeEventListener("abort",onAbort)}}));try{let[stdout,outcome]=await Promise.race(racers);if(typeof churnTimeout<"u")clearTimeout(churnTimeout);if(outcome==="timeout")throw Error(`git churn analysis failed: git log did not finish within ${GIT_CHURN_TIMEOUT_MS} ms (bounded; child tree killed)`);if(outcome==="aborted")throw Error(`git churn analysis failed: aborted by host cancellation (ctx.abort fired before the ${GIT_CHURN_TIMEOUT_MS} ms deadline; child tree killed)`);if(proc.spawnError)throw Error(`git churn analysis failed: ${proc.spawnError.message}`);if(proc.signalCode)throw Error(`git churn analysis failed: git log was killed by ${proc.signalCode} after exceeding the ${GIT_CHURN_TIMEOUT_MS} ms / ${GIT_CHURN_MAX_BUFFER_BYTES}-byte bound`);if(Buffer4.byteLength(stdout)>=GIT_CHURN_MAX_BUFFER_BYTES)throw Error(`git churn analysis failed: git log output reached the ${GIT_CHURN_MAX_BUFFER_BYTES}-byte buffer limit`);let lines=stdout.split(/\r?\n/);for(let line of lines){let normalizedPath=line.replace(/\\/g,"/");if(!normalizedPath||normalizedPath.trim()==="")continue;if(normalizedPath.includes("node_modules")||normalizedPath.includes("/.git/")||normalizedPath.includes("/dist/")||normalizedPath.includes("/build/")||normalizedPath.includes("__tests__"))continue;if(normalizedPath.includes(".test.")||normalizedPath.includes(".spec."))continue;churnMap.set(normalizedPath,(churnMap.get(normalizedPath)||0)+1)}}finally{if(typeof churnTimeout<"u")clearTimeout(churnTimeout);churnAbortCleanup?.();try{proc.kill()}catch{}}return churnMap}function getComplexityForFile2(filePath){try{if(fs197.statSync(filePath).size>MAX_FILE_SIZE_BYTES5)return null;let content=fs197.readFileSync(filePath,"utf-8");return estimateCyclomaticComplexity(content)}catch{return null}}async function analyzeHotspots(days,topN,extensions,directory,abortSignal){let churnMap=await getGitChurn(days,directory,abortSignal),extSet=new Set(extensions.map((e)=>e.startsWith(".")?e:`.${e}`)),filteredChurn=new Map;for(let[file3,count4]of churnMap){let ext=path334.extname(file3).toLowerCase();if(extSet.has(ext))filteredChurn.set(file3,count4)}let hotspots=[],cwd=directory,analyzedFiles=0;for(let[file3,churnCount]of filteredChurn){let fullPath=file3;if(!fs197.existsSync(fullPath))fullPath=path334.join(cwd,file3);let complexity=getComplexityForFile2(fullPath);if(complexity!==null){analyzedFiles++;let riskScore=Math.round(churnCount*Math.log2(Math.max(complexity,1))*10)/10,recommendation;if(riskScore>=50)recommendation="full_gates";else if(riskScore>=30)recommendation="security_review";else if(riskScore>=15)recommendation="enhanced_review";else recommendation="standard";hotspots.push({file:file3,churnCount,complexity,riskScore,recommendation})}}hotspots.sort((a,b)=>b.riskScore-a.riskScore);let topHotspots=hotspots.slice(0,topN),summary={fullGates:topHotspots.filter((h)=>h.recommendation==="full_gates").length,securityReview:topHotspots.filter((h)=>h.recommendation==="security_review").length,enhancedReview:topHotspots.filter((h)=>h.recommendation==="enhanced_review").length,standard:topHotspots.filter((h)=>h.recommendation==="standard").length};return{analyzedFiles,period:`${days} days`,hotspots:topHotspots,summary}}var complexity_hotspots=createSwarmTool({description:"Identify high-risk code hotspots by combining git churn frequency with cyclomatic complexity estimates. Returns files with their churn count, complexity score, risk score, and recommended review level.",args:{days:exports_external.number().optional().describe("Number of days of git history to analyze (default: 90, valid range: 1-365)"),top_n:exports_external.number().optional().describe("Number of top hotspots to return (default: 20, valid range: 1-100)"),extensions:exports_external.string().optional().describe('Comma-separated extensions to include (default: "ts,tsx,js,jsx,py,rs,ps1")')},async execute(args2,directory,ctx){if(!directory||typeof directory!=="string"||directory.trim()==="")return JSON.stringify({error:"project directory is required but was not provided",analyzedFiles:0,period:"0 days",hotspots:[],summary:{fullGates:0,securityReview:0,enhancedReview:0,standard:0}},null,2);let daysInput,topNInput,extensionsInput;try{if(args2&&typeof args2==="object"){let obj=args2;daysInput=typeof obj.days==="number"?obj.days:void 0,topNInput=typeof obj.top_n==="number"?obj.top_n:void 0,extensionsInput=typeof obj.extensions==="string"?obj.extensions:void 0}}catch{}let daysValidation=validateDays(daysInput);if(!daysValidation.valid){let errorResult={error:`invalid days: ${daysValidation.error}`,analyzedFiles:0,period:"0 days",hotspots:[],summary:{fullGates:0,securityReview:0,enhancedReview:0,standard:0}};return JSON.stringify(errorResult,null,2)}let topNValidation=validateTopN(topNInput);if(!topNValidation.valid){let errorResult={error:`invalid top_n: ${topNValidation.error}`,analyzedFiles:0,period:"0 days",hotspots:[],summary:{fullGates:0,securityReview:0,enhancedReview:0,standard:0}};return JSON.stringify(errorResult,null,2)}let extensionsValidation=validateExtensions(extensionsInput);if(!extensionsValidation.valid){let errorResult={error:`invalid extensions: ${extensionsValidation.error}`,analyzedFiles:0,period:"0 days",hotspots:[],summary:{fullGates:0,securityReview:0,enhancedReview:0,standard:0}};return JSON.stringify(errorResult,null,2)}let days=daysValidation.value,topN=topNValidation.value,extensions=extensionsValidation.value.split(",").map((e)=>e.trim());try{let result=await analyzeHotspots(days,topN,extensions,directory,ctx?.abort);return JSON.stringify(result,null,2)}catch(e){let errorResult={error:e instanceof Error?`analysis failed: ${e.message}`:"analysis failed: unknown error",analyzedFiles:0,period:`${days} days`,hotspots:[],summary:{fullGates:0,securityReview:0,enhancedReview:0,standard:0}};return JSON.stringify(errorResult,null,2)}}});init_zod();init_config2();init_schema();init_miner();init_miner();init_store4();async function mineAndStoreConsensusV1(options){let priorFingerprints=options.deps.priorFingerprints??await listConsensusProposalFingerprints(options.directory),result=await mineConsensus(options.directory,options.request,{...options.deps,priorFingerprints}),report=await writeConsensusReport(options.directory,result.report);return{...result,report}}init_store4();init_memory();init_recommendation_ledger();init_state();init_logger();init_create_tool();var MAX_FILTER_ENTRIES=200,FilterListSchema=exports_external.array(exports_external.string().min(1).max(512)).max(MAX_FILTER_ENTRIES),MAX_INLINE_ATTRIBUTES=25;function countSummaries(attributes,inlineLimit){let total=0,shown=0;for(let[index,attribute]of attributes.entries()){if(attribute.llmSummary===void 0)continue;if(total+=1,index<inlineLimit)shown+=1}return{total,hidden:total-shown}}function buildMinerRecommendationCandidates(report,sessionId){return report.proposals.map((proposal)=>({kind:"miner",target:proposal.target,statement:proposal.intent,scopeKeys:[],provenance:{mechanism:"consensus_mine",sourceEvidenceRefs:proposal.evidenceRefs,sourceRunIds:proposal.provenance.sourceRunIds,sourceModelIds:proposal.provenance.sourceModelIds,sourceTaskIds:proposal.provenance.sourceTaskIds},origin:{agentRole:"consensus_mine",...sessionId?{sessionId}:{},producedAt:report.generatedAt}}))}var MIRRORED_PROPOSAL_KIND="todo";async function mirrorProposalsToMemory(options){if(options.memoryConfig?.enabled!==!0)return{enabled:!1,attempted:0,proposed:0,rejected:0,failed:0};let proposals=options.report.proposals;if(proposals.length===0)return{enabled:!0,attempted:0,proposed:0,rejected:0,failed:0};let gateway;try{gateway=_internals290.createMemoryGateway({directory:options.directory,...options.sessionId?{sessionID:options.sessionId,runId:options.sessionId}:{},agentRole:"consensus_mine"},{config:options.memoryConfig})}catch(err){let message=err instanceof Error?err.message:String(err);return warn(`[consensus_mine] memory mirror unavailable (fail-open): ${message}`),{enabled:!0,attempted:proposals.length,proposed:0,rejected:0,failed:proposals.length,error:message}}let proposed=0,rejected2=0,failed=0,error93;try{for(let proposal of proposals)try{if((await gateway.propose({operation:"add",kind:MIRRORED_PROPOSAL_KIND,text:proposal.intent,rationale:`consensus_mine proposal from report ${options.report.reportId}, attribute ${proposal.sourceAttributeId} (target ${proposal.target}, confidence ${proposal.confidence})`,evidenceRefs:proposal.evidenceRefs})).status==="rejected")rejected2+=1;else proposed+=1}catch(err){failed+=1,error93??=err instanceof Error?err.message:String(err)}}finally{try{await gateway.dispose()}catch(err){warn(`[consensus_mine] memory gateway dispose failed: ${err instanceof Error?err.message:String(err)}`)}}if(error93!==void 0)warn(`[consensus_mine] memory mirror partially failed: ${error93}`);return{enabled:!0,attempted:proposals.length,proposed,rejected:rejected2,failed,...error93?{error:error93}:{}}}var _internals290={createMemoryGateway};var consensus_mine=createSwarmTool({description:"Mine cross-run consensus from existing .swarm evidence — evaluation runs, gate audits, gate "+"ground truth, task trajectories, PRM sessions, skill usage, knowledge outcomes, evidence "+"bundles, and curated failures (nine sources) — and persist an immutable report of "+`agreed-upon attributes plus proposals-only recommendations. It never activates a skill, writes a knowledge entry, admits a durable memory record, edits a project file, or mutates any evidence it reads. It is NOT otherwise write-minimal, so plan for these effects: it DELETES its own older reports past consensus.report_retention (default 50) on every run; it rewrites the shared recommendation dedup ledger whole, with FIFO eviction that can drop another producer's oldest entries; it leaves one never-removed lock sentinel per report id under .swarm/locks/; when memory.enabled is true it mirrors each proposal into a PENDING swarm-memory proposal (curator review still required); and when consensus.llm_summarization_enabled is true (the default) it issues up to ${MAX_LLM_SUMMARIES} session.create plus session.prompt calls. Under a knowledge or memory link the ledger and the memory store resolve to the shared cohort root, outside this project's .swarm/.`,args:{run_ids:FilterListSchema.optional().describe("Restrict mining to these run ids (raw or namespaced). Omit for all runs."),task_categories:FilterListSchema.optional().describe("Restrict to these evaluation task categories. Omit for all categories."),agent_roles:FilterListSchema.optional().describe("Restrict to these agent roles. Omit for all roles."),model_ids:FilterListSchema.optional().describe("Restrict to these model ids. Omit for all models."),min_support:exports_external.number().int().min(1).max(1e4).optional().describe("Distinct runs required to emit an attribute. Defaults to consensus.default_min_support."),min_successful_runs:exports_external.number().int().min(0).max(1e4).optional().describe("Successful runs required. Defaults to consensus.default_min_successful_runs."),max_evidence_items:exports_external.number().int().min(1).max(1e4).optional().describe("Cap on corpus observations read. Defaults to consensus.default_max_evidence_items.")},execute:async(args2,directory,ctx)=>{let input=args2??{},loaded=loadPluginConfigWithMeta(directory),config3=ConsensusConfigSchema.parse(loaded.config.consensus??{});if(!config3.enabled)return JSON.stringify({success:!1,disabled:!0,message:"Consensus mining is disabled (consensus.enabled = false). No report was written."},null,2);let request={...input.run_ids?{runIds:input.run_ids}:{},...input.task_categories?{taskCategories:input.task_categories}:{},...input.agent_roles?{agentRoles:input.agent_roles}:{},...input.model_ids?{modelIds:input.model_ids}:{},minSupport:input.min_support??config3.default_min_support,minSuccessfulRuns:input.min_successful_runs??config3.default_min_successful_runs,maxEvidenceItems:input.max_evidence_items??config3.default_max_evidence_items},client=swarmState.opencodeClient,dispatcher=config3.llm_summarization_enabled&&client?createEvaluationModelDispatcher(client):void 0,result=await mineAndStoreConsensusV1({directory,request,deps:{config:config3,...dispatcher?{dispatcher}:{},...ctx?.sessionID?{sessionId:ctx.sessionID}:{},agentRole:"consensus_mine"}}),report=result.report,ledger=await recordEmittedRecommendations(directory,buildMinerRecommendationCandidates(report,ctx?.sessionID),{producedAt:report.generatedAt});if(ledger.degraded)warn("[consensus_mine] recommendation ledger write degraded; proposals were not recorded for cross-producer dedup");let memoryMirror=await mirrorProposalsToMemory({directory,memoryConfig:loaded.config.memory,report,...ctx?.sessionID?{sessionId:ctx.sessionID}:{}}),pruned=await pruneConsensusReports(directory,config3.report_retention),pruningEnabled=config3.report_retention>0,summaries=countSummaries(report.attributes,MAX_INLINE_ATTRIBUTES);return JSON.stringify({success:!0,report_id:report.reportId,report_path:`.swarm/evolution/consensus/${report.reportId}.json`,generated_at:report.generatedAt,integrity_hash:report.integrityHash,config_hash:report.configHash,redaction_policy_version:report.redactionPolicyVersion,thresholds:{min_support:request.minSupport,min_successful_runs:request.minSuccessfulRuns,max_evidence_items:request.maxEvidenceItems,min_task_diversity:MIN_TASK_DIVERSITY_FOR_PROPOSAL,min_support_for_proposal:MIN_SUPPORT_FOR_PROPOSAL},input_run_count:report.inputIds.length,corpus:report.corpusHashes.map((entry)=>({source:entry.source,observations:entry.observations})),corpus_truncated:result.truncated,truncation:{corpus:report.truncation.corpus,observations_tallied:report.truncation.observations,input_ids_truncated:report.truncation.inputIds,total_input_ids:report.truncation.totalInputIds,attributes_dropped:report.truncation.attributesDropped},unreadable_sources:result.unreadableSources,attribute_count:report.attributes.length,investigation_note_count:result.investigationNoteCount,proposal_count:report.proposals.length,deduped_proposal_count:result.dedupedProposalCount,recommendation_ledger:{recorded:ledger.recorded,duplicate_recommendation_count:ledger.suppressed,evicted:ledger.evicted,degraded:ledger.degraded},memory_mirror:memoryMirror,summarized_count:summaries.total,summarized_but_not_shown:summaries.hidden,restatements_accepted_this_run:result.summarizedCount,...result.summarizationSkippedReason?{summarization_skipped_reason:result.summarizationSkippedReason}:{},attributes:report.attributes.slice(0,MAX_INLINE_ATTRIBUTES).map((attribute)=>({id:attribute.id,statement:attribute.statement,...attribute.llmSummary?{llm_summary:attribute.llmSummary}:{},support:attribute.support,success_support:attribute.successSupport,failure_support:attribute.failureSupport,task_diversity:attribute.taskDiversity,model_diversity:attribute.modelDiversity,confidence:attribute.confidence,proposed_target:attribute.proposedTarget,counterexample_count:attribute.counterexampleRefs.length})),attributes_truncated:report.attributes.length>MAX_INLINE_ATTRIBUTES,retention:pruningEnabled?{configured:config3.report_retention,pruning_enabled:!0,deleted:pruned.deleted.length,retained:pruned.retained.length,failed:pruned.failed.length,corrupt:pruned.corrupt.length}:{configured:config3.report_retention,pruning_enabled:!1,deleted:0,failed:0},guarantees:["proposals only — no skill activation, no knowledge write, no durable memory record, and no mutation of any evidence read",'model_diversity 0 means "not measurable from this corpus", never "measured as none"',`attributes below task diversity ${MIN_TASK_DIVERSITY_FOR_PROPOSAL} or below support ${MIN_SUPPORT_FOR_PROPOSAL} are investigation notes, never proposals`,"an attribute counting failing runs always carries counterexample refs (schema-enforced)","truncation is not biased toward successes, but it is still a cut: it balances per source, and drops whole sources once the budget is spent","statement is deterministic; llm_summary is an optional restatement excluded from integrity_hash","reproducible: identical corpus, request, config_hash, and prior proposals yield the same integrity_hash and report_id; model wording never moves it",'truncation is declared on the report; read failure_support 0 on a truncated report as "none survived the cut"']},null,2)}});init_config2();init_model_limits();init_state();init_create_tool();var _internals291={loadPluginConfig,fetchSessionMessages:async(sessionID,directory,limit=100)=>{if(!swarmState.opencodeClient?.session)return null;try{return(await swarmState.opencodeClient.session.messages({path:{id:sessionID},query:{directory,limit}})).data??null}catch{return null}}};function computeContextHeadroom(messages,warnThreshold=0.7,criticalThreshold=0.9,modelLimitsConfig={},liveContextLimit,modelIdentity,directory){let{modelID,providerID}=modelIdentity??extractModelInfo(messages),modelLimitResolution=resolveModelLimit(modelID,providerID,modelLimitsConfig,liveContextLimit,directory),modelLimit=modelLimitResolution.limit,usage=computeContextUsage(messages),usagePercent=usage.tokensUsed/modelLimit,thresholdCrossed="none";if(usagePercent>criticalThreshold)thresholdCrossed="critical";else if(usagePercent>warnThreshold)thresholdCrossed="warn";return{tokensUsed:usage.tokensUsed,usageSource:usage.source,modelLimit,modelLimitSource:modelLimitResolution.source,modelLimitResolution:modelLimitResolution.resolution,fallbackActive:modelLimitResolution.source==="provider_cap"||modelLimitResolution.source==="native"||modelLimitResolution.source==="fallback",usagePercent,thresholdCrossed,modelId:modelID??null,provider:providerID??null}}var context_status=createSwarmTool({allowWorkingDirectoryOverride:!0,description:"Report current context-window headroom for the active session. Returns tokens-used, usageSource (provider|estimated), model-limit with provenance (modelLimitSource: host|override|provider_cap|native|fallback; modelLimitResolution: user_provider_model|user_model|user_default|live_model_limit|static_provider_cap|static_native|static_default; fallbackActive: true when the denominator came from a static table or the flat 128k default — treat headroom as uncertain), usage-percent, threshold-state (none|warn|critical), model name, and provider. Pure read-only — no state mutation, no warning injection. Works whether context_budget.enabled is true or false.",args:{},async execute(_args,directory,ctx){let config3=_internals291.loadPluginConfig(directory),warnThreshold=config3.context_budget?.warn_threshold??0.7,criticalThreshold=config3.context_budget?.critical_threshold??0.9,modelLimitsConfig=config3.context_budget?.model_limits??{},messages=[];if(ctx?.sessionID){let sessionMessages=await _internals291.fetchSessionMessages(ctx.sessionID,directory);if(sessionMessages)messages=sessionMessages}let{modelID,providerID}=getLiveContextModelIdentity(ctx?.sessionID)??extractModelInfo(messages),headroom=computeContextHeadroom(messages,warnThreshold,criticalThreshold,modelLimitsConfig,getLiveContextWindow(ctx?.sessionID,{modelID,providerID}),{modelID,providerID},directory);return JSON.stringify(headroom,null,2)}});init_zod();init_loader();function pushCouncilAdvisory(session,synthesis){let dedupKey=`council:${synthesis.taskId}:${synthesis.roundNumber}`;if(synthesis.overallVerdict==="APPROVE"&&synthesis.advisoryFindings.length===0)return;if(session.pendingAdvisoryMessages??=[],session.pendingAdvisoryMessages.some((m)=>m.includes(dedupKey)))return;let blocking=synthesis.overallVerdict==="REJECT",header=`[${dedupKey}] (priority=HIGH, blocking=${blocking})`,body=synthesis.unifiedFeedbackMd;pushAdvisory(session,`${header}
|
|
7641
7641
|
${body}`,{dedupeKey:dedupKey})}init_zod();init_task_file();init_gate_evidence();init_project_boundary();init_council_review_identity();import{existsSync as existsSync172,mkdirSync as mkdirSync92,readFileSync as readFileSync148}from"node:fs";import{join as join266}from"node:path";var EVIDENCE_DIR2=".swarm/evidence",VALID_TASK_ID=/^\d+\.\d+(\.\d+)*$/,COUNCIL_GATE_NAME="council",COUNCIL_AGENT_ID="architect",EvidenceFileSchema=exports_external.record(exports_external.string(),exports_external.unknown()),_internals292={withTaskEvidenceLock},FORBIDDEN_KEYS=new Set(["__proto__","constructor","prototype"]);function safeAssignOwnProps(target,source){for(let key3 of Object.keys(source)){if(FORBIDDEN_KEYS.has(key3))continue;let value=source[key3];if(value!==null&&typeof value==="object"&&!Array.isArray(value)){let nested=Object.create(null);safeAssignOwnProps(nested,value),target[key3]=nested}else if(Array.isArray(value))target[key3]=value.map((item)=>{if(item!==null&&typeof item==="object"&&!Array.isArray(item)){let nested=Object.create(null);return safeAssignOwnProps(nested,item),nested}return item});else target[key3]=value}return target}async function writeCouncilEvidence(workingDir,synthesis,attemptId,expectedGeneration,identity){if(!VALID_TASK_ID.test(synthesis.taskId))throw Error(`writeCouncilEvidence: invalid taskId "${synthesis.taskId}" — must match N.M or N.M.P format`);let dir=join266(workingDir,EVIDENCE_DIR2);assertProjectRoot(workingDir),mkdirSync92(dir,{recursive:!0});let filePath=taskEvidencePath(workingDir,synthesis.taskId);await _internals292.withTaskEvidenceLock(workingDir,synthesis.taskId,COUNCIL_AGENT_ID,async()=>{assertTaskEvidenceWriteAllowed(workingDir,synthesis.taskId);let existingRoot=Object.create(null);if(existsSync172(filePath))try{let raw=readFileSync148(filePath,"utf-8");if(expectedGeneration!==void 0){let exactEvidence=parseTaskEvidence(raw,synthesis.taskId),workflow=getTaskWorkflowSnapshot(exactEvidence);if(!workflow.authoritative||workflow.generation!==expectedGeneration||workflow.state!=="pre_check_passed")throw Error(`TASK_COUNCIL_GENERATION_MISMATCH: expected pre_check_passed@${expectedGeneration}, found ${workflow.state}@${workflow.generation}`)}let parsed=EvidenceFileSchema.parse(JSON.parse(raw));safeAssignOwnProps(existingRoot,parsed)}catch(error93){if(expectedGeneration!==void 0)throw error93}else if(expectedGeneration!==void 0)throw Error(`TASK_COUNCIL_GENERATION_MISMATCH: no exact evidence exists for generation ${expectedGeneration}`);let existingGatesRaw=existingRoot.gates,mergedGates=Object.create(null);if(existingGatesRaw&&typeof existingGatesRaw==="object"&&!Array.isArray(existingGatesRaw))safeAssignOwnProps(mergedGates,existingGatesRaw);mergedGates[COUNCIL_GATE_NAME]={sessionId:synthesis.swarmId,timestamp:synthesis.timestamp,agent:COUNCIL_AGENT_ID,verdict:synthesis.overallVerdict,vetoedBy:synthesis.vetoedBy,roundNumber:synthesis.roundNumber,allCriteriaMet:synthesis.allCriteriaMet,quorumSize:synthesis.quorumSize,...identity?councilIdentityEvidenceFields(identity):{},...expectedGeneration!==void 0?{workflowGeneration:expectedGeneration}:{},...attemptId?{attemptId}:{}};let updated=Object.create(null);if(safeAssignOwnProps(updated,existingRoot),updated.gates=mergedGates,!updated.taskId)updated.taskId=synthesis.taskId;if(!Array.isArray(updated.required_gates))updated.required_gates=[];await atomicWriteFile(filePath,JSON.stringify(updated,null,2))})}function hasCouncilEvidenceAttempt(workingDir,taskId,attemptId,roundNumber){if(!VALID_TASK_ID.test(taskId))return!1;try{let council=EvidenceFileSchema.parse(JSON.parse(readFileSync148(taskEvidencePath(workingDir,taskId),"utf-8"))).gates?.[COUNCIL_GATE_NAME];return council?.attemptId===attemptId&&council.roundNumber===roundNumber}catch{return!1}}init_council_review_identity();init_lock();init_task_file();import{createHash as createHash109,randomUUID as randomUUID43}from"node:crypto";import{closeSync as closeSync41,existsSync as existsSync173,fsyncSync as fsyncSync11,mkdirSync as mkdirSync93,openSync as openSync41,readFileSync as readFileSync149,readSync as readSync29,statSync as statSync106,writeSync as writeSync7}from"node:fs";import{dirname as dirname124,join as join267}from"node:path";init_telemetry();function scopeIdentityPayload(scope){return{level:scope.kind,...scope.kind==="task"&&scope.taskId!==void 0?{taskId:scope.taskId}:{},...scope.kind==="phase"&&scope.phaseNumber!==void 0?{phase:scope.phaseNumber}:{},identityDigest:scope.identityDigest}}function observeCouncilAuditAppend(scope,sessionID,councilRoundId,record3){try{emit("council_attempt",{...sessionID!==void 0?{sessionId:sessionID}:{},councilRoundId,...scopeIdentityPayload(scope),stage:record3.event,attemptId:record3.attemptId,disposition:record3.disposition,authoritativeRound:record3.authoritativeRound,...record3.clientRound!==void 0?{clientRound:record3.clientRound}:{},verdictCount:record3.verdictCount,memberCount:record3.members.length,...record3.quorumSize!==void 0?{quorumSize:record3.quorumSize}:{},...record3.verdict!==void 0?{verdict:record3.verdict}:{},...record3.transition!==void 0?{transition:record3.transition}:{},...record3.gateEffect!==void 0?{gateEffect:record3.gateEffect}:{}});let next=record3.nextState;if(record3.event!=="received"&&(record3.transition==="advance"||record3.transition==="close")&&next!==void 0)emit("council_round_transition",{...sessionID!==void 0?{sessionId:sessionID}:{},councilRoundId,...scopeIdentityPayload(scope),attemptId:record3.attemptId,transition:record3.transition,gateEffect:record3.gateEffect,round:record3.authoritativeRound,nextRound:next.currentRound,roundStatus:next.status,maxRoundsExhausted:next.maxRoundsExhausted,...record3.verdict!==void 0?{verdict:record3.verdict}:{},...record3.quorumSize!==void 0?{quorumSize:record3.quorumSize}:{}})}catch{}}function emitUnscopedCouncilAttemptObservation(sessionID,level,disposition,fingerprint2,attemptId){try{emit("council_attempt_unscoped",{...sessionID!==void 0?{sessionId:sessionID}:{},level,disposition,fingerprint:fingerprint2,attemptId})}catch{}}init_council_review_identity();var VERSION=2,MAX_ROUND=10,MAX_AUDIT_TAIL=262144,STATE_AGENT="council-round-state",EXHAUSTION_EVENT_RELATIVE_PATH="council/events/max-rounds-exhaustion.jsonl";class CouncilRoundStateUncertainError extends Error{constructor(message){super(message);this.name="CouncilRoundStateUncertainError"}}function sha25613(value){return createHash109("sha256").update(value).digest("hex")}var UUID_PATTERN2=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,DIGEST_PATTERN2=/^[a-f0-9]{64}$/;function isUuid2(value){return typeof value==="string"&&UUID_PATTERN2.test(value)}function isDigest(value){return typeof value==="string"&&DIGEST_PATTERN2.test(value)}function isRound(value){return Number.isInteger(value)&&Number(value)>=1&&Number(value)<=MAX_ROUND}function isDisposition(value){return typeof value==="string"&&value.length>0&&value.length<=80}function isEvidenceRef(value){return typeof value==="string"&&value.length>0&&value.length<=240&&value.startsWith(".swarm/")&&!value.includes("..")}function scopeToken(scope){if(scope.kind==="task"){if(!/^\d+\.\d+(\.\d+)*$/.test(scope.taskId))throw Error("invalid task council scope");if(!isIdentityDigest(scope.identityDigest))throw Error("invalid task council scope identity");return`task-${sha25613(JSON.stringify({k:"task",taskId:scope.taskId,id:scope.identityDigest}))}`}if(scope.kind==="phase"){if(!Number.isInteger(scope.phaseNumber)||scope.phaseNumber<1||scope.phaseNumber>1000)throw Error("invalid phase council scope");if(!isIdentityDigest(scope.identityDigest))throw Error("invalid phase council scope identity");return`phase-${sha25613(JSON.stringify({k:"phase",phaseNumber:scope.phaseNumber,id:scope.identityDigest}))}`}if(!isIdentityDigest(scope.identityDigest))throw Error("invalid final council scope identity");return`final-${sha25613(JSON.stringify({k:"final",id:scope.identityDigest}))}`}function auditScope(scope){if(scopeToken(scope),scope.kind==="task")return{kind:"task",scopeHash:sha25613(scope.taskId),identityDigest:scope.identityDigest};if(scope.kind==="phase")return{kind:"phase",phaseNumber:scope.phaseNumber,identityDigest:scope.identityDigest};return{kind:"final",scopeHash:sha25613(scope.identityDigest),identityDigest:scope.identityDigest}}function sameAuditScope(left,right){if(left.kind!==right.kind)return!1;if(left.identityDigest!==right.identityDigest)return!1;if(left.kind==="phase"&&right.kind==="phase")return left.phaseNumber===right.phaseNumber;if(left.kind!=="phase"&&right.kind!=="phase")return left.scopeHash===right.scopeHash;return!1}function councilRoundStatePaths(directory,scope){let token=scopeToken(scope);return{state:join267(directory,".swarm","council","round-state",`${token}.json`),audit:join267(directory,".swarm","council","attempts",`${token}.jsonl`),lock:join267("council","round-state",`${token}.json`)}}function canonicalize3(value){if(Array.isArray(value))return value.map(canonicalize3);if(value&&typeof value==="object"){let result=Object.create(null);for(let key3 of Object.keys(value).sort()){if(key3==="working_directory"||key3==="roundNumber"||key3==="provenanceAgentName"||key3==="provenanceSessionId")continue;result[key3]=canonicalize3(value[key3])}return result}return value}function councilRequestDigest(request,round){return sha25613(JSON.stringify({round,request:canonicalize3(request)}))}function isSnapshot(value){if(!value||typeof value!=="object")return!1;let state2=value;return state2.version===VERSION&&isIdentityDigest(state2.identityDigest)&&isRound(state2.currentRound)&&(state2.status==="open"||state2.status==="closed")&&typeof state2.maxRoundsExhausted==="boolean"&&(state2.lastAttemptId===void 0||isUuid2(state2.lastAttemptId))&&(state2.lastDigest===void 0||isDigest(state2.lastDigest))&&state2.lastAttemptId===void 0===(state2.lastDigest===void 0)}function isTransition(value){return value==="stay"||value==="advance"||value==="close"}function isGateEffect(value){return value==="none"||value==="blocked"||value==="allowed"}function isVerdict(value){return value==="APPROVE"||value==="CONCERNS"||value==="REJECT"}function auditTransitionIsConsistent(record3){if(!record3.nextState||!record3.transition)return!1;if(record3.transition==="close")return record3.nextState.status==="closed"&&record3.nextState.currentRound===record3.authoritativeRound;if(record3.transition==="stay"){if(record3.nextState.status==="closed"&&!["duplicate_submission","council_round_closed","council_round_mismatch"].includes(record3.disposition))return!1;return(record3.nextState.status==="open"||record3.nextState.status==="closed")&&record3.nextState.currentRound===record3.authoritativeRound}return record3.nextState.status==="open"&&(record3.nextState.currentRound===record3.authoritativeRound+1&&record3.nextState.maxRoundsExhausted===!1||record3.nextState.currentRound===record3.authoritativeRound&&record3.nextState.maxRoundsExhausted===!0)}function recoverAuditHistory(tail2,identityDigest){let current=tail2.truncated?void 0:initialState(identityDigest),awaiting,sawTransition=!1;for(let record3 of tail2.records){if(record3.event==="received"){if(awaiting)throw new CouncilRoundStateUncertainError("council audit contains overlapping attempts");if(current&&record3.authoritativeRound!==current.currentRound||!current&&!tail2.truncated&&record3.authoritativeRound!==1)throw new CouncilRoundStateUncertainError("council audit round history is not monotonic");awaiting=record3;continue}if(!record3.nextState||!record3.transition)throw new CouncilRoundStateUncertainError("council audit transition is incomplete");if(awaiting){if(awaiting.attemptId!==record3.attemptId||awaiting.digest!==record3.digest||awaiting.authoritativeRound!==record3.authoritativeRound)throw new CouncilRoundStateUncertainError("council audit attempt pairing is inconsistent");awaiting=void 0}else if(!tail2.truncated||sawTransition)throw new CouncilRoundStateUncertainError("council audit transition has no matching received record");if(current){if(record3.authoritativeRound!==current.currentRound)throw new CouncilRoundStateUncertainError("council audit transition regresses the authoritative round");if(record3.transition==="stay"&&record3.nextState.status!==current.status)throw new CouncilRoundStateUncertainError("council audit stay transition changes scope status");if((record3.transition==="stay"||record3.transition==="close")&&record3.nextState.maxRoundsExhausted!==current.maxRoundsExhausted)throw new CouncilRoundStateUncertainError("council audit changes exhaustion without advancing");if(current.status==="closed"&&(record3.transition!=="stay"||record3.nextState.status!=="closed"))throw new CouncilRoundStateUncertainError("council audit reopens a closed scope")}current=record3.nextState,sawTransition=!0}if(awaiting)throw new CouncilRoundStateUncertainError("council audit ends with an unresolved received attempt");return current}function pendingMatchesParent(state2,pending){if(state2.status!=="open"||pending.round!==state2.currentRound)return!1;if(pending.nextState.lastAttemptId!==pending.attemptId||pending.nextState.lastDigest!==pending.digest)return!1;if(pending.transition==="stay")return pending.nextState.status==="open"&&pending.nextState.currentRound===state2.currentRound&&pending.nextState.maxRoundsExhausted===state2.maxRoundsExhausted;if(pending.transition==="close")return pending.nextState.status==="closed"&&pending.nextState.currentRound===state2.currentRound&&pending.nextState.maxRoundsExhausted===state2.maxRoundsExhausted;return pending.nextState.status==="open"&&(pending.nextState.currentRound===state2.currentRound+1&&pending.nextState.maxRoundsExhausted===!1||pending.nextState.currentRound===state2.currentRound&&pending.nextState.maxRoundsExhausted===!0)}function parseState(raw,expectedIdentityDigest){let value;try{value=JSON.parse(raw)}catch{throw new CouncilRoundStateUncertainError("council round state is corrupt")}if(!isSnapshot(value))throw new CouncilRoundStateUncertainError("council round state is invalid");let state2=value;if(state2.identityDigest!==expectedIdentityDigest)throw new CouncilRoundStateUncertainError("council round state identity does not match the request scope");if(state2.pending){let pending=state2.pending;if(!isUuid2(pending.attemptId)||!isDigest(pending.digest)||!isRound(pending.round)||!isSnapshot(pending.nextState)||!isTransition(pending.transition)||!isDisposition(pending.disposition)||!isGateEffect(pending.gateEffect)||typeof pending.evidenceExpected!=="boolean"||pending.evidenceExpected!==(pending.evidenceRef!==void 0)||pending.evidenceRef!==void 0&&!isEvidenceRef(pending.evidenceRef)||pending.verdict!==void 0&&!isVerdict(pending.verdict)||pending.quorumSize!==void 0&&(!Number.isInteger(pending.quorumSize)||pending.quorumSize<0||pending.quorumSize>5)||pending.verdict===void 0!==(pending.quorumSize===void 0)||!pendingMatchesParent(state2,pending))throw new CouncilRoundStateUncertainError("pending council state is invalid")}return state2}function parseAuditRecord(line,expectedScope){try{let record3=JSON.parse(line);if(record3.version!==VERSION||!["received","finalized","recovered"].includes(record3.event)||!isUuid2(record3.attemptId)||typeof record3.timestamp!=="string"||record3.timestamp.length>40||!Number.isFinite(Date.parse(record3.timestamp))||!sameAuditScope(record3.scope,expectedScope)||record3.clientRound!==void 0&&!isRound(record3.clientRound)||!isRound(record3.authoritativeRound)||!isDigest(record3.digest)||record3.sessionHash!==void 0&&!isDigest(record3.sessionHash)||!isDisposition(record3.disposition)||!Number.isInteger(record3.verdictCount)||record3.verdictCount<0||record3.verdictCount>5||!Array.isArray(record3.members)||record3.members.length>5||record3.members.some((member)=>typeof member!=="string"||member.length===0||member.length>32)||new Set(record3.members).size!==record3.members.length)throw Error("invalid");if(record3.event==="received"){if(record3.disposition!=="received"||record3.transition!==void 0||record3.gateEffect!==void 0||record3.nextState!==void 0||record3.evidenceRef!==void 0)throw Error("invalid")}else if(!isTransition(record3.transition)||!isGateEffect(record3.gateEffect)||!isSnapshot(record3.nextState)||record3.nextState.lastAttemptId!==record3.attemptId||record3.nextState.lastDigest!==record3.digest||!auditTransitionIsConsistent(record3))throw Error("invalid");if(record3.verdict!==void 0&&!isVerdict(record3.verdict))throw Error("invalid");if(record3.quorumSize!==void 0&&(!Number.isInteger(record3.quorumSize)||record3.quorumSize<0||record3.quorumSize>5))throw Error("invalid");if(record3.verdict===void 0!==(record3.quorumSize===void 0))throw Error("invalid");if(record3.evidenceRef!==void 0&&!isEvidenceRef(record3.evidenceRef))throw Error("invalid");return record3}catch{throw new CouncilRoundStateUncertainError("council attempt audit is corrupt")}}function appendAudit2(path335,record3){mkdirSync93(dirname124(path335),{recursive:!0});let descriptor=openSync41(path335,"a");try{writeSync7(descriptor,`${JSON.stringify(record3)}
|
|
7642
7642
|
`,void 0,"utf8"),fsyncSync11(descriptor)}finally{closeSync41(descriptor)}}function appendAuditAndObserve(input,paths,councilRoundId,record3){_internals293.appendAudit(paths.audit,record3),observeCouncilAuditAppend(input.scope,input.sessionID,councilRoundId,record3)}function readAuditTail(path335,scope){if(!existsSync173(path335))return{records:[],truncated:!1};let size=statSync106(path335).size;if(size===0)return{records:[],truncated:!1};let offset=Math.max(0,size-MAX_AUDIT_TAIL),length=size-offset,descriptor=openSync41(path335,"r"),buffer=Buffer.alloc(length);try{readSync29(descriptor,buffer,0,length,offset)}finally{closeSync41(descriptor)}let text=buffer.toString("utf8");if(!text.endsWith(`
|
|
7643
7643
|
`))throw new CouncilRoundStateUncertainError("council attempt audit has a partial tail");if(offset>0){let firstNewline=text.indexOf(`
|
|
@@ -7852,7 +7852,7 @@ ${jsdocContent}`;else if(line.includes("*/"))break;else if(functionKeywords.test
|
|
|
7852
7852
|
`)){let trimmed=line.trim();if(!trimmed)continue;let[name,rest]=trimmed.split(/\s+/,2);if(!name||!rest||byName.has(name))continue;let url3=rest.replace(/\s+\((?:fetch|push)\)\s*$/i,"");byName.set(boundUntrusted(name,64),boundUntrusted(url3,MAX_REMOTE_URL_LEN))}let entries2=[...byName.entries()],remotes=entries2.slice(0,MAX_REMOTES).map(([name,url3])=>({name,url:url3}));return{remotes,remotesTruncated:entries2.length>remotes.length}}async function countCheckoutReceiptFiles(directory,sessionID){try{let receiptDirectory=validateSwarmPath(directory,path367.join(RECEIPT_DIR2,prWorkflowSessionFileStem(sessionID)));return(await fsp12.readdir(receiptDirectory,{withFileTypes:!0})).filter((entry)=>entry.isFile()&&/^[0-9a-f]{40,64}\.json$/i.test(entry.name)).length}catch(error93){if(error93.code==="ENOENT")return 0;return null}}function describeDelegationRead(directory){try{let outcome=_internals317.readDelegationsDetailed(directory);if(outcome.status==="ok")return{state:"ok"};return{state:"uncertain",reasonCode:boundUntrusted(outcome.reason,MAX_RECOVERY_REASON_CODE_LEN)}}catch{return{state:"uncertain",reasonCode:"reader-threw"}}}function describeRecoveryNextStep(delegationReadState){if(delegationReadState==="uncertain")return"Delegation store read is uncertain: repair the store, then re-run pr_workflow_status; if abandoning the workflow, abort via abort_pr_workflow.";return"Re-run pr_workflow_status after any store repair; if abandoning the workflow, abort via abort_pr_workflow."}function describeNextStep(gate,git2,checkout){if(checkout.kind==="recovery-required"||checkout.kind==="indeterminate")return`Manual Git recovery required. code=${checkout.code} retryable=false required_action=${checkout.requiredAction}`;if(!gate.active){if(gate.reason==="delegation-chain-uncertain")return"PR workflow gate ownership could not be resolved from this session delegation chain (cycle, depth limit, or missing ancestor). Treat the workflow state as unknown and use read-only recovery inspection; do not perform PR-workflow writes.";return"No active PR workflow gate for this session. Activate with `/swarm pr-review <pr-ref>` or `/swarm pr-feedback <pr-ref>` before PR-workflow tool calls are admitted."}if(!gate.prHeadBound)return gate.mode==="PR_FEEDBACK"?"PR_FEEDBACK gate active; PR head not yet bound. If the working tree is dirty, preserve it with prepare_pr_workflow_checkout (omit paths to include tracked and untracked changes). Prefer the intended exact tracking checkout, then bind; if this workflow inherited an already-detached exact intake head, bind it directly and the controller will attach the unique exact local/remote tracking ref. Ambiguity or an existing mismatched upstream fails closed.":"PR_REVIEW gate active; PR head not yet bound. If the working tree is dirty, preserve it with prepare_pr_workflow_checkout (omit paths to include tracked and untracked changes), then bind the exact detached PR head.";if(git2.isClean===!1)return`${gate.mode} gate active and head bound, but the working tree is dirty. Read-only observation only; the gate keeps writes and non-tracking fetches fail-closed.`;if(git2.isClean===null)return`${gate.mode} gate active and head bound, but this session could not determine whether the working tree is clean (git status failed). Treat the tree state as unknown and verify manually before assuming it is clean; read-only observation only.`;return`${gate.mode} gate active and head bound. Continue read-only review using the admitted observe/validate tools (diff, gh_evidence, repo_map, lint check, etc.).`}function summarizeGate(state2,receiptFiles,salvage){if(!state2)return{active:!1,reason:"no-active-gate"};return{active:!0,...salvage?.salvaged?{stateSalvaged:!0,stateSalvageDisclosure:salvage.disclosure}:{},mode:state2.mode,prHeadBound:Boolean(state2.prHeadSha),prHeadSha:state2.prHeadSha??null,prFeedbackTargetUrl:state2.prFeedbackTargetUrl?boundUntrusted(state2.prFeedbackTargetUrl,MAX_FIELD_LEN):null,prReviewBaseRef:state2.prReviewBaseRef?boundUntrusted(state2.prReviewBaseRef,MAX_FIELD_LEN):null,prReviewBaseSha:state2.prReviewBaseSha??null,prReviewDepthTier:state2.prReviewDepthTier??null,baseDispatchBatches:state2.prReviewBaseDispatches?.length??0,validationBatches:state2.prReviewValidationBatches?.length??0,feedbackVerificationBatches:state2.prFeedbackVerifications?.length??0,...state2.prFeedbackInventoryAmendments?.length?{inventoryAmendments:state2.prFeedbackInventoryAmendments}:{},checkoutReceiptFiles:receiptFiles,activatedAt:state2.activatedAt,updatedAt:state2.updatedAt,revision:state2.revision}}function boundFindingLine(line){let cleaned=line.replace(/[\p{Cc}]/gu," ").replace(/[`<>]/g," ").replace(/\s+/g," ").trim(),chars=Array.from(cleaned);if(chars.length<=PR_REVIEW_STATUS_FINDING_LINE_MAX)return cleaned;return`${chars.slice(0,PR_REVIEW_STATUS_FINDING_LINE_MAX-1).join("")}…`}async function buildPrReviewProjection(directory,state2,projectionDropped){let settledPhases=new Set(state2.prReviewArtifactBoundaries??[]),runId=state2.prReviewArtifactRunId??null,findingsPath=state2.prReviewFindingsPath??null,digests=state2.prReviewVerdictSettlementDigests??{},boundaries=PR_REVIEW_BOUNDARY_ORDER.map((phase)=>{let settlementPhase=PR_REVIEW_BOUNDARY_SETTLEMENT_PHASE[phase],settled=settledPhases.has(phase);return{phase,status:settled?"settled":"pending",runId,findingsPath,settlementDigest:settled&&settlementPhase?digests[settlementPhase]??null:null}}),declaredLanes=[];for(let batch of state2.prReviewBaseDispatches??[])for(let lane of batch.lanes??[])declaredLanes.push({laneId:lane.laneId,workflowLane:lane.workflowLane,batchId:batch.batchId});let laneCoverageTruncated=declaredLanes.length>PR_REVIEW_STATUS_LANE_ROWS_CAP,emittedLanes=declaredLanes.slice(0,PR_REVIEW_STATUS_LANE_ROWS_CAP),rejectionCounts=new Map;for(let entry of state2.prReviewSubmitRejections??[]){if(!entry.laneId)continue;rejectionCounts.set(entry.laneId,(rejectionCounts.get(entry.laneId)??0)+1)}let receiptsByLane=new Map,uncertainBatches=new Set,headSha=state2.prHeadSha;for(let batchId of new Set(emittedLanes.map((lane)=>lane.batchId)))try{let outcome=_internals317.findByBatchIdDetailed(directory,batchId,{parentSessionId:state2.sessionID});if(outcome.status==="uncertain"){uncertainBatches.add(batchId);continue}for(let record3 of outcome.value){if(record3.laneId==null||record3.mode!=="swarm-pr-review:base")continue;if(record3.workspace?.prHeadSha!==headSha||record3.workspace?.gitHead!==headSha)continue;let receipt=recordedPrReviewResultReceipt(record3);if(!receipt)continue;let key3=`${batchId}\x00${record3.laneId}`;if(!receiptsByLane.has(key3))receiptsByLane.set(key3,receipt)}}catch{uncertainBatches.add(batchId)}let laneCoverage=emittedLanes.map((lane)=>{let uncertain=uncertainBatches.has(lane.batchId),receipt=uncertain?void 0:receiptsByLane.get(`${lane.batchId}\x00${lane.laneId}`),findings=receipt?.envelope.findings??[],lastFinding=findings[findings.length-1],latestFinding=uncertain?"receipt-uncertain":receipt?lastFinding?boundFindingLine(`${lastFinding.severity} ${lastFinding.id}: ${lastFinding.title}`):receipt.envelope.outcome==="CLEAN"?"clean":"incomplete":"no-receipt",findingsTruncated=findings.length>PR_REVIEW_STATUS_FINDINGS_PER_LANE,findingSummaries=findings.slice(0,PR_REVIEW_STATUS_FINDINGS_PER_LANE).map((finding)=>({id:boundUntrusted(finding.id,PR_REVIEW_STATUS_FINDING_ID_MAX),severity:boundUntrusted(finding.severity,PR_REVIEW_STATUS_FINDING_SEVERITY_MAX),title:boundUntrusted(finding.title,PR_REVIEW_STATUS_FINDING_LINE_MAX)}));return{laneId:lane.laneId,workflowLane:lane.workflowLane,batchId:lane.batchId,accepted:findings.length,rejected:rejectionCounts.get(lane.laneId)??0,latestFinding,findings:findingSummaries,findingsTruncated}}),inventory=projectionDropped?{state:"unavailable",reason:SALVAGED_PROJECTION_REASON}:await(async()=>{let derived=await derivePrReviewCandidateInventoryForStatus(directory,state2);if(derived.state==="unavailable")return{state:"unavailable",reason:boundUntrusted(derived.reason,PR_REVIEW_STATUS_FINDING_LINE_MAX)};return{state:"available",ids:derived.inventory.slice(0,PR_REVIEW_STATUS_INVENTORY_CAP).map((id)=>boundUntrusted(id,PR_REVIEW_STATUS_FINDING_ID_MAX)),truncated:derived.inventory.length>PR_REVIEW_STATUS_INVENTORY_CAP,total:derived.inventory.length,cap:PR_REVIEW_STATUS_INVENTORY_CAP}})(),salvagedSource=()=>projectionDropped?{state:"unavailable",reason:SALVAGED_PROJECTION_REASON}:{state:"ok"},verdictAttempts=["reviewer","critic"].flatMap((phase)=>deriveVerdictAttemptCounts({window:prReviewPhaseWindowForStatus(state2,phase),unclaimed:[...new Set(prReviewPhaseWindowForStatus(state2,phase).flatMap((batch)=>batch.lanes.flatMap((lane)=>lane.reviewItemIds??[])))]}).map((row)=>({...row,phase})));return{boundaries,checkpointScope:"shared-last-write-wins",laneCoverage,laneCoverageTruncated,laneCoverageAdmission:"lane-record-only",inventory,verdictAttempts,sources:{boundaries:salvagedSource(),laneCoverage:salvagedSource()}}}async function resolveWorkflowGate(directory,sessionID){let outcome=await _internals317.resolvePrWorkflowControllerSession({directory,sessionID,readGate:(candidate2)=>_internals317.readPrWorkflowGateStateForRecovery(directory,candidate2)});if(outcome.kind==="gate-owner")return{sessionID:outcome.sessionID,recovery:outcome.gate};if(outcome.kind==="no-gate")return{sessionID:outcome.sessionID,recovery:null};return{sessionID:null,recovery:null}}async function resolveWorkflowGateSession(directory,sessionID){return(await resolveWorkflowGate(directory,sessionID)).sessionID}async function executePrWorkflowStatus(directory,rawSessionID){let sessionID=rawSessionID?.trim()?rawSessionID.trim():null,resolvedGate=sessionID?await resolveWorkflowGate(directory,sessionID):null,gateSessionID=resolvedGate?.sessionID??null,[head2,isClean,branchInfo,porcelain,remoteOutput,liveCheckout]=await Promise.all([_internals317.resolveCurrentGitHeadAsync(directory),_internals317.resolveIsWorkingTreeCleanAsync(directory),resolveBranch(directory),_internals317.runGitCapture(directory,["status","--porcelain=v1","--untracked-files=all"]),_internals317.runGitCapture(directory,["remote","-v"]),_internals317.classifyGitState(directory)]),dirty=parseDirtyFiles(porcelain),{remotes,remotesTruncated}=parseRemotes(remoteOutput),git2={head:head2,branch:branchInfo.branch,detached:branchInfo.detached,isClean,dirtyFileCount:dirty.dirtyFileCount,dirtyFiles:dirty.dirtyFiles,dirtyFilesTruncated:dirty.dirtyFilesTruncated,remotes,remotesTruncated},gate,activeState=null;if(!gateSessionID)gate={active:!1,reason:sessionID?"delegation-chain-uncertain":"no-session-context"};else{let recovery2=resolvedGate?.recovery??null;activeState=recovery2?.state??null;let receiptFiles=activeState?await countCheckoutReceiptFiles(directory,gateSessionID):null;if(gate=summarizeGate(activeState,receiptFiles,recovery2?{salvaged:recovery2.salvaged,disclosure:recovery2.disclosure}:void 0),activeState?.mode==="PR_REVIEW")gate.prReviewProjection=await buildPrReviewProjection(directory,activeState,recovery2?.prReviewProjectionDropped??!1)}let recovery=activeState?.checkoutRecovery,checkout=recovery?{kind:recovery.code==="GIT_STATE_INDETERMINATE"?"indeterminate":"recovery-required",code:recovery.code,retryable:!1,requiredAction:recovery.requiredAction,evidence:recovery.evidence}:liveCheckout,delegationRead=describeDelegationRead(directory),recoverySection={controllerSessionID:gateSessionID,delegationRead,lastProgress:activeState?{revision:activeState.revision,updatedAt:activeState.updatedAt}:null,wakeSuspension:{suspended:sessionID?_internals317.isPrWorkflowAutoWakeSuppressed(directory,sessionID):!1},actionCircuits:{state:"unavailable"},nextStep:describeRecoveryNextStep(delegationRead.state)},result={success:!0,sessionID,git:git2,checkout,gate,publication:activeState?describePrWorkflowPublicationSection(activeState):null,nextStep:describeNextStep(gate,git2,checkout),recovery:recoverySection};return JSON.stringify(result,null,2)}var pr_workflow_status=createSwarmTool({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 (mode, bound PR head, base ref/sha, depth tier, dispatch/validation batch counts) and, for an active PR_REVIEW gate, a bounded projection of boundary settlement, per-lane coverage, and the derived candidate inventory. Use to observe state under the fail-closed PR_REVIEW/PR_FEEDBACK gate. Never executes PR-controlled scripts and never reads another session gate.",args:{},execute:async(_args,directory,ctx)=>executePrWorkflowStatus(directory,ctx?.sessionID)}),_internals317={readPrWorkflowGateStateForRecovery,readDelegationsDetailed,isPrWorkflowAutoWakeSuppressed,resolvePrWorkflowControllerSession,resolveCurrentGitHeadAsync,resolveIsWorkingTreeCleanAsync,runGitCapture:runGitCapture2,classifyGitState:classifyPrWorkflowGitState,truncateToByteBudget,resolveWorkflowGateSession,findByBatchIdDetailed,boundUntrusted,boundFindingLine};init_p_limit();init_zod();init_config2();init_manager2();init_utils();init_external_tool_runner();init_filesystem_identity();init_git_executable();init_project_boundary();init_create_tool();init_lint();import*as path368 from"node:path";init_quality_budget();init_sast_scan();init_secretscan();var TOOL_TIMEOUT_MS=60000,MAX_COMBINED_BYTES=500000,MAX_COMPACT_ERROR_BYTES=4096,CANCELLATION_SETTLEMENT_GRACE_MS=1000,MAX_CONCURRENT=4,MAX_FILES=100,GIT_TIMEOUT_MS12=1e4,GIT_MAX_OUTPUT_BYTES2=2000000,ALL_LINES_CHANGED=-1,MAX_CHANGED_LINE_ENTRIES=200000,_internals318={qualityBudget,runLintWrapped,runSecretscanWrapped,runSastScanWrapped,runQualityBudgetWrapped,runWithTimeout:runWithTimeout2,getChangedLineRanges,getChangedLineAmbiguousFiles,saveEvidence,runExternalTool,detectResolvedLinter,runLintOnFiles,platform:()=>process.platform,serializePreCheckResult,resolveGatePreamble,runPreCheckBatch,loadGateOverrides,MAX_COMBINED_BYTES};function formatIncompletePaths(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 evaluateSecretscanGate(toolResult,requestedFiles,classification){if(toolResult.error)return{passed:!1,summary:`Secretscan wrapper error: ${toolResult.error}`,findingsCount:0};if(!toolResult.ran||!toolResult.result)return{passed:!1,summary:"Secretscan did not return a result",findingsCount:0};if("error"in toolResult.result)return{passed:!1,summary:`Secretscan error: ${toolResult.result.error}`,findingsCount:0};let result=toolResult.result;if(typeof result.incomplete_files!=="number"||!Array.isArray(result.incomplete_paths))return{passed:!1,summary:"Secretscan failed: scanner returned incomplete coverage metadata",result,findingsCount:Math.max(result.count,result.findings.length)};let findingsCount=Math.max(result.count,result.findings.length),failures=[],vacuousCoverage=result.files_scanned===0&&typeof result.policy_skipped_files==="number"&&typeof result.requested_files==="number"&&result.requested_files>0&&result.policy_skipped_files>=result.requested_files&&result.count===0&&result.findings.length===0&&result.incomplete_files===0&&result.incomplete_paths.length===0,newFindingsCount=classification?classification.newFindings.length:findingsCount;if(newFindingsCount>0)failures.push(`${newFindingsCount} new secret finding(s) on changed lines`);if(result.truncated===!0)failures.push(`results truncated at ${SECRETSCAN_MAX_FINDINGS} findings`);if(result.incomplete_files>0||result.incomplete_paths.length>0){let incompletePaths=result.incomplete_paths.length>0?`; incomplete paths: ${formatIncompletePaths(result.incomplete_paths)}`:"";failures.push(`${result.incomplete_files} incomplete file(s)${incompletePaths}`)}if(result.count!==result.findings.length)failures.push(`findings/count mismatch (reported ${result.count}, actual ${result.findings.length})`);if(requestedFiles>0&&result.files_scanned===0&&!vacuousCoverage)failures.push(typeof result.ignored_files==="number"&&result.ignored_files>0?`${result.ignored_files} requested file(s) suppressed by .secretscanignore; no file scanned`:"zero requested files scanned");let statistics=`Secretscan: ${findingsCount} finding(s), ${result.files_scanned} files scanned, ${result.skipped_files} skipped`;if(classification)statistics+=`, ${classification.newFindings.length} new secret finding(s) on changed lines (${classification.preexistingFindings.length} pre-existing)`;if(vacuousCoverage)statistics+=`, all ${result.requested_files} requested file(s) skipped by secretscan scan policy (vacuous coverage)`;let passedSummary=classification?.diffScoped?`${statistics}; secretscan green = zero new secrets on changed lines`:statistics;return{passed:failures.length===0,summary:failures.length>0?`${statistics}; failed: ${failures.join("; ")}`:passedSummary,result,findingsCount,...classification&&{newFindingsCount:classification.newFindings.length,preexistingFindingsCount:classification.preexistingFindings.length,diffScoped:classification.diffScoped}}}function truncateUtf8(value,maxBytes){if(Buffer.byteLength(value,"utf8")<=maxBytes)return value;let marker="... (truncated)",budget=Math.max(0,maxBytes-Buffer.byteLength(marker,"utf8")),result="",usedBytes=0;for(let character of value){let characterBytes=Buffer.byteLength(character,"utf8");if(usedBytes+characterBytes>budget)break;result+=character,usedBytes+=characterBytes}return`${result}${marker}`}function compactToolResult(toolResult){return{ran:toolResult.ran,duration_ms:toolResult.duration_ms,...toolResult.error!==void 0&&{error:truncateUtf8(toolResult.error,MAX_COMPACT_ERROR_BYTES)},...toolResult.error===void 0&&toolResult.result!==void 0&&{result_omitted:!0}}}function serializePreCheckResult(result){let serialized3=JSON.stringify(result,null,2);if(Buffer.byteLength(serialized3,"utf8")<=MAX_COMBINED_BYTES)return serialized3;let compact={batch_status:result.batch_status,gates_passed:result.gates_passed,...result.sast_degraded!==void 0&&{sast_degraded:result.sast_degraded},...result.sast_skipped!==void 0&&{sast_skipped:result.sast_skipped},lint:compactToolResult(result.lint),secretscan:compactToolResult(result.secretscan),sast_scan:compactToolResult(result.sast_scan),quality_budget:compactToolResult(result.quality_budget),total_duration_ms:result.total_duration_ms,output_truncated:!0};return JSON.stringify(compact,null,2)}function isWindowsAbsolutePath(inputPath){return/^[A-Za-z]:[/\\]/.test(inputPath)}function validatePath(inputPath,baseDir,workspaceDir){if(typeof inputPath!=="string")return"path must be a string";if(!inputPath||inputPath.trim().length===0)return"path is required";let resolved,isWinAbs=isWindowsAbsolutePath(inputPath);if(isWinAbs)resolved=path368.win32.resolve(inputPath);else if(path368.isAbsolute(inputPath))resolved=path368.resolve(inputPath);else resolved=path368.resolve(baseDir,inputPath);let workspaceResolved=isWindowsAbsolutePath(workspaceDir)?path368.win32.resolve(workspaceDir):path368.resolve(workspaceDir),relative98;if(isWinAbs)relative98=path368.win32.relative(workspaceResolved,resolved);else relative98=path368.relative(workspaceResolved,resolved);if(relative98.startsWith(".."))return"path traversal detected";return null}function isAcceptedProjectRootForPlatform(dir,workspaceDir,platform,hasExplicitBoundary,exactPhysicalRoot=!1){if(exactPhysicalRoot)return!0;let pathApi=platform==="win32"?path368.win32:path368,directoryKey=pathApi.resolve(dir).replace(/\\/g,"/"),workspaceKey=pathApi.resolve(workspaceDir).replace(/\\/g,"/"),normalizedDirectoryKey=platform==="win32"?directoryKey.toLowerCase():directoryKey,normalizedWorkspaceKey=platform==="win32"?workspaceKey.toLowerCase():workspaceKey;if(normalizedDirectoryKey===normalizedWorkspaceKey)return!0;let relative98=pathApi.relative(workspaceDir,dir);return relative98!==""&&relative98!==".."&&!relative98.startsWith(`..${pathApi.sep}`)&&!pathApi.isAbsolute(relative98)&&hasExplicitBoundary}function validateDirectory2(dir,workspaceDir){if(!dir||dir.length===0)return"directory is required";if(dir.length>500)return"directory path too long";let exactPhysicalRoot=sameExistingFilesystemPath(dir,workspaceDir);if(!exactPhysicalRoot){let traversalCheck=validatePath(dir,workspaceDir,workspaceDir);if(traversalCheck)return traversalCheck}let platform=_internals318.platform();if(!isAcceptedProjectRootForPlatform(dir,workspaceDir,platform,hasExplicitProjectBoundary(dir),exactPhysicalRoot))return"directory must resolve to the project root";return null}async function runWithTimeout2(operation,timeoutMs,parentSignal,waitForCancellationSettlement=!1){let controller=new AbortController,timeoutHandle,parentAbortListener;if(parentSignal?.aborted)throw Error("Tool execution cancelled");let parentAbortPromise=new Promise((_,reject3)=>{if(!parentSignal)return;if(parentAbortListener=()=>{reject3(Error("Tool execution cancelled")),controller.abort()},parentSignal.addEventListener("abort",parentAbortListener,{once:!0}),parentSignal.aborted)parentAbortListener()});if(controller.signal.aborted)return await parentAbortPromise;let operationPromise=operation(controller.signal);try{let timeoutPromise=new Promise((_,reject3)=>{timeoutHandle=setTimeout(()=>{reject3(Error(`Timeout after ${timeoutMs}ms`)),controller.abort()},timeoutMs)});return await Promise.race([operationPromise,timeoutPromise,parentAbortPromise])}catch(error93){if(controller.signal.aborted&&waitForCancellationSettlement){let settlementTimer;try{await Promise.race([operationPromise.then(()=>{return},()=>{return}),new Promise((resolve144)=>{settlementTimer=setTimeout(resolve144,CANCELLATION_SETTLEMENT_GRACE_MS)})])}finally{if(settlementTimer!==void 0)clearTimeout(settlementTimer)}}throw error93}finally{if(timeoutHandle!==void 0)clearTimeout(timeoutHandle);if(parentAbortListener&&parentSignal)parentSignal.removeEventListener("abort",parentAbortListener)}}async function runLintWrapped(files,directory,_gates,abortSignal){let start=process.hrtime.bigint();try{let resolvedLinter=await _internals318.detectResolvedLinter(directory,abortSignal);if(!resolvedLinter)return{ran:!1,error:"No linter found (biome or eslint)",duration_ms:Number(process.hrtime.bigint()-start)/1e6};if(files&&files.length>0)return{ran:!0,result:await _internals318.runLintOnFiles(resolvedLinter,files,directory,abortSignal),duration_ms:Number(process.hrtime.bigint()-start)/1e6};return{ran:!0,result:await _internals210.runResolvedLint(resolvedLinter,"check",directory,abortSignal),duration_ms:Number(process.hrtime.bigint()-start)/1e6}}catch(error93){return{ran:!0,error:error93 instanceof Error?error93.message:"Unknown error",duration_ms:Number(process.hrtime.bigint()-start)/1e6}}}async function runLintOnFiles(resolvedLinter,files,workspaceDir,abortSignal){if(resolvedLinter.source==="legacy-test-probe")return _internals210.runResolvedLint(resolvedLinter,"check",workspaceDir,abortSignal);let validatedFiles=[];for(let file3 of files){if(typeof file3!=="string")continue;let resolvedPath=path368.resolve(file3);if(validatePath(resolvedPath,workspaceDir,workspaceDir))continue;validatedFiles.push(resolvedPath)}if(validatedFiles.length===0)return{success:!1,mode:"check",linter:resolvedLinter.linter,command:[],error:"No valid files after security validation"};let args2;if(resolvedLinter.linter==="biome")args2=[...resolvedLinter.argsPrefix,"check",...validatedFiles];else args2=[...resolvedLinter.argsPrefix,...validatedFiles];let command=[...resolvedLinter.displayPrefix,...args2];try{let execution=await _internals318.runExternalTool({executable:resolvedLinter.executable,args:args2,cwd:workspaceDir,timeoutMs:TOOL_TIMEOUT_MS,maxStdoutBytes:512000,maxStderrBytes:512000,abortSignal});if(execution.status!=="completed")return{success:!1,mode:"check",linter:resolvedLinter.linter,command,error:execution.message??`Execution ${execution.status}`};let exitCode=execution.exitCode??1,output=execution.stdout;if(execution.stderr)output+=(output?`
|
|
7853
7853
|
`:"")+execution.stderr;if(execution.stdoutTruncated||execution.stderrTruncated)output+=`
|
|
7854
7854
|
... (output truncated)`;let result={success:!0,mode:"check",linter:resolvedLinter.linter,command,exitCode,output};if(exitCode===0)result.message=`${resolvedLinter.linter} check completed successfully with no issues`;else if(resolvedLinter.linter==="biome"&&output.includes("No files were processed"))result.message=`${resolvedLinter.linter} check processed no files (all specified paths ignored by biome configuration)`;else result.message=`${resolvedLinter.linter} check found issues (exit code ${exitCode}).`;return result}catch(error93){return{success:!1,mode:"check",linter:resolvedLinter.linter,command,error:error93 instanceof Error?`Execution failed: ${error93.message}`:"Execution failed: unknown error"}}}async function runSecretscanWrapped(files,directory,_gates,abortSignal,rawRequestedFiles){let start=process.hrtime.bigint();try{if(files&&files.length>0)return{ran:!0,result:await runWithTimeout2(()=>runSecretscanOnFiles(files,directory,rawRequestedFiles),TOOL_TIMEOUT_MS,abortSignal),duration_ms:Number(process.hrtime.bigint()-start)/1e6};return{ran:!0,result:await runWithTimeout2(()=>runSecretscan(directory),TOOL_TIMEOUT_MS,abortSignal,!0),duration_ms:Number(process.hrtime.bigint()-start)/1e6}}catch(error93){return{ran:!0,error:error93 instanceof Error?error93.message:"Unknown error",duration_ms:Number(process.hrtime.bigint()-start)/1e6}}}async function runSastScanWrapped(changedFiles,directory,severityThreshold,gates,phase,abortSignal){let start=process.hrtime.bigint();try{return{ran:!0,result:await runWithTimeout2((signal2)=>sastScan({changed_files:changedFiles,severity_threshold:severityThreshold,phase,abort_signal:signal2},directory,gates),TOOL_TIMEOUT_MS,abortSignal,!0),duration_ms:Number(process.hrtime.bigint()-start)/1e6}}catch(error93){return{ran:!0,error:error93 instanceof Error?error93.message:"Unknown error",duration_ms:Number(process.hrtime.bigint()-start)/1e6}}}async function runQualityBudgetWrapped(changedFiles,directory,gates,abortSignal){let start=process.hrtime.bigint();try{return{ran:!0,result:await runWithTimeout2((signal2)=>_internals318.qualityBudget({changed_files:changedFiles,config:gates?.quality_budget},directory,signal2),TOOL_TIMEOUT_MS,abortSignal,!0),duration_ms:Number(process.hrtime.bigint()-start)/1e6}}catch(error93){return{ran:!0,error:error93 instanceof Error?error93.message:"Unknown error",duration_ms:Number(process.hrtime.bigint()-start)/1e6}}}var GATE_SEVERITIES=new Set(["high","critical"]),SEVERITY_ORDER_PCB={low:0,medium:1,high:2,critical:3};function meetsThresholdForTriage(severity2,threshold){return(SEVERITY_ORDER_PCB[severity2]??0)>=(SEVERITY_ORDER_PCB[threshold]??1)}async function runGit8(args2,directory,abortSignal){let gitExecutable;try{gitExecutable=await resolveGitExecutableAsync()}catch{return null}let result=await _internals318.runExternalTool({executable:gitExecutable,args:args2,cwd:directory,timeoutMs:GIT_TIMEOUT_MS12,maxStdoutBytes:GIT_MAX_OUTPUT_BYTES2,maxStderrBytes:64000,abortSignal});if(result.status!=="completed"||result.exitCode!==0||result.stdoutTruncated)return null;return result.stdout}function decodeGitQuotedPath(value){if(!value.startsWith('"'))return value;if(!value.endsWith('"'))return null;let bytes=[],appendText=(text)=>{bytes.push(...Buffer.from(text,"utf8"))};for(let index=1;index<value.length-1;index++){let codePoint=value.codePointAt(index);if(codePoint===void 0)return null;let char=String.fromCodePoint(codePoint);if(char!=="\\"){if(appendText(char),char.length===2)index++;continue}if(index++,index>=value.length-1)return null;let escaped=value[index],simple={"\\":"\\",'"':'"',t:"\t",n:`
|
|
7855
|
-
`,r:"\r",b:"\b",f:"\f",v:"\v"};if(simple[escaped]!==void 0){appendText(simple[escaped]);continue}if(/[0-7]/.test(escaped)){let octal=escaped;for(let count4=0;count4<2;count4++){let next=value[index+1];if(!next||!/[0-7]/.test(next))break;octal+=next,index++}bytes.push(Number.parseInt(octal,8));continue}return null}return Buffer.from(bytes).toString("utf8")}function normalizeRepoPathKey(repoPath){let normalized=repoPath.replace(/\\/g,"/");return _internals318.platform()==="win32"||_internals318.platform()==="darwin"?normalized.toLowerCase():normalized}function normalizeDiffPath(rawPath){let pathToken=rawPath.startsWith('"')?rawPath:rawPath.split("\t",1)[0],decoded=decodeGitQuotedPath(pathToken);if(decoded===null||decoded==="/dev/null"||decoded.trim().length===0)return null;return normalizeRepoPathKey(decoded)}function parseDiffLineRangesChecked(diffOutput,requireGitFileHeaders){let result=new Map,currentFile=null,inGitFile=!1,expectingDestination=!1,destinationSeen=!1,destinationNeedsHunk=!1,collectedLines=0;for(let rawLine of diffOutput.split(/\r?\n/)){let line=rawLine.endsWith("\r")?rawLine.slice(0,-1):rawLine;if(line.startsWith("diff --git ")){if(expectingDestination||destinationNeedsHunk)return null;inGitFile=!0,currentFile=null,expectingDestination=!1,destinationSeen=!1;continue}if(line.startsWith("--- ")&&(inGitFile||!requireGitFileHeaders)){if(expectingDestination||destinationNeedsHunk)return null;expectingDestination=!0;continue}if(line.startsWith("+++ ")){if(requireGitFileHeaders&&(!inGitFile||!expectingDestination))return null;let rawDestination=line.slice(4);if(currentFile=normalizeDiffPath(rawDestination),currentFile===null&&rawDestination.trim()!=="/dev/null")return null;if(expectingDestination=!1,destinationSeen=!0,destinationNeedsHunk=!0,!currentFile)continue;if(!result.has(currentFile))result.set(currentFile,new Set);continue}if(!line.startsWith("@@"))continue;if(expectingDestination||requireGitFileHeaders&&(!inGitFile||!destinationSeen))return null;let match=/^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/.exec(line);if(!match)return null;let start=Number.parseInt(match[1],10),count4=match[2]!==void 0?Number.parseInt(match[2],10):1;if(!Number.isSafeInteger(start)||!Number.isSafeInteger(count4)||count4<0||count4>0&&start<1||count4>MAX_CHANGED_LINE_ENTRIES||start+count4-1>Number.MAX_SAFE_INTEGER||collectedLines+count4>MAX_CHANGED_LINE_ENTRIES)return null;if(destinationNeedsHunk=!1,!currentFile)continue;let lines=result.get(currentFile);if(!lines)return null;for(let index=0;index<count4;index++)lines.add(start+index);collectedLines+=count4}if(expectingDestination||destinationNeedsHunk)return null;return result}function mergeChangedLines(target,source){for(let[file3,sourceLines]of source){let targetLines=target.get(file3)??new Set;for(let line of sourceLines)targetLines.add(line);target.set(file3,targetLines)}}function parseUntrackedStatus(output){if(output.length>0&&!output.endsWith("\x00"))return null;let untracked=[],records=output.split("\x00");for(let index=0;index<records.length-1;index++){let record3=records[index];if(!record3||record3.length<4||record3[2]!==" ")return null;let status2=record3.slice(0,2),filePath=record3.slice(3);if(!filePath||!isKnownPorcelainStatus(status2))return null;if(status2==="??"||status2==="!!")untracked.push(normalizeRepoPathKey(filePath));if(/[RC]/.test(status2)){let sourcePath=records[++index];if(!sourcePath||looksLikePorcelainStatusRecord(sourcePath))return null}}return untracked}function isKnownPorcelainStatus(status2){if(status2==="??"||status2==="!!")return!0;if(/U/.test(status2))return new Set(["DD","AU","UD","UA","DU","AA","UU"]).has(status2);return status2!==" "&&/^[ MTADRC]{2}$/.test(status2)}function looksLikePorcelainStatusRecord(value){return value.length>=4&&value[2]===" "&&isKnownPorcelainStatus(value.slice(0,2))}async function getChangedLineAmbiguousFiles(directory,abortSignal,requestedFiles=[]){let mergeBase=null;for(let baseBranch of["zaxbyhub/main","upstream/main","origin/main","main","origin/master","master"]){let candidate2=(await runGit8(["merge-base",baseBranch,"HEAD"],directory,abortSignal))?.trim();if(candidate2&&/^[0-9a-f]{40,64}$/i.test(candidate2)){mergeBase=candidate2;break}}if(!mergeBase)return null;let headSha=(await runGit8(["rev-parse","HEAD"],directory,abortSignal))?.trim();if(typeof headSha==="string"&&/^[0-9a-f]{40,64}$/i.test(headSha)&&headSha.toLowerCase()===mergeBase.toLowerCase())return null;let literalPathspecs=requestedFiles.map((file3)=>path368.relative(directory,file3).replace(/\\/g,"/")).filter((file3)=>file3.length>0&&file3!==".."&&!file3.startsWith("../")).map((file3)=>`:(literal)${file3}`),statusArgs=["-c","core.quotePath=false","status","--porcelain=v1","-z","--untracked-files=all",...literalPathspecs.length>0?["--",...literalPathspecs]:[]],[committedNames,status2]=await Promise.all([runGit8(["-c","core.quotePath=false","diff","--name-only","--no-ext-diff","--no-color","--no-prefix","-z",`${mergeBase}..HEAD`,"--",...literalPathspecs.length>0?literalPathspecs:[]],directory,abortSignal),runGit8(statusArgs,directory,abortSignal)]);if(committedNames===null||status2===null)return null;let committed=new Set(committedNames.split("\x00").filter(Boolean).map(normalizeRepoPathKey)),staged=new Set,unstaged=new Set;if(status2.length>0&&!status2.endsWith("\x00"))return null;let records=status2.split("\x00");for(let index=0;index<records.length-1;index++){let record3=records[index];if(!record3||record3.length<4||record3[2]!==" ")return null;let statusCode=record3.slice(0,2),filePath=record3.slice(3);if(!filePath||!isKnownPorcelainStatus(statusCode))return null;if(statusCode!=="??"&&statusCode!=="!!"){let key3=normalizeRepoPathKey(filePath);if(/[MADRCU]/.test(statusCode[0]))staged.add(key3);if(/[MADRCU]/.test(statusCode[1]))unstaged.add(key3)}if(/[RC]/.test(statusCode)){let sourcePath=records[++index];if(!sourcePath||looksLikePorcelainStatusRecord(sourcePath))return null}}let ambiguous=new Set;for(let key3 of committed)if(staged.has(key3)||unstaged.has(key3))ambiguous.add(key3);for(let key3 of staged)if(unstaged.has(key3))ambiguous.add(key3);return ambiguous}async function getChangedLineRanges(directory,abortSignal,requestedFiles=[]){let mergeBase=null;for(let baseBranch of["zaxbyhub/main","upstream/main","origin/main","main","origin/master","master"]){let candidate2=(await runGit8(["merge-base",baseBranch,"HEAD"],directory,abortSignal))?.trim();if(candidate2&&/^[0-9a-f]{40,64}$/i.test(candidate2)){mergeBase=candidate2;break}}if(!mergeBase)return null;let commonDiffArgs=["-c","core.quotePath=false","diff","--no-ext-diff","--no-color","--no-prefix","-U0"],requestedPathspecs=requestedFiles.map((file3)=>path368.relative(directory,file3).replace(/\\/g,"/")).filter((file3)=>file3.length>0&&file3!==".."&&!file3.startsWith("../")),statusArgs=["-c","core.quotePath=false","status","--porcelain=v1","-z","--untracked-files=all",...requestedPathspecs.length>0?["--ignored=matching"]:[],...requestedPathspecs.length>0?["--",...requestedPathspecs]:[]],[committed,staged,unstaged,status2]=await Promise.all([runGit8([...commonDiffArgs,`${mergeBase}..HEAD`,"--"],directory,abortSignal),runGit8([...commonDiffArgs,"--cached","HEAD","--"],directory,abortSignal),runGit8([...commonDiffArgs,"--"],directory,abortSignal),runGit8(statusArgs,directory,abortSignal)]);if(committed===null||staged===null||unstaged===null||status2===null)return null;let committedLines=parseDiffLineRangesChecked(committed,!0),stagedLines=parseDiffLineRangesChecked(staged,!0),unstagedLines=parseDiffLineRangesChecked(unstaged,!0);if(!committedLines||!stagedLines||!unstagedLines)return null;let result=new Map;mergeChangedLines(result,committedLines),mergeChangedLines(result,stagedLines),mergeChangedLines(result,unstagedLines);let untracked=parseUntrackedStatus(status2);if(untracked===null)return null;let requestedKeys=requestedPathspecs.map(normalizeRepoPathKey);for(let file3 of untracked)if(result.set(file3,new Set([ALL_LINES_CHANGED])),file3.endsWith("/")){for(let requestedFile of requestedKeys)if(requestedFile.startsWith(file3))result.set(requestedFile,new Set([ALL_LINES_CHANGED]))}return result}function classifySastFindings(findings,changedLineRanges,directory){if(!changedLineRanges)return{newFindings:findings,preexistingFindings:[]};let newFindings=[],preexistingFindings=[],pathApi=_internals318.platform()==="win32"?path368.win32:path368.posix,resolvedDirectory=pathApi.resolve(directory);for(let finding of findings){let filePath=finding.location.file,normalised;try{if(typeof filePath!=="string"||filePath.length===0||filePath.includes("\x00")){newFindings.push(finding);continue}let resolvedFinding=pathApi.isAbsolute(filePath)?pathApi.resolve(filePath):pathApi.resolve(resolvedDirectory,filePath),relative98=pathApi.relative(resolvedDirectory,resolvedFinding);if(pathApi.isAbsolute(relative98)||relative98===".."||relative98.startsWith(`..${pathApi.sep}`)){newFindings.push(finding);continue}normalised=normalizeRepoPathKey(relative98)}catch{newFindings.push(finding);continue}let changedLines=changedLineRanges.get(normalised);if(changedLines?.has(ALL_LINES_CHANGED)||changedLines?.has(finding.location.line))newFindings.push(finding);else preexistingFindings.push(finding)}return{newFindings,preexistingFindings}}function classifySecretFindings(findings,changedLineRanges,directory,ambiguousFiles){if(!changedLineRanges)return{newFindings:findings,preexistingFindings:[]};let newFindings=[],preexistingFindings=[],pathApi=_internals318.platform()==="win32"?path368.win32:path368.posix,resolvedDirectory=pathApi.resolve(directory);for(let finding of findings){let{path:filePath,line}=finding;if(typeof filePath!=="string"||filePath.length===0||filePath.includes("\x00")||typeof line!=="number"||!Number.isSafeInteger(line)||line<1){newFindings.push(finding);continue}let changedLines;try{let resolvedFinding=pathApi.isAbsolute(filePath)?pathApi.resolve(filePath):pathApi.resolve(resolvedDirectory,filePath),relative98=pathApi.relative(resolvedDirectory,resolvedFinding);if(pathApi.isAbsolute(relative98)||relative98===".."||relative98.startsWith(`..${pathApi.sep}`)){newFindings.push(finding);continue}let normalised=normalizeRepoPathKey(relative98);if(ambiguousFiles?.has(normalised)){newFindings.push(finding);continue}changedLines=changedLineRanges.get(normalised)}catch{newFindings.push(finding);continue}if(changedLines!==void 0&&changedLines.size>0&&!changedLines.has(ALL_LINES_CHANGED)&&!changedLines.has(line))preexistingFindings.push(finding);else newFindings.push(finding)}return{newFindings,preexistingFindings}}async function runPreCheckBatch(input,workspaceDir,contextDir,abortSignal){let effectiveWorkspaceDir=workspaceDir||input.directory||contextDir,{files,directory,sast_threshold="medium",gates:gatesOverrides,phase,sast_enabled=!0}=input,gates=gatesOverrides??(input.config?.gates?{sast_scan:input.config.gates.sast_scan,quality_budget:input.config.gates.quality_budget}:void 0),dirError=validateDirectory2(directory,effectiveWorkspaceDir);if(dirError)return warn(`pre_check_batch: Invalid directory: ${dirError}`),{batch_status:"invalid",gates_passed:!1,lint:{ran:!1,error:dirError,duration_ms:0},secretscan:{ran:!1,error:dirError,duration_ms:0},sast_scan:{ran:!1,error:dirError,duration_ms:0},quality_budget:{ran:!1,error:dirError,duration_ms:0},total_duration_ms:0};if(!files||files.length===0)return warn("pre_check_batch: No files provided, skipping all tools (fail-closed)"),{batch_status:"invalid",gates_passed:!1,lint:{ran:!1,error:"No files provided",duration_ms:0},secretscan:{ran:!1,error:"No files provided",duration_ms:0},sast_scan:{ran:!1,error:"No files provided",duration_ms:0},quality_budget:{ran:!1,error:"No files provided",duration_ms:0},total_duration_ms:0};let changedFiles=[],rawDeclaredCount=files.length;for(let file3 of files){if(typeof file3!=="string"){warn(`pre_check_batch: Non-string file entry rejected: ${String(file3)}`);continue}if(validatePath(file3,directory,effectiveWorkspaceDir)){warn(`pre_check_batch: Invalid file path: ${file3}`);continue}changedFiles.push(path368.resolve(directory,file3))}if(changedFiles.length===0)return warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)"),{batch_status:"invalid",gates_passed:!1,lint:{ran:!1,error:"No files provided",duration_ms:0},secretscan:{ran:!1,error:"No files provided",duration_ms:0},sast_scan:{ran:!1,error:"No files provided",duration_ms:0},quality_budget:{ran:!1,error:"No files provided",duration_ms:0},total_duration_ms:0};try{assertProjectRoot(directory)}catch(error93){let rootError=error93 instanceof Error?error93.message:String(error93);return warn(`pre_check_batch: Project-root validation failed: ${rootError}`),{batch_status:"invalid",gates_passed:!1,lint:{ran:!1,error:rootError,duration_ms:0},secretscan:{ran:!1,error:rootError,duration_ms:0},sast_scan:{ran:!1,error:rootError,duration_ms:0},quality_budget:{ran:!1,error:rootError,duration_ms:0},total_duration_ms:0}}if(changedFiles.length>MAX_FILES)throw Error(`Input exceeds maximum file count: ${changedFiles.length} > ${MAX_FILES}`);let limit=pLimit(MAX_CONCURRENT),sastDisabledByConfig=gates?.sast_scan?.enabled===!1,[lintResult,secretscanResult,sastScanResult,qualityBudgetResult]=await Promise.all([limit(()=>_internals318.runLintWrapped(changedFiles,directory,gates,abortSignal)),limit(()=>_internals318.runSecretscanWrapped(changedFiles,directory,gates,abortSignal,rawDeclaredCount)),sast_enabled&&!sastDisabledByConfig?limit(()=>_internals318.runSastScanWrapped(changedFiles,directory,sast_threshold,gates,phase,abortSignal)):Promise.resolve({ran:!1,duration_ms:0}),limit(()=>_internals318.runQualityBudgetWrapped(changedFiles,directory,gates,abortSignal))]),totalDuration=lintResult.duration_ms+secretscanResult.duration_ms+sastScanResult.duration_ms+qualityBudgetResult.duration_ms,gatesPassed=!0;if(lintResult.ran&&lintResult.result){let lintRes=lintResult.result;if("success"in lintRes&&lintRes.success===!1)warn("pre_check_batch: Lint found issues (informational only)")}else if(lintResult.error)warn(`pre_check_batch: Lint error (informational only): ${lintResult.error}`);let changedLineRangesMemo,getChangedLineRangesMemoized=async()=>{if(changedLineRangesMemo===void 0)changedLineRangesMemo=await _internals318.getChangedLineRanges(directory,abortSignal,changedFiles);return changedLineRangesMemo},secretscanClassification,secretscanPreexistingFindings,secretscanScanFindings=secretscanResult.ran&&secretscanResult.result&&!("error"in secretscanResult.result)?secretscanResult.result.findings:[];if(secretscanScanFindings.length>0){let changedLineRanges=await getChangedLineRangesMemoized(),ambiguousFiles=await _internals318.getChangedLineAmbiguousFiles(directory,abortSignal,changedFiles);if(ambiguousFiles===null)secretscanClassification={newFindings:secretscanScanFindings,preexistingFindings:[],diffScoped:!1};else{let{newFindings,preexistingFindings}=classifySecretFindings(secretscanScanFindings,changedLineRanges,directory,ambiguousFiles);if(secretscanClassification={newFindings,preexistingFindings,diffScoped:changedLineRanges!==null},preexistingFindings.length>0)secretscanPreexistingFindings=preexistingFindings,warn(`pre_check_batch: Secretscan found ${preexistingFindings.length} pre-existing secret finding(s) on unchanged lines - visible, non-gating, passed to reviewer for triage`)}}let secretscanDecision=evaluateSecretscanGate(secretscanResult,rawDeclaredCount,secretscanClassification);if(!secretscanDecision.passed)gatesPassed=!1,warn(`pre_check_batch: ${secretscanDecision.summary} - GATE FAILED`);if(secretscanResult.ran||secretscanResult.error)try{let scanResult=secretscanDecision.result,secretscanEvidence={task_id:"secretscan",type:"secretscan",timestamp:new Date().toISOString(),agent:"pre_check_batch",verdict:secretscanDecision.passed?"pass":"fail",summary:secretscanDecision.summary,findings_count:secretscanDecision.findingsCount,scan_directory:scanResult?.scan_dir??directory,files_scanned:scanResult?.files_scanned??0,skipped_files:scanResult?.skipped_files??0,ignored_files:scanResult?.ignored_files??0,policy_skipped_files:scanResult?.policy_skipped_files??0,requested_files:scanResult?.requested_files??rawDeclaredCount,new_findings_count:secretscanDecision.newFindingsCount??0,preexisting_findings_count:secretscanDecision.preexistingFindingsCount??0,diff_scoped:secretscanDecision.diffScoped??!1,incomplete_files:scanResult?.incomplete_files??changedFiles.length,incomplete_paths:scanResult?.incomplete_paths??[{path:".",reason:"missing_coverage_metadata"}]};await _internals318.saveEvidence(directory,"secretscan",secretscanEvidence,abortSignal)}catch(e){let persistError=`Failed to persist secretscan evidence: ${e instanceof Error?e.message:String(e)}`;secretscanResult.error=persistError,gatesPassed=!1,warn(`pre_check_batch: ${persistError} - GATE FAILED`)}let sastPreexistingFindings,sastDegraded=!1;if(sastScanResult.ran&&sastScanResult.result){let sastResult=sastScanResult.result;if(sastResult.error)if(sastResult.failure_kind==="semgrep_process_exit"&&sastResult.findings.length===0)sastDegraded=!0,warn(`pre_check_batch: SAST coverage degraded (${sastResult.error}) - continuing without a gate failure`);else gatesPassed=!1,warn(`pre_check_batch: SAST scan error (${sastResult.error}) - GATE FAILED`);else if(sastResult.baseline_used){let sastCarryFindings=[...sastResult.pre_existing_findings??[],...sastResult.moved_findings??[]];if(sastCarryFindings.length>0){if(sastPreexistingFindings=sastCarryFindings.filter((f)=>meetsThresholdForTriage(f.severity,sast_threshold)),sastPreexistingFindings.length>0)warn(`pre_check_batch: SAST baseline diff found ${sastPreexistingFindings.length} pre-existing/moved finding(s) - passing to reviewer for triage`)}if(sastResult.verdict==="fail")gatesPassed=!1,warn("pre_check_batch: SAST scan found new findings above threshold - GATE FAILED")}else if(sastResult.verdict==="fail"){let gateFindings=sastResult.findings.filter((f)=>GATE_SEVERITIES.has(f.severity));if(gateFindings.length>0){let changedLineRanges=await getChangedLineRangesMemoized(),{newFindings,preexistingFindings}=classifySastFindings(gateFindings,changedLineRanges,directory);if(newFindings.length>0)gatesPassed=!1,warn(`pre_check_batch: SAST scan found ${newFindings.length} new HIGH/CRITICAL finding(s) on changed lines - GATE FAILED`);else if(preexistingFindings.length>0)sastPreexistingFindings=preexistingFindings,warn(`pre_check_batch: SAST scan found ${preexistingFindings.length} pre-existing HIGH/CRITICAL finding(s) on unchanged lines - passing to reviewer for triage`)}else gatesPassed=!1,warn("pre_check_batch: SAST scan found vulnerabilities - GATE FAILED")}}else if(sastScanResult.error)gatesPassed=!1,warn(`pre_check_batch: SAST scan error - GATE FAILED: ${sastScanResult.error}`);if(qualityBudgetResult.ran&&qualityBudgetResult.result){if(qualityBudgetResult.result.verdict==="fail")warn("pre_check_batch: Quality budget exceeded (informational only)")}else if(qualityBudgetResult.error)warn(`pre_check_batch: Quality budget error (informational only): ${qualityBudgetResult.error}`);return{batch_status:[lintResult,secretscanResult,sastScanResult,qualityBudgetResult].every((toolResult)=>toolResult.ran===!1)?"skipped":"completed",gates_passed:gatesPassed,lint:lintResult,secretscan:secretscanResult,sast_scan:sastScanResult,quality_budget:qualityBudgetResult,total_duration_ms:Math.round(totalDuration),...sastDegraded&&{sast_degraded:!0},...(!sast_enabled||sastDisabledByConfig)&&{sast_skipped:!0},...sastPreexistingFindings&&sastPreexistingFindings.length>0&&{sast_preexisting_findings:sastPreexistingFindings},...secretscanPreexistingFindings&&secretscanPreexistingFindings.length>0&&{secretscan_preexisting_findings:secretscanPreexistingFindings}}}var pre_check_batch=createSwarmTool({allowWorkingDirectoryOverride:!0,description:"Run multiple verification tools in parallel: lint, secretscan, SAST scan, and quality budget. Returns unified result with gates_passed status. Security findings and incomplete SAST runs are hard failures; a Semgrep nonzero process exit with zero findings is returned as explicit sast_degraded coverage and does not block.",args:{files:exports_external.array(exports_external.string()).optional().describe("Specific files to check (optional, scans directory if not provided)"),directory:exports_external.string().describe("Project root directory — ordinary workspace subdirectories are rejected; direct .git or .opencode project boundaries are accepted"),sast_threshold:exports_external.enum(["low","medium","high","critical"]).optional().describe("Minimum severity for SAST findings to cause failure (default: medium)"),phase:exports_external.number().int().min(1).optional().describe("Current phase number (positive integer >= 1). When provided, enables SAST baseline diffing: only findings absent from the phase-scoped baseline fail the gate.")},async execute(args2,directory,ctx){if(!args2||typeof args2!=="object")return serializePreCheckResult({batch_status:"invalid",gates_passed:!1,lint:{ran:!1,error:"Invalid arguments",duration_ms:0},secretscan:{ran:!1,error:"Invalid arguments",duration_ms:0},sast_scan:{ran:!1,error:"Invalid arguments",duration_ms:0},quality_budget:{ran:!1,error:"Invalid arguments",duration_ms:0},total_duration_ms:0});if(!directory||typeof directory!=="string"||directory.trim()==="")return serializePreCheckResult({batch_status:"invalid",gates_passed:!1,lint:{ran:!1,error:"project directory is required but was not provided",duration_ms:0},secretscan:{ran:!1,error:"project directory is required but was not provided",duration_ms:0},sast_scan:{ran:!1,error:"project directory is required but was not provided",duration_ms:0},quality_budget:{ran:!1,error:"project directory is required but was not provided",duration_ms:0},total_duration_ms:0});let typedArgs=args2;if(!typedArgs.directory)return serializePreCheckResult({batch_status:"invalid",gates_passed:!1,lint:{ran:!1,error:"directory is required",duration_ms:0},secretscan:{ran:!1,error:"directory is required",duration_ms:0},sast_scan:{ran:!1,error:"directory is required",duration_ms:0},quality_budget:{ran:!1,error:"directory is required",duration_ms:0},total_duration_ms:0});let resolvedDirectory=path368.resolve(typedArgs.directory),workspaceAnchor=path368.resolve(directory);if(isStrictPathDescendant(resolvedDirectory,workspaceAnchor)&&!hasExplicitProjectBoundary(resolvedDirectory)){let subDirError=`directory "${typedArgs.directory}" is a subdirectory of the project root — pre_check_batch requires the project root directory "${workspaceAnchor}"`;return serializePreCheckResult({batch_status:"invalid",gates_passed:!1,lint:{ran:!1,error:subDirError,duration_ms:0},secretscan:{ran:!1,error:subDirError,duration_ms:0},sast_scan:{ran:!1,error:subDirError,duration_ms:0},quality_budget:{ran:!1,error:subDirError,duration_ms:0},total_duration_ms:0})}let dirError=validateDirectory2(resolvedDirectory,workspaceAnchor);if(dirError)return serializePreCheckResult({batch_status:"invalid",gates_passed:!1,lint:{ran:!1,error:dirError,duration_ms:0},secretscan:{ran:!1,error:dirError,duration_ms:0},sast_scan:{ran:!1,error:dirError,duration_ms:0},quality_budget:{ran:!1,error:dirError,duration_ms:0},total_duration_ms:0});try{let sastEnabled=!0;try{let preamble=await _internals318.resolveGatePreamble(resolvedDirectory,ctx?.sessionID);if(preamble.resolved&&preamble.effectiveGates)sastEnabled=preamble.effectiveGates.sast_enabled}catch{warn("pre_check_batch: QA-gate profile resolution failed; keeping SAST enabled")}let rawPhase=typedArgs.phase,safePhase=typeof rawPhase==="number"&&Number.isInteger(rawPhase)&&rawPhase>=1?rawPhase:void 0,result=await _internals318.runPreCheckBatch({files:typedArgs.files,directory:resolvedDirectory,sast_threshold:typedArgs.sast_threshold,config:typedArgs.config,gates:_internals318.loadGateOverrides(resolvedDirectory),phase:safePhase,sast_enabled:sastEnabled},workspaceAnchor,directory,ctx?.abort);return serializePreCheckResult(result)}catch(error93){let errorMessage3=error93 instanceof Error?error93.message:"Unknown error";return serializePreCheckResult({batch_status:"invalid",gates_passed:!1,lint:{ran:!1,error:errorMessage3,duration_ms:0},secretscan:{ran:!1,error:errorMessage3,duration_ms:0},sast_scan:{ran:!1,error:errorMessage3,duration_ms:0},quality_budget:{ran:!1,error:errorMessage3,duration_ms:0},total_duration_ms:0})}}});init_zod();init_pr_workflow_gate();init_atomic_write();init_create_tool();import{createHash as createHash119}from"node:crypto";import{mkdirSync as mkdirSync98,readdirSync as readdirSync57,realpathSync as realpathSync58,rmSync as rmSync36,statSync as statSync113}from"node:fs";import{tmpdir as tmpdir20}from"node:os";import path369 from"node:path";var MAX_COMMIT_MESSAGE_CHARS=8192,MESSAGE_FILE_TTL_MS=86400000,PreparePrFeedbackCommitMessageArgsSchema=exports_external.object({message:exports_external.string().refine((value)=>value.trim().length>0,{message:"message must not be empty or whitespace-only"}).refine((value)=>value.length<=MAX_COMMIT_MESSAGE_CHARS,{message:`message must be at most ${MAX_COMMIT_MESSAGE_CHARS} characters`}).refine((value)=>!value.includes("\x00"),{message:"message must not contain NUL bytes"}).transform((value)=>value.trim())}).strict();function commitMessageTargetDir(){return path369.join(tmpdir20(),"swarm-pr-feedback-commit-msg")}function resolvePrFeedbackCommitMessageFilePath(sessionID,message){let sanitizedSession=sessionID.replace(/[^A-Za-z0-9._-]/g,"_"),digest5=createHash119("sha256").update(message,"utf8").digest("hex").slice(0,16);return path369.join(commitMessageTargetDir(),`${sanitizedSession}-${digest5}.txt`)}function pruneStaleMessageFiles(){try{let dir=commitMessageTargetDir(),now2=Date.now();for(let entry of readdirSync57(dir)){if(!entry.endsWith(".txt"))continue;let full=path369.join(dir,entry);try{let stats2=statSync113(full);if(now2-stats2.mtimeMs>MESSAGE_FILE_TTL_MS)rmSync36(full,{force:!1})}catch{}}}catch{}}async function executePreparePrFeedbackCommitMessage(args2,directory,context={}){let parsed=PreparePrFeedbackCommitMessageArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid commit-message request: ${parsed.error.issues.map((issue3)=>issue3.path.length>0?`${issue3.path.join(".")}: ${issue3.message}`:issue3.message).join("; ")}`});let sessionID=context.sessionID?.trim();if(!sessionID)return JSON.stringify({success:!1,message:"Commit-message authoring requires an active sessionID"});let state2=await readPrWorkflowGateState(directory,sessionID);if(!state2||state2.mode!=="PR_FEEDBACK"||!state2.prHeadSha)return JSON.stringify({success:!1,message:"Commit-message authoring requires an active bound PR_FEEDBACK workflow; bind the PR head first"});let message=parsed.data.message,targetDir=commitMessageTargetDir(),targetPath=resolvePrFeedbackCommitMessageFilePath(sessionID,message),resolvedTarget=path369.resolve(targetPath),resolvedDir=path369.resolve(targetDir);if(!(resolvedTarget===resolvedDir||resolvedTarget.startsWith(resolvedDir+path369.sep)))return JSON.stringify({success:!1,message:"Commit-message file path escaped the swarm-pr-feedback-commit-msg directory; refusing to write"});let repoRoot=path369.resolve(directory),insideRepo=(value)=>{let rel3=path369.relative(repoRoot,value);return rel3===""||!rel3.startsWith("..")&&!path369.isAbsolute(rel3)};if(insideRepo(resolvedTarget)||insideRepo(resolvedDir))return JSON.stringify({success:!1,message:"TMPDIR resolves inside the repository; the commit-message file must live outside the repository — refusing to write"});try{mkdirSync98(resolvedDir,{recursive:!0});let realpathDir=resolvedDir;try{realpathDir=realpathSync58(resolvedDir)}catch{mkdirSync98(resolvedDir,{recursive:!0})}let realpathTarget=path369.join(realpathDir,path369.basename(resolvedTarget));if(!realpathTarget.startsWith(realpathDir+path369.sep)&&realpathTarget!==realpathDir)return JSON.stringify({success:!1,message:"Commit-message file path escaped the swarm-pr-feedback-commit-msg directory through a symlink; refusing to write"});if(insideRepo(realpathDir))return JSON.stringify({success:!1,message:"The resolved temp directory points inside the repository through a symlink; refusing to write"});pruneStaleMessageFiles(),await atomicWriteFileAnyRoot(realpathTarget,message,{mode:384})}catch(error93){return JSON.stringify({success:!1,message:`Could not author the commit-message file: ${error93 instanceof Error?error93.message:String(error93)}`})}return JSON.stringify({success:!0,path:resolvedTarget,message:"Commit-message file authored outside the repository; commit with git commit -F <path> (the classifier refuses in-repo message files). The file is mode 0600, lives in the OS temp directory, never touches the bound checkout, and is pruned after 24h."})}var prepare_pr_feedback_commit_message=createSwarmTool({description:"Author a PR_FEEDBACK commit message that contains shell metacharacters (e.g. a Co-Authored-By trailer with <...>) into a file OUTSIDE the repository, returning the path for the sanctioned git commit -F command. The inline -m form is rejected by the shell classifier by design; an in-repo message file would dirty the clean-tree arming check. Requires an active bound PR_FEEDBACK workflow.",args:{message:PreparePrFeedbackCommitMessageArgsSchema.shape.message},execute:executePreparePrFeedbackCommitMessage});init_zod();init_guardrails2();init_pr_workflow_gate();init_scope_binding();init_create_tool();var PreparePrFeedbackScopeArgsSchema=exports_external.object({task_id:exports_external.string().regex(/^\d+\.\d+(?:\.\d+)*$/,"task_id must use N.M notation"),files:exports_external.array(exports_external.string().min(1).max(4096)).min(1).max(1e4)}).strict();function failure3(message){return JSON.stringify({success:!1,message},null,2)}async function executePreparePrFeedbackScope(args2,directory,context={}){let parsed=PreparePrFeedbackScopeArgsSchema.safeParse(args2);if(!parsed.success)return failure3(`Invalid PR-feedback scope: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`);let sessionID=context.sessionID?.trim();if(!sessionID)return failure3("PR-feedback scope requires an active session");let files=normalizeScopeFiles(parsed.data.files);if(!files)return failure3("PR-feedback scope contains an unsafe file path");for(let file3 of files){let symlinkBlock=checkWriteTargetForSymlink(file3,directory);if(symlinkBlock)return failure3(symlinkBlock)}try{await declarePrFeedbackScope(directory,sessionID,parsed.data.task_id,files)}catch(error93){return failure3(error93 instanceof Error?error93.message:String(error93))}return JSON.stringify({success:!0,task_id:parsed.data.task_id,files,message:"Scope is bound to the verified PR-feedback revision and will authorize only the next matching coder Task."},null,2)}var prepare_pr_feedback_scope=createSwarmTool({description:"Prepare an exact file scope for one PR-feedback coder Task after immutable feedback verification settles.",args:{task_id:PreparePrFeedbackScopeArgsSchema.shape.task_id,files:PreparePrFeedbackScopeArgsSchema.shape.files},execute:executePreparePrFeedbackScope});init_quality_budget();init_zod();init_pr_workflow_gate();init_create_tool();var RebindPrFeedbackHeadArgsSchema=exports_external.object({pr_head_sha:exports_external.string().trim().regex(/^[0-9a-f]{40}$/i)}).strict();async function executeRebindPrFeedbackHead(args2,directory,context={}){let parsed=RebindPrFeedbackHeadArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid PR feedback rebind: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`});if(!context.sessionID?.trim())return JSON.stringify({success:!1,message:"PR feedback rebind requires an active sessionID"});try{let state2=await rebindPrFeedbackHead(directory,context.sessionID,parsed.data.pr_head_sha);return JSON.stringify({success:!0,pr_head_sha:state2.prHeadSha,rebind_count:state2.prFeedbackRebindCount??1,message:"Rebound the PR_FEEDBACK intake head; every Stage A / verification / gate receipt is invalidated — re-run the full mechanical ladder on the new ancestry."})}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:String(error93)})}}var rebind_pr_feedback_head=createSwarmTool({description:"Rebind a PR_FEEDBACK workflow to a new verified remote PR head after merge/rebase/conflict repair (base-sync). Use ONLY when the history genuinely changed to repair base drift or conflicts: it refuses a no-op rebind to the current intake head, refuses while publication is armed (to change approved content after arming use invalidate_pr_feedback_publication), and refuses while lanes are in flight. It invalidates every ancestry-bound receipt (Stage A, verification, ordered gates) so the full mechanical ladder re-runs on the new ancestry. Requires the full 40-char new PR head SHA; the current checkout must equal it.",args:{pr_head_sha:RebindPrFeedbackHeadArgsSchema.shape.pr_head_sha},execute:executeRebindPrFeedbackHead});init_zod();init_utils2();init_atomic_write();init_create_tool();var FreshnessValueSchema=exports_external.string().trim().min(1).max(500).regex(/^(synced|behind:[1-9][0-9]*|fetch-failed:\S+)$/,"must be 'synced', 'behind:<n>', or 'fetch-failed:<reason>' (reason contains no whitespace)"),RecordBranchFreshnessArgsSchema=exports_external.object({issueNumber:exports_external.number().int().min(1),freshness:FreshnessValueSchema,override:exports_external.string().trim().min(1).max(4000).optional()}).strict();async function executeRecordBranchFreshness(args2,directory,context={}){let parsed=RecordBranchFreshnessArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid branch-freshness receipt: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`});let data=parsed.data;if(data.freshness==="synced"&&data.override)return JSON.stringify({success:!1,message:"An override is only meaningful for a fetch-failed outcome; a synced base needs none."});let receipt={issueNumber:data.issueNumber,freshness:data.freshness,timestamp:new Date().toISOString()};if(data.override)receipt.override=data.override;if(context.sessionID?.trim())receipt.sessionId=context.sessionID.trim();let validatedPath;try{validatedPath=validateSwarmPath(directory,"branch-freshness.json")}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:"Failed to validate path"})}try{await atomicWriteSwarmFile(validatedPath,JSON.stringify(receipt,null,2));let permits=await branchFreshnessReceiptExists(directory,data.issueNumber);return JSON.stringify({success:!0,issueNumber:data.issueNumber,path:".swarm/branch-freshness.json",permits,message:permits?`Branch-freshness receipt recorded for issue #${data.issueNumber}; the trace's freshness gate is satisfied.`:`Branch-freshness receipt recorded for issue #${data.issueNumber}, but the outcome (${data.freshness}) does NOT permit the trace — ${data.freshness.startsWith("behind:")?"re-sync with the default branch and re-record as synced.":"a fetch-failed outcome without a recorded user override fails closed."}`})}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:String(error93)})}}var record_branch_freshness=createSwarmTool({description:`Record the Phase 0 branch-freshness outcome for the current traced issue (issue #2564): freshness is "synced", "behind:<n>", or "fetch-failed:<reason>" exactly as the fetch recorded it, plus an optional verbatim user override for a failed fetch. The /swarm issue --trace workflow will not transition to PLAN until the recorded outcome permits (synced, or fetch-failed with an override). The response's permits field mirrors the gate reader's verdict on the persisted receipt (advisory for the calling agent — the reducer always recomputes it independently).`,args:{issueNumber:RecordBranchFreshnessArgsSchema.shape.issueNumber,freshness:RecordBranchFreshnessArgsSchema.shape.freshness,override:RecordBranchFreshnessArgsSchema.shape.override},execute:executeRecordBranchFreshness});init_zod();init_plan_schema();init_schema();init_extractors();init_manager();init_create_tool();var recordDirectiveOverrideInternals={loadPlan,recordDirectiveOverrides};async function executeRecordDirectiveOverride(args2,directory,ctx){if(!ctx?.sessionID?.trim())return{success:!1,code:"DIRECTIVE_OVERRIDE_SESSION_REQUIRED",message:"An exact session identity is required to record an override."};if(stripKnownSwarmPrefix(ctx.agent??"").toLowerCase()!=="architect")return{success:!1,code:"DIRECTIVE_OVERRIDE_ARCHITECT_ONLY",message:"Only the architect may record a critical-directive override."};let plan=await recordDirectiveOverrideInternals.loadPlan(directory),requestedPhase=plan?.phases.find((candidate2)=>candidate2.id===args2.phase);if(!plan||!requestedPhase||getCurrentPhase(plan)!==args2.phase&&!isPhaseInWrapWindow(plan,args2.phase))return{success:!1,code:"DIRECTIVE_OVERRIDE_PHASE_MISMATCH",message:`Phase ${args2.phase} is neither the current plan phase nor the phase being wrapped.`};let phaseLabel=extractPhaseLabelFromPlan(plan,args2.phase)??`Phase ${args2.phase}`;return await recordDirectiveOverrideInternals.recordDirectiveOverrides(directory,[...new Set(args2.directive_ids)],args2.justification,ctx.sessionID,phaseLabel,args2.phase),{success:!0,code:"DIRECTIVE_OVERRIDE_RECORDED",phase:args2.phase,directive_ids:[...new Set(args2.directive_ids)],message:"Recorded the audited override. Retry phase_complete so every gate is re-evaluated from a fresh snapshot."}}var record_directive_override=createSwarmTool({description:"Architect-only audited override for identified critical-directive violations. Requires the current phase (or the phase being wrapped, whose last task already advanced the cursor), the session identity and substantive justification; it cannot repair or bypass unreadable authority.",args:{directive_ids:exports_external.array(exports_external.string().min(1).max(256)).min(1).max(64),justification:exports_external.string().trim().min(10).max(2000),phase:exports_external.number().int().min(1).max(9999)},execute:async(args2,directory,ctx)=>JSON.stringify(await executeRecordDirectiveOverride(args2,directory,ctx),null,2)});init_zod();init_utils2();init_atomic_write();init_create_tool();var RecordImplementationReviewArgsSchema=exports_external.object({issueNumber:exports_external.number().int().min(1),reviewerVerdict:exports_external.enum(["APPROVE","NEEDS_REVISION","BLOCKED"]),criticVerdict:exports_external.enum(["APPROVE","NEEDS_REVISION","BLOCKED"]),diffBase:exports_external.string().trim().regex(/^[0-9a-f]{7,40}$/i),diffHead:exports_external.string().trim().regex(/^[0-9a-f]{7,40}$/i),notes:exports_external.string().trim().min(8).max(4000)}).strict();async function executeRecordImplementationReview(args2,directory,context={}){let parsed=RecordImplementationReviewArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid implementation review receipt: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`});let data=parsed.data;if(data.reviewerVerdict!=="APPROVE"||data.criticVerdict!=="APPROVE")return JSON.stringify({success:!1,message:"A satisfying implementation-review receipt requires BOTH the reviewer and the critic to have delivered APPROVE; record non-approving verdicts in the working notes and fix the findings instead."});let receipt={issueNumber:data.issueNumber,reviewerVerdict:data.reviewerVerdict,criticVerdict:data.criticVerdict,diffBase:data.diffBase,diffHead:data.diffHead,notes:data.notes,timestamp:new Date().toISOString()};if(context.sessionID?.trim())receipt.sessionId=context.sessionID.trim();let validatedPath;try{validatedPath=validateSwarmPath(directory,"implementation-review.json")}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:"Failed to validate path"})}try{return await atomicWriteSwarmFile(validatedPath,JSON.stringify(receipt,null,2)),JSON.stringify({success:!0,issueNumber:data.issueNumber,path:".swarm/implementation-review.json",message:`Implementation review recorded for issue #${data.issueNumber} (reviewer APPROVE + critic APPROVE); the trace may now satisfy its review gate.`})}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:String(error93)})}}var record_implementation_review=createSwarmTool({description:"Record the independent implementation review for the current traced issue (issue #2131 residual B): dispatch FRESH-context reviewer and critic passes over the implementation diff (separate contexts from the implementer), and once BOTH approve call this with the issue number, both APPROVE verdicts, the reviewed diff base/head SHAs, and notes. The /swarm issue --trace workflow will not hand off to commit-pr until this receipt exists. Non-approving verdicts cannot be recorded here — fix the findings and re-review.",args:{issueNumber:RecordImplementationReviewArgsSchema.shape.issueNumber,reviewerVerdict:RecordImplementationReviewArgsSchema.shape.reviewerVerdict,criticVerdict:RecordImplementationReviewArgsSchema.shape.criticVerdict,diffBase:RecordImplementationReviewArgsSchema.shape.diffBase,diffHead:RecordImplementationReviewArgsSchema.shape.diffHead,notes:RecordImplementationReviewArgsSchema.shape.notes},execute:executeRecordImplementationReview});init_zod();init_url_security();init_loader();init_utils2();init_forge_provider();init_atomic_write();init_create_tool();function loadConfiguredForgeContext4(directory){try{let config3=loadPluginConfig(directory),remote=detectGitRemote(directory,void 0);return resolveForgeContextFromPluginConfig(config3,remote?[remote]:[])??void 0}catch{return}}var RecordIssuePublicationArgsSchema=exports_external.object({issueNumber:exports_external.number().int().min(1),prNumber:exports_external.number().int().min(1),prUrl:exports_external.string().url(),headSha:exports_external.string().min(1).optional()}).strict();async function executeRecordIssuePublication(args2,directory){let parsed=RecordIssuePublicationArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid publication receipt: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`});let{issueNumber,prNumber,prUrl,headSha}=parsed.data,sanitizedPrUrl=sanitizeUrl(prUrl);if(!isForgePrUrl(prUrl)){let configured=loadConfiguredForgeContext4(directory);if(!(configured&&isForgePrUrl(prUrl,configured)))return JSON.stringify({success:!1,message:"Invalid publication receipt: prUrl must be a canonical PR URL (GitHub https://github.com/<owner>/<repo>/pull/<number> or GitLab https://<gitlab-host>/<owner>/<repo>/-/merge_requests/<number>)"})}let receipt={published:!0,issueNumber,prNumber,prUrl:sanitizedPrUrl,publishedAt:new Date().toISOString()};if(headSha)receipt.headSha=headSha;let validatedPath;try{validatedPath=validateSwarmPath(directory,"issue-publication.json")}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:"Failed to validate path"})}try{return await atomicWriteSwarmFile(validatedPath,JSON.stringify(receipt,null,2)),JSON.stringify({success:!0,issueNumber,prNumber,prUrl,path:".swarm/issue-publication.json",message:`Publication receipt recorded for issue #${issueNumber} (PR #${prNumber}); the issue-trace workflow will transition to its terminal published state.`})}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:String(error93)})}}var record_issue_publication=createSwarmTool({description:'Record that the traced issue has been published (PR created/updated) so the /swarm issue --trace workflow can reach its terminal published state. The trace stops at publication_handoff (the commit-pr directive) until this receipt is observed — publication_handoff is NOT "issue resolved". commit-pr calls this after the PR is created/updated. Supply the traced issue number, the exact PR number, the canonical PR URL (GitHub or GitLab), and (optionally) the published HEAD sha. The receipt is issue-bound.',args:{issueNumber:RecordIssuePublicationArgsSchema.shape.issueNumber,prNumber:RecordIssuePublicationArgsSchema.shape.prNumber,prUrl:RecordIssuePublicationArgsSchema.shape.prUrl,headSha:RecordIssuePublicationArgsSchema.shape.headSha},execute:executeRecordIssuePublication});init_zod();init_utils2();init_atomic_write();init_create_tool();var RecordIssueReproductionArgsSchema=exports_external.object({issueNumber:exports_external.number().int().min(1),performed:exports_external.boolean(),commands:exports_external.array(exports_external.string().min(1)).min(1).optional(),output_summary:exports_external.string().min(1).optional()}).strict();async function executeRecordIssueReproduction(args2,directory,context={}){let parsed=RecordIssueReproductionArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid reproduction receipt: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`});let{issueNumber,performed,commands,output_summary}=parsed.data;if(performed&&(!commands||commands.length===0||!output_summary))return JSON.stringify({success:!1,message:"A performed=true reproduction receipt requires non-empty commands and output_summary."});let receipt={performed,issueNumber,timestamp:new Date().toISOString()};if(commands)receipt.commands=commands;if(output_summary)receipt.output_summary=output_summary;if(context.sessionID?.trim())receipt.sessionId=context.sessionID.trim();let validatedPath;try{validatedPath=validateSwarmPath(directory,"reproduction.json")}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:"Failed to validate path"})}try{return await atomicWriteSwarmFile(validatedPath,JSON.stringify(receipt,null,2)),JSON.stringify({success:!0,issueNumber,performed,path:".swarm/reproduction.json",message:performed?`Reproduction receipt recorded for issue #${issueNumber}; the trace may now transition to PLAN.`:`Reproduction receipt recorded (performed=false) for issue #${issueNumber}; it does NOT satisfy the reproduction gate.`})}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:String(error93)})}}var record_issue_reproduction=createSwarmTool({description:"Record the reproduction outcome for the current traced issue. The /swarm issue --trace workflow requires reproduction evidence (or a typed --no-repro waiver) before it can leave localization and transition to PLAN. Call this with performed=true, the exact commands run, and a concrete output_summary after attempting a minimal reproduction; the receipt binds to issueNumber (and records the calling session) and is read by the issue-trace engine. A performed=true receipt MUST include commands and output_summary. A performed=false receipt is recorded but does NOT satisfy the gate.",args:{issueNumber:RecordIssueReproductionArgsSchema.shape.issueNumber,performed:RecordIssueReproductionArgsSchema.shape.performed,commands:RecordIssueReproductionArgsSchema.shape.commands,output_summary:RecordIssueReproductionArgsSchema.shape.output_summary},execute:executeRecordIssueReproduction});init_zod();init_utils2();init_atomic_write();init_create_tool();var HEX40=/^[0-9a-f]{40}$/,RecordMergeApprovalArgsSchema=exports_external.object({issueNumber:exports_external.number().int().min(1),prHeadSha:exports_external.string().regex(HEX40,"must be a 40-hex commit SHA"),finalCriticReviewedCommit:exports_external.string().regex(HEX40,"must be a 40-hex commit SHA"),userApprovalVerbatim:exports_external.string().trim().min(1).max(8000)}).strict();async function executeRecordMergeApproval(args2,directory,context={}){let parsed=RecordMergeApprovalArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid merge-approval receipt: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`});let data=parsed.data;if(data.prHeadSha!==data.finalCriticReviewedCommit)return JSON.stringify({success:!1,message:"Merge-approval binding failed: prHeadSha must equal finalCriticReviewedCommit (the final critic approval must be bound to the exact PR head)."});let receipt={issueNumber:data.issueNumber,prHeadSha:data.prHeadSha,finalCriticReviewedCommit:data.finalCriticReviewedCommit,userApprovalVerbatim:data.userApprovalVerbatim,timestamp:new Date().toISOString()};if(context.sessionID?.trim())receipt.sessionId=context.sessionID.trim();let validatedPath;try{validatedPath=validateSwarmPath(directory,"merge-approval.json")}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:"Failed to validate path"})}try{return await atomicWriteSwarmFile(validatedPath,JSON.stringify(receipt,null,2)),JSON.stringify({success:!0,issueNumber:data.issueNumber,path:".swarm/merge-approval.json",message:`Merge approval recorded for issue #${data.issueNumber}, bound to PR head ${data.prHeadSha}. The approval is captured verbatim for audit; the merge itself is human-enforced and this plugin neither drives nor certifies it.`})}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:String(error93)})}}var record_merge_approval=createSwarmTool({description:"Record the human merge approval for the current traced issue (issue #2564): prHeadSha and finalCriticReviewedCommit must be the same 40-hex SHA (the final critic approval bound to the exact PR head), and userApprovalVerbatim is the user approval quoted verbatim. The receipt is recorded for audit only — the merge stays human-enforced and the plugin never certifies or drives it.",args:{issueNumber:RecordMergeApprovalArgsSchema.shape.issueNumber,prHeadSha:RecordMergeApprovalArgsSchema.shape.prHeadSha,finalCriticReviewedCommit:RecordMergeApprovalArgsSchema.shape.finalCriticReviewedCommit,userApprovalVerbatim:RecordMergeApprovalArgsSchema.shape.userApprovalVerbatim},execute:executeRecordMergeApproval});init_zod();init_utils2();init_atomic_write();init_create_tool();var DispositionSchema=exports_external.object({ref:exports_external.string().trim().min(1).max(500),disposition:exports_external.enum(["FIX","FALSE_POSITIVE","OUT_OF_CLASS","DEFERRED_WITH_USER_APPROVAL"]),note:exports_external.string().trim().max(1000).optional()}).strict(),GuardrailSchema=exports_external.object({kind:exports_external.enum(["lint-static-analysis","type-level","runtime-assertion","ci-check","documented-invariant-plus-regression-test"]),description:exports_external.string().trim().min(8).max(2000),proof:exports_external.string().trim().min(8).max(4000)}).strict(),RelatedProblemSchema=exports_external.object({ref:exports_external.string().trim().min(1).max(500),note:exports_external.string().trim().max(1000).optional()}).strict(),RecordRecurrenceSweepArgsSchema=exports_external.object({issueNumber:exports_external.number().int().min(1),defectClass:exports_external.string().trim().min(1).max(1000),justification:exports_external.string().trim().min(1).max(1000).optional(),predicates:exports_external.array(exports_external.string().trim().min(1).max(500)).min(1).max(32).optional(),dispositions:exports_external.array(DispositionSchema).min(1).max(200).optional(),guardrail:GuardrailSchema.optional(),relatedProblems:exports_external.array(RelatedProblemSchema).min(1).max(200)}).strict();async function executeRecordRecurrenceSweep(args2,directory,context={}){let parsed=RecordRecurrenceSweepArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid recurrence sweep receipt: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`});let data=parsed.data,noDefectClass=data.defectClass==="no defect class";if(noDefectClass){if(!data.justification)return JSON.stringify({success:!1,message:'The "no defect class" fast path requires a one-line justification.'})}else if(!data.predicates||data.predicates.length===0||!data.dispositions||data.dispositions.length===0||!data.guardrail)return JSON.stringify({success:!1,message:"A defect-class sweep requires search predicates, a non-empty disposition for every hit (at least one — the original defect site itself, dispositioned FIX), and a guardrail with proof it catches the original defect. An empty dispositions array is indistinguishable from a sweep that never ran."});let receipt={issueNumber:data.issueNumber,defectClass:data.defectClass,timestamp:new Date().toISOString()};if(data.justification)receipt.justification=data.justification;if(data.predicates)receipt.predicates=data.predicates;if(data.dispositions)receipt.dispositions=data.dispositions;if(data.guardrail)receipt.guardrail=data.guardrail;if(receipt.relatedProblems=data.relatedProblems,context.sessionID?.trim())receipt.sessionId=context.sessionID.trim();let validatedPath;try{validatedPath=validateSwarmPath(directory,"recurrence-sweep.json")}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:"Failed to validate path"})}try{return await atomicWriteSwarmFile(validatedPath,JSON.stringify(receipt,null,2)),JSON.stringify({success:!0,issueNumber:data.issueNumber,path:".swarm/recurrence-sweep.json",message:noDefectClass?`Recurrence sweep recorded for issue #${data.issueNumber} (no defect class fast path).`:`Recurrence sweep recorded for issue #${data.issueNumber}; the trace may now satisfy its recurrence gate.`})}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:String(error93)})}}var record_recurrence_sweep=createSwarmTool({description:'Record the recurrence sweep for the current traced issue (issue #2131 residual B; widened in #2564 and #2600). The /swarm issue --trace workflow will not hand off to commit-pr until this receipt exists. Supply relatedProblems (the Phase 1 related-problems sweep results — at least one {ref, note?} entry) plus, for a real defect class: defectClass (one-sentence characterization), predicates (the exact search predicates), dispositions (non-empty — every hit as FIX / FALSE_POSITIVE / OUT_OF_CLASS / DEFERRED_WITH_USER_APPROVAL, including the original defect site), and a guardrail (kind + description + proof it catches the original defect). If the change corrects no incorrect behavior, use the literal defectClass "no defect class" with a one-line justification (relatedProblems still required).',args:{issueNumber:RecordRecurrenceSweepArgsSchema.shape.issueNumber,defectClass:RecordRecurrenceSweepArgsSchema.shape.defectClass,justification:RecordRecurrenceSweepArgsSchema.shape.justification,predicates:RecordRecurrenceSweepArgsSchema.shape.predicates,dispositions:RecordRecurrenceSweepArgsSchema.shape.dispositions,guardrail:RecordRecurrenceSweepArgsSchema.shape.guardrail,relatedProblems:RecordRecurrenceSweepArgsSchema.shape.relatedProblems},execute:executeRecordRecurrenceSweep});init_zod();import*as fs227 from"node:fs";init_utils2();init_file_locks();init_atomic_write();init_create_tool();var HEX402=/^[0-9a-f]{40}$/,TRACE_VALIDATION_PHASES2=["0","1","2","2.5","3","4","4.2","4.5","4.6","5"],ValidationEntrySchema=exports_external.object({phase:exports_external.enum(TRACE_VALIDATION_PHASES2),outcome:exports_external.enum(["pass","fail"]),reviewedCommit:exports_external.string().regex(HEX402,"must be a 40-hex commit SHA"),treeId:exports_external.string().regex(HEX402,"must be a 40-hex tree id")}).strict(),RecordTraceValidationArgsSchema=ValidationEntrySchema.extend({issueNumber:exports_external.number().int().min(1)}).strict();async function executeRecordTraceValidation(args2,directory,context={}){let parsed=RecordTraceValidationArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid trace-validation receipt: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`});let data=parsed.data,validatedPath;try{validatedPath=validateSwarmPath(directory,"trace-validation.json")}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:"Failed to validate path"})}try{let lockResult=await tryAcquireLock(directory,"trace-validation.json","trace-validation","trace-validation");if(!lockResult.acquired)return JSON.stringify({success:!1,message:"The trace-validation receipt is locked by another concurrent writer; no write was attempted. Re-run record_trace_validation for this phase once the other writer finishes."});try{let validations=[];try{let raw=await fs227.promises.readFile(validatedPath,"utf-8"),existing=JSON.parse(raw);if(typeof existing==="object"&&existing!==null&&Array.isArray(existing.validations))validations=existing.validations.filter((v)=>typeof v==="object"&&v!==null&&typeof v.phase==="string")}catch{}let entry={phase:data.phase,outcome:data.outcome,reviewedCommit:data.reviewedCommit,treeId:data.treeId,timestamp:new Date().toISOString()},idx=validations.findIndex((v)=>v.phase===data.phase);if(idx===-1)validations.push(entry);else validations[idx]=entry;let receipt={issueNumber:data.issueNumber,timestamp:new Date().toISOString(),validations};if(context.sessionID?.trim())receipt.sessionId=context.sessionID.trim();await atomicWriteSwarmFile(validatedPath,JSON.stringify(receipt,null,2));let allGreen=await traceValidationReceiptExists(directory,data.issueNumber);return JSON.stringify({success:!0,issueNumber:data.issueNumber,path:".swarm/trace-validation.json",allGreen,message:allGreen?`Validator receipt recorded for issue #${data.issueNumber} phase ${data.phase} (${data.outcome}); every recorded phase is green.`:`Validator receipt recorded for issue #${data.issueNumber} phase ${data.phase} (${data.outcome}), but at least one recorded phase is failing — fix and re-record that phase as a pass before handoff.`})}finally{try{await lockResult.lock._release?.()}catch{}}}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:String(error93)})}}var record_trace_validation=createSwarmTool({description:"Record one per-phase trace-check.sh validator outcome for the current traced issue (issue #2564): the phase (v3 enum 0..5 incl. 2.5/4.2/4.5/4.6), the outcome (pass or fail), and the exact reviewedCommit and treeId the validator reported. Re-running a phase replaces its entry. The /swarm issue --trace workflow will not hand off to commit-pr while any recorded phase is failing or none is recorded. The receipt write is serialized by a per-file receipt lock, and the response's allGreen field mirrors the gate reader's verdict on the persisted receipt (advisory for the calling agent — the reducer always recomputes it independently).",args:{issueNumber:RecordTraceValidationArgsSchema.shape.issueNumber,phase:RecordTraceValidationArgsSchema.shape.phase,outcome:RecordTraceValidationArgsSchema.shape.outcome,reviewedCommit:RecordTraceValidationArgsSchema.shape.reviewedCommit,treeId:RecordTraceValidationArgsSchema.shape.treeId},execute:executeRecordTraceValidation});init_zod();init_schema();init_gate_evidence();init_manager();init_path_identity();init_state();init_stage_a_repair();import*as fs228 from"node:fs";import*as path370 from"node:path";async function forceRecoverReworkTask(directory,sessionID,options){let session=ensureAgentSession(sessionID,void 0,directory);if(!session||!session.agentName||stripKnownSwarmPrefix(session.agentName)!=="architect")throw Error("RECOVER_REWORK_ARCHITECT_REQUIRED: recover_rework_task requires an active architect session. The rework escape hatch is architect-only; a coder/reviewer/test_engineer cannot self-unblock a task.");let taskId=typeof options.taskId==="string"?options.taskId.trim():"";if(!taskId)throw Error('RECOVER_REWORK_UNKNOWN_TASK: recover_rework_task requires the exact plan task id (e.g. "1.1").');let plan=await loadPlanJsonOnly(directory);if(!plan){let planPath=path370.join(directory,".swarm","plan.json");if(fs228.existsSync(planPath))throw Error("PLAN_CORRUPT: .swarm/plan.json exists but could not be parsed (corrupt or schema-invalid). Repair or re-save the plan before recovering a rework_required task.");throw Error("PLAN_NOT_FOUND: no .swarm/plan.json — cannot recover a rework_required "+"task without a plan. Save a plan first.")}if(!new Set(plan.phases.flatMap((phase)=>phase.tasks.map((task2)=>task2.id))).has(taskId))throw Error(`RECOVER_REWORK_UNKNOWN_TASK: task ${taskId} is not in the current plan. Refusing to recover a foreign task id.`);let evidenceRead=await readTaskEvidenceState(directory,taskId);if(evidenceRead.kind==="unparseable")throw Error(`RECOVER_REWORK_EVIDENCE_CORRUPT: the workflow evidence file for task ${taskId} exists but could not be parsed (${evidenceRead.evidencePath}). Repair the evidence first (repair_gate_evidence or /swarm doctor); recovery cannot classify a corrupt evidence state.`);let evidence2=evidenceRead.kind==="ok"?evidenceRead.evidence:null,workflow=getTaskWorkflowSnapshot(evidence2);if(!evidence2||!workflow.authoritative)throw Error(`RECOVER_REWORK_NO_WORKFLOW: no durable task workflow evidence exists for task ${taskId} — there is no rework state to recover.`);if(workflow.state!=="rework_required")throw Error(`RECOVER_REWORK_STATE_REQUIRED: task ${taskId} is at ${workflow.state}, not rework_required. This recovery applies only to a task whose Stage B verdict moved it to rework_required without a code change. From coder_delegated, run pre_check_batch; for a genuine code defect, delegate the coder to repair it first.`);let wedgeMs=Date.parse(workflow.updatedAt);if(!Number.isFinite(wedgeMs))throw Error(`RECOVER_REWORK_GREEN_PRECHECK_REQUIRED: cannot prove pre-check recency (workflow updatedAt "${workflow.updatedAt}" is not a parseable timestamp — the evidence file for task ${taskId} is likely corrupt). Repair the evidence (repair_gate_evidence or /swarm doctor); re-running pre_check_batch cannot fix an unparseable timestamp.`);let greenness=await hasGreenPostSettlementPreCheck(directory,wedgeMs);if(!greenness.green){let sastHint=greenness.reason==="no_pre_check_bundles"?" Note: if gates.sast_scan.enabled is false, no sast_scan bundle is ever persisted and this recovery is unavailable by design — enable gates.sast_scan.enabled and run sast_scan, or use the coder repair loop.":"";throw Error(`RECOVER_REWORK_GREEN_PRECHECK_REQUIRED: refusing to mark Stage A passed without proof (${greenness.reason}). `+"The bar is a green secretscan AND sast_scan evidence pair newer than the failing verdict — normally provided by a fresh pre_check_batch run (bundle proof is global, not correlated to the task's changed files)."+sastHint)}let sanitizedReason=typeof options.reason==="string"&&options.reason.trim().length>0?sanitizeDiagnosticText(options.reason.trim(),500):void 0,recordedAt=new Date().toISOString(),transitionId=`rework-recovery:${taskId}:gen${workflow.generation}`,updated=await transitionTaskWorkflowEvidence(directory,taskId,{type:"stage_a_passed",supervisedRecovery:!0,expectedGeneration:workflow.generation,transitionId}),updatedWorkflow=getTaskWorkflowSnapshot(updated),auditEventRecorded=await appendStageARepairEvent(directory,{action:"rework_recovered",taskId,transitionId,generation:workflow.generation,sessionId:sessionID,...sanitizedReason?{reason:sanitizedReason}:{}});return{taskId,generation:updatedWorkflow.generation,state:updatedWorkflow.state,transitionId,recordedAt,auditEventRecorded}}init_create_tool();var RecoverReworkTaskArgsSchema=exports_external.object({task_id:exports_external.string().trim().min(1).max(64).describe('Exact plan task id of the rework_required task (e.g. "1.1"). Must exist in the current plan and have durable workflow evidence at state rework_required.'),reason:exports_external.string().trim().min(1).max(500).describe('Why the Stage B verdict did not require a code change (e.g. "test_engineer returned SKIPPED for a tool-argument error while pytest passes"). Audited to .swarm/events.jsonl.')}).strict();async function executeRecoverReworkTask(args2,directory,context={}){let parsed=RecoverReworkTaskArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid recover_rework_task call: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`});if(!context.sessionID?.trim())return JSON.stringify({success:!1,message:"recover_rework_task requires an active sessionID"});try{let summary=await forceRecoverReworkTask(directory,context.sessionID,{taskId:parsed.data.task_id,reason:parsed.data.reason}),auditNote=summary.auditEventRecorded?"The recovery is audited to .swarm/events.jsonl (stage_a_repair action rework_recovered).":"WARNING: the audit event could NOT be appended to .swarm/events.jsonl (see the plugin log); the durable workflow evidence still records the supervised recovery via the rework-recovery: transition id.";return JSON.stringify({success:!0,task_id:summary.taskId,generation:summary.generation,state:summary.state,transition_id:summary.transitionId,recorded_at:summary.recordedAt,audit_event_recorded:summary.auditEventRecorded,method:"supervised_recovery",message:`Task ${summary.taskId} recovered from rework_required: a supervised stage_a_passed was written at generation ${summary.generation} (transition id `+summary.transitionId+"). Reviewer/test_engineer dispatch is permitted again — re-run the Stage B gates that the failed verdict cleared. "+auditNote+" Use it ONLY when the Stage B verdict did not require a code change; a genuine defect still needs the coder repair loop."})}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:String(error93)})}}var recover_rework_task=createSwarmTool({description:"Recover a task wedged at rework_required when the Stage B verdict did NOT require a code change (issue #2755): writes a supervised stage_a_passed for the current generation so reviewer/test_engineer can be re-dispatched, without re-running the coder. Requires the exact plan task id, an active architect session, durable workflow state exactly rework_required, and green pre-check proof: green secretscan AND sast_scan evidence bundles newer than the failing verdict (normally from a fresh pre_check_batch run; bundle recency is global, not file-correlated; projects with SAST disabled cannot use this path). Fail-closed otherwise; the mechanical stage_a_passed path still requires an accepted coder mutation. A reason is required and audited to .swarm/events.jsonl (stage_a_repair action rework_recovered). Prefer the coder repair loop when the code actually has a defect.",args:{task_id:RecoverReworkTaskArgsSchema.shape.task_id,reason:RecoverReworkTaskArgsSchema.shape.reason},execute:executeRecoverReworkTask});init_zod();init_schema();init_gate_evidence();init_path_identity();init_state();init_coder_settlement();init_session_view();init_stage_a_repair();async function recoverStageATaskSupervised(directory,sessionID,options){let session=ensureAgentSession(sessionID,void 0,directory);if(!session||!session.agentName||stripKnownSwarmPrefix(session.agentName)!=="architect")throw Error("RECOVER_STAGE_A_ARCHITECT_REQUIRED: recover_stage_a_task requires an active architect session. The settlement-backed Stage A escape hatch is architect-only; a coder/reviewer/test_engineer cannot self-unblock a task.");let taskId=typeof options.taskId==="string"?options.taskId.trim():"";if(!taskId)throw Error('RECOVER_STAGE_A_UNKNOWN_TASK: recover_stage_a_task requires the exact task id of the settlement-wedged task (e.g. "1.1").');let sanitizedReason=typeof options.reason==="string"&&options.reason.trim().length>0?sanitizeDiagnosticText(options.reason.trim(),500):void 0;if(!sanitizedReason)throw Error("RECOVER_STAGE_A_REASON_REQUIRED: recover_stage_a_task requires a reason describing why the settlement-backed recovery is justified; it is audited to .swarm/events.jsonl.");let evidenceRead=await readTaskEvidenceState(directory,taskId);if(evidenceRead.kind==="unparseable")throw Error(`RECOVER_STAGE_A_EVIDENCE_CORRUPT: the workflow evidence file for task ${taskId} exists but could not be parsed (${evidenceRead.evidencePath}). Repair the evidence first (repair_gate_evidence or /swarm doctor); recovery cannot classify a corrupt evidence state.`);let evidence2=evidenceRead.kind==="ok"?evidenceRead.evidence:null,workflow=getTaskWorkflowSnapshot(evidence2);if(!evidence2||!workflow.authoritative)throw Error(`RECOVER_STAGE_A_NO_WORKFLOW: no durable task workflow evidence exists for task ${taskId} — there is no settlement wedge to recover.`);if(workflow.state==="pre_check_passed"||workflow.state==="reviewer_run"||workflow.state==="tests_run"){if(isStageARecoveredState(workflow.state)&&shouldRefreshStageARecoveryView(session.taskWorkflowStates.get(taskId),workflow.state))applySessionWorkflowView(session,taskId,workflow);return{taskId,generation:workflow.generation,state:workflow.state,transitionId:`stage-a-supervised:${taskId}:noop`,recordedAt:new Date().toISOString(),alreadyRecovered:!0,auditEventRecorded:!1}}if(workflow.state!=="idle"&&workflow.state!=="blocked")throw Error(`RECOVER_STAGE_A_STATE_REQUIRED: task ${taskId} is at ${workflow.state}, not idle/blocked. This recovery applies only to the settlement-backed wedge (a COMMITTED accepted coder settlement while the workflow drifted to idle or blocked). From coder_delegated, run pre_check_batch or /swarm recover; from rework_required without a code change, use recover_rework_task.`);let{states:walStates}=await listCoderSettlementWalStates(directory),settledAfterMs=latestCommittedAcceptedSettlementMs(taskId,walStates);if(settledAfterMs===null)throw Error(`RECOVER_STAGE_A_SETTLEMENT_REQUIRED: refusing to recover task ${taskId} — no COMMITTED accepted coder settlement exists for it. `+"The settlement receipt is what distinguishes this wedge from a not-yet-started or deliberately stopped task; recovery without it would fabricate Stage A justification. Background-dispatched coder tasks never write a settlement WAL and cannot use this path.");let greenness=await hasGreenPostSettlementPreCheck(directory,settledAfterMs);if(!greenness.green){let sastHint=greenness.reason==="no_pre_check_bundles"?" Note: if gates.sast_scan.enabled is false, no sast_scan bundle is ever persisted and this recovery is unavailable by design — enable gates.sast_scan.enabled and run sast_scan, or use the coder repair loop.":"";throw Error(`RECOVER_STAGE_A_GREEN_PRECHECK_REQUIRED: refusing to mark Stage A passed without proof (${greenness.reason}). `+"The bar is a green secretscan AND sast_scan evidence pair newer than the settlement commit — normally provided by a fresh pre_check_batch run (bundle proof is global, not correlated to the task's changed files)."+sastHint)}let recordedAt=new Date().toISOString(),transitionId=`stage-a-supervised:${taskId}:${workflow.generation}`,updated=await transitionTaskWorkflowEvidence(directory,taskId,{type:"stage_a_passed",settlementRecovery:!0,expectedGeneration:workflow.generation,transitionId}),updatedWorkflow=getTaskWorkflowSnapshot(updated);if(isStageARecoveredState(updatedWorkflow.state)){if(shouldRefreshStageARecoveryView(session.taskWorkflowStates.get(taskId),updatedWorkflow.state))applySessionWorkflowView(session,taskId,updatedWorkflow)}let auditEventRecorded=await appendStageARepairEvent(directory,{action:"repaired",via:"recover_stage_a_task",taskId,transitionId,generation:workflow.generation,settlementRecovery:!0,predecessorTransitionId:workflow.lastTransitionId??null,sessionId:sessionID,reason:sanitizedReason});return{taskId,generation:updatedWorkflow.generation,state:updatedWorkflow.state,transitionId,recordedAt,alreadyRecovered:!1,auditEventRecorded}}init_create_tool();var RecoverStageATaskArgsSchema=exports_external.object({task_id:exports_external.string().trim().min(1).max(64).describe('Exact task id of the settlement-wedged task (e.g. "1.1"). Must have durable workflow evidence at state idle or blocked, a COMMITTED accepted coder settlement, and green post-settlement pre-check proof.'),reason:exports_external.string().trim().min(1).max(500).describe('Why the settlement-backed recovery is justified (e.g. "settlement COMMITTED and pre_check_batch green but stage_a_passed never fired; force-repair cleared the proofs"). Audited to .swarm/events.jsonl.')}).strict();async function executeRecoverStageATask(args2,directory,context={}){let parsed=RecoverStageATaskArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid recover_stage_a_task call: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`});if(!context.sessionID?.trim())return JSON.stringify({success:!1,message:"recover_stage_a_task requires an active sessionID"});try{let summary=await recoverStageATaskSupervised(directory,context.sessionID,{taskId:parsed.data.task_id,reason:parsed.data.reason});if(summary.alreadyRecovered)return JSON.stringify({success:!0,task_id:summary.taskId,generation:summary.generation,state:summary.state,already_recovered:!0,message:`Task ${summary.taskId} already has Stage A recorded (state ${summary.state}, generation ${summary.generation}) — nothing to recover.`});let auditNote=summary.auditEventRecorded?"The recovery is audited to .swarm/events.jsonl (stage_a_repair action repaired, via recover_stage_a_task).":"WARNING: the audit event could NOT be appended to .swarm/events.jsonl (see the plugin log); the durable workflow evidence still records the settlement-backed recovery via the stage-a-supervised: transition id and the settlementRecovery marker.";return JSON.stringify({success:!0,task_id:summary.taskId,generation:summary.generation,state:summary.state,transition_id:summary.transitionId,recorded_at:summary.recordedAt,audit_event_recorded:summary.auditEventRecorded,method:"settlement_recovery",message:`Task ${summary.taskId} recovered from the settlement wedge: a settlement-backed stage_a_passed was written at generation ${summary.generation} (transition id `+summary.transitionId+"). Reviewer/test_engineer dispatch is permitted again — run the Stage B gates the task still needs. "+auditNote+" Use it ONLY when a COMMITTED accepted settlement and green post-settlement pre-check proof already justify Stage A; it never re-runs the coder and never edits gate evidence."})}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:String(error93)})}}var recover_stage_a_task=createSwarmTool({description:"Recover a task wedged in the settlement-backed Stage A deadlock (issue #2828): workflow at idle or blocked while a COMMITTED accepted coder settlement and green post-settlement pre-check proof (green secretscan AND sast_scan evidence newer than the settlement commit) still justify Stage A — the shape where stage_a_passed never fired, a force-repair cleared the proofs, and every other recovery path refuses. Writes a settlement-backed stage_a_passed for the current generation so reviewer/test_engineer can be dispatched, without re-running the coder and without editing gate evidence. Requires the exact task id (bound by its durable workflow evidence and settlement WAL — deliberately no plan-membership precondition, mirroring the /swarm recover scan), an active architect session, a reason (audited), and durable workflow evidence at exactly idle/blocked. Fail-closed otherwise (RECOVER_STAGE_A_* errors); the mechanical stage_a_passed path still requires an accepted coder mutation or the #2665 live_wedge scan.",args:{task_id:RecoverStageATaskArgsSchema.shape.task_id,reason:RecoverStageATaskArgsSchema.shape.reason},execute:executeRecoverStageATask});init_zod();init_schema();init_gate_evidence();init_utils2();init_manager();init_state();init_project_boundary();init_swarm_artifact_cache();init_task_id();init_task_file();init_task_gate_requirements();init_gate_evidence();import{createHash as createHash120,randomUUID as randomUUID48}from"node:crypto";import*as fs229 from"node:fs";import*as path371 from"node:path";var TASK_GATE_EVIDENCE_QUARANTINE_DIR=path371.join("evidence","task-gate-quarantine"),MAX_TASK_GATE_EVIDENCE_BYTES=262144,MAX_TASK_GATE_EVIDENCE_QUARANTINE_FILES=32,MAX_TASK_GATE_EVIDENCE_QUARANTINE_BYTES=12582912,MAX_TASK_GATE_EVIDENCE_QUARANTINE_DIRECTORY_ENTRIES=128,MAX_TASK_GATE_EVIDENCE_QUARANTINE_RECORD_BYTES=786432,TASK_GATE_EVIDENCE_QUARANTINE_SCHEMA_VERSION=1,GENERIC_REPAIR_REASONS=new Set(["fix","repair","test","debug","unknown","n/a","na","none"]);function isQuarantinableTaskEvidenceRead(read){return read.status==="corrupt"||read.status==="valid"}function sha25614(bytes){return createHash120("sha256").update(bytes).digest("hex")}function normalizeRepairReason(reason){let normalized=reason.trim().replace(/\s+/g," ");if(normalized.length<12)throw Error("TASK_GATE_EVIDENCE_REASON_REQUIRED: repair_gate_evidence requires a substantive reason of at least 12 characters.");if(GENERIC_REPAIR_REASONS.has(normalized.toLowerCase()))throw Error("TASK_GATE_EVIDENCE_REASON_REQUIRED: repair_gate_evidence requires a substantive reason, not a placeholder.");return normalized}function canonicalizeRepairRoot(directory){let requestedRoot=path371.resolve(directory),requestedStat=fs229.lstatSync(requestedRoot);if(requestedStat.isSymbolicLink()||!requestedStat.isDirectory())throw Error("TASK_GATE_EVIDENCE_ROOT_UNSAFE: repair_gate_evidence requires a canonical project root directory, not a symlink, junction, reparse point, or non-directory path.");let canonicalRoot2=fs229.realpathSync(requestedRoot);return assertProjectRoot(canonicalRoot2),canonicalRoot2}function assertExistingRegularPath(root,relativePath2){let segments=relativePath2.replace(/\\/g,"/").split("/").filter(Boolean),cursor=root;for(let segment of segments){if(cursor=path371.join(cursor,segment),!fs229.existsSync(cursor))return;if(fs229.lstatSync(cursor).isSymbolicLink())throw Error(`TASK_GATE_EVIDENCE_PATH_UNSAFE: ${relativePath2} contains a symlink, junction, or reparse point.`)}}function taskEvidenceFilePath(directory,taskId){let relativePath2=taskEvidenceRelPath(taskId);return assertExistingRegularPath(directory,".swarm"),assertExistingRegularPath(directory,path371.join(".swarm","evidence")),assertExistingRegularPath(directory,path371.join(".swarm",relativePath2)),validateSwarmPath(directory,relativePath2)}function readTaskEvidenceForRepair(directory,taskId){let filePath=taskEvidenceFilePath(directory,taskId),pathStat;try{pathStat=fs229.lstatSync(filePath)}catch(error93){if(error93.code==="ENOENT")return{status:"missing"};return{status:"unreadable",filePath,bytes:Buffer.alloc(0),sha256:sha25614(""),error:error93}}if(pathStat.isSymbolicLink()||!pathStat.isFile())return{status:"unreadable",filePath,bytes:Buffer.alloc(0),sha256:sha25614(""),error:Error("TASK_GATE_EVIDENCE_UNREADABLE: evidence path is not a regular file")};if(pathStat.size>MAX_TASK_GATE_EVIDENCE_BYTES)return{status:"oversized",filePath,bytes:Buffer.alloc(0),sha256:sha25614(""),error:Error(`TASK_GATE_EVIDENCE_OVERSIZED: ${pathStat.size} bytes exceeds ${MAX_TASK_GATE_EVIDENCE_BYTES}`)};let descriptor=fs229.openSync(filePath,fs229.constants.O_RDONLY|(fs229.constants.O_NOFOLLOW??0));try{let openedStat=fs229.fstatSync(descriptor);if(!openedStat.isFile()||openedStat.dev!==pathStat.dev||openedStat.ino!==pathStat.ino)return{status:"unreadable",filePath,bytes:Buffer.alloc(0),sha256:sha25614(""),error:Error("TASK_GATE_EVIDENCE_UNREADABLE: evidence changed while being opened")};let bytes=fs229.readFileSync(descriptor);if(bytes.byteLength>MAX_TASK_GATE_EVIDENCE_BYTES)return{status:"oversized",filePath,bytes:Buffer.alloc(0),sha256:sha25614(""),error:Error(`TASK_GATE_EVIDENCE_OVERSIZED: ${bytes.byteLength} bytes exceeds ${MAX_TASK_GATE_EVIDENCE_BYTES}`)};let digest5=sha25614(bytes);try{let evidence2=parseTaskEvidence(bytes.toString("utf8"),taskId);return{status:"valid",filePath,bytes,sha256:digest5,evidence:evidence2,generation:evidence2.workflow?.generation}}catch(error93){return{status:"corrupt",filePath,bytes,sha256:digest5,error:error93}}}finally{try{fs229.closeSync(descriptor)}catch{}}}function taskGateEvidenceQuarantinePath(directory,taskId,digest5){return validateSwarmPath(directory,path371.join(TASK_GATE_EVIDENCE_QUARANTINE_DIR,`${taskId}.${digest5}.v${TASK_GATE_EVIDENCE_QUARANTINE_SCHEMA_VERSION}.json`))}function parseErrorMetadata(error93){if(!error93)return null;return{name:error93.name||"Error",message:error93.message||String(error93),code:typeof error93.code==="string"?error93.code:null}}function parseQuarantineRecord(raw){try{let parsed=JSON.parse(raw);if(parsed?.schemaVersion!==TASK_GATE_EVIDENCE_QUARANTINE_SCHEMA_VERSION||typeof parsed.taskId!=="string"||typeof parsed.recordedAt!=="string"||typeof parsed.reason!=="string"||typeof parsed.original?.path!=="string"||typeof parsed.original?.sha256!=="string"||typeof parsed.content?.bytes!=="string"||parsed.content?.encoding!=="base64")return null;return parsed}catch{return null}}function buildQuarantineRecord(taskId,read,reason,context,receiptGeneration){let agentName=context?.sessionID!=null?swarmState.activeAgent.get(context.sessionID)??swarmState.agentSessions.get(context.sessionID)?.agentName??null:null;return{schemaVersion:TASK_GATE_EVIDENCE_QUARANTINE_SCHEMA_VERSION,taskId,recordedAt:new Date().toISOString(),reason,caller:{sessionId:context?.sessionID?.trim()||null,messageId:context?.messageID?.trim()||null,agentName},original:{path:read.filePath,sha256:read.sha256,sizeBytes:read.bytes.byteLength,status:read.status,observedGeneration:read.generation??null,receiptGeneration,requirementsState:read.evidence?.requirements_state??null},parseError:parseErrorMetadata(read.error),content:{encoding:"base64",bytes:read.bytes.toString("base64")}}}async function quarantineTaskEvidenceBytes(directory,taskId,read,reason,context,receiptGeneration){let digest5=read.sha256,quarantineDir=validateSwarmPath(directory,TASK_GATE_EVIDENCE_QUARANTINE_DIR);await fs229.promises.mkdir(quarantineDir,{recursive:!0});let dirStat=await fs229.promises.lstat(quarantineDir);if(dirStat.isSymbolicLink()||!dirStat.isDirectory())throw Error("TASK_GATE_EVIDENCE_QUARANTINE_UNREADABLE: quarantine is not a regular directory");let target=taskGateEvidenceQuarantinePath(directory,taskId,digest5),record3=buildQuarantineRecord(taskId,read,reason,context,receiptGeneration),serialized3=JSON.stringify(record3,null,2),serializedBytes=Buffer.byteLength(serialized3,"utf8");if(serializedBytes>MAX_TASK_GATE_EVIDENCE_QUARANTINE_RECORD_BYTES)throw Error("TASK_GATE_EVIDENCE_QUARANTINE_FULL: quarantine payload exceeds the bounded record size limit");let reconcileExisting=async()=>{let existingStat;try{existingStat=await fs229.promises.lstat(target)}catch(error93){if(error93.code==="ENOENT")return!1;throw error93}if(existingStat.isSymbolicLink()||!existingStat.isFile())throw Error("TASK_GATE_EVIDENCE_QUARANTINE_MISMATCH: existing quarantine path is not a regular immutable record");let existingRaw=await fs229.promises.readFile(target,"utf8"),existingRecord=parseQuarantineRecord(existingRaw);if(existingRecord&&existingRecord.taskId===taskId&&existingRecord.original.path===read.filePath&&existingRecord.original.sha256===read.sha256&&existingRecord.content.bytes===read.bytes.toString("base64"))return!0;throw Error("TASK_GATE_EVIDENCE_QUARANTINE_MISMATCH: existing quarantine record does not match the repaired evidence source")};if(await reconcileExisting())return{digest:digest5,filePath:target};let count4=0,totalBytes=0,scanned=0,handle=await fs229.promises.opendir(quarantineDir,{bufferSize:16});try{for await(let entry of handle){if(scanned+=1,scanned>MAX_TASK_GATE_EVIDENCE_QUARANTINE_DIRECTORY_ENTRIES)throw Error("TASK_GATE_EVIDENCE_QUARANTINE_FULL: too many quarantine entries");if(!entry.isFile()||!/^[0-9.]+\.[a-f0-9]{64}\.v1\.json$/.test(entry.name))continue;count4+=1;let candidate2=path371.join(quarantineDir,entry.name),candidateStat=await fs229.promises.lstat(candidate2);if(candidateStat.isSymbolicLink()||!candidateStat.isFile())throw Error("TASK_GATE_EVIDENCE_QUARANTINE_UNREADABLE: invalid quarantine artifact");if(totalBytes+=candidateStat.size,count4>=MAX_TASK_GATE_EVIDENCE_QUARANTINE_FILES||totalBytes+serializedBytes>MAX_TASK_GATE_EVIDENCE_QUARANTINE_BYTES)throw Error("TASK_GATE_EVIDENCE_QUARANTINE_FULL: quarantine retention limit reached")}}finally{try{await handle.close()}catch{}}let tempPath=path371.join(quarantineDir,`.pending.${process.pid}.${randomUUID48()}.json`),fileHandle;try{fileHandle=await fs229.promises.open(tempPath,"wx"),await fileHandle.writeFile(serialized3,"utf8"),await fileHandle.sync(),await fileHandle.close(),fileHandle=void 0,invalidateCachedArtifact(tempPath),await fs229.promises.link(tempPath,target),invalidateCachedArtifact(target)}catch(error93){if(error93.code!=="EEXIST")throw error93;if(await reconcileExisting())return{digest:digest5,filePath:target};throw error93}finally{await fileHandle?.close().catch(()=>{return}),await fs229.promises.unlink(tempPath).catch(()=>{return})}return{digest:digest5,filePath:target}}function buildRepairTransitionId(taskId,source){return`repair_gate_evidence:${taskId}:${source.slice(0,32)}`}function withoutLegacyReconstructionGate(gates){return[...new Set(gates.filter((gate)=>gate!==TASK_GATE_REQUIREMENTS_RECONSTRUCTION_SENTINEL))].sort()}function hasLegacyReconstructionGate(gates){return gates.includes(TASK_GATE_REQUIREMENTS_RECONSTRUCTION_SENTINEL)}function buildKnownRepairedEvidence(taskId,receipt,generation,source){let requiredGates=withoutLegacyReconstructionGate(receipt.requiredGates);if(requiredGates.length!==receipt.requiredGates.length)throw Error("TASK_GATE_REQUIREMENTS_RECEIPT_TAINTED: legacy reconstruction markers cannot seed known requirements.");return{taskId,required_gates:requiredGates,gates:{},requirements_state:"known",test_engineer_exempt:receipt.testEngineerExempt??void 0,workflow:{schema:TASK_WORKFLOW_SCHEMA_MARKER,generation,state:"idle",retryCount:0,retryHistory:[],retryEpoch:0,lastOutcome:"repair_idle",lastTransitionId:buildRepairTransitionId(taskId,receipt.chainHash),updatedAt:new Date().toISOString()},repair_provenance:{source_sha256:source.sha256,source_generation:source.generation,requirements_receipt_hash:receipt.chainHash}}}function buildUnknownRepairedEvidence(taskId,requiredGates,seedGeneration,source,receiptHash){return{taskId,required_gates:withoutLegacyReconstructionGate(requiredGates),gates:{},requirements_state:"unknown",workflow:{schema:TASK_WORKFLOW_SCHEMA_MARKER,generation:seedGeneration,state:"idle",retryCount:0,retryHistory:[],retryEpoch:0,lastOutcome:"repair_idle",lastTransitionId:buildRepairTransitionId(taskId,"unknown"),updatedAt:new Date().toISOString()},repair_provenance:{source_sha256:source.sha256,source_generation:source.generation,requirements_receipt_hash:receiptHash}}}function canonicalizeTaskEvidence(taskId,evidence2){let validated=parseTaskEvidence(JSON.stringify({...evidence2,taskId}),taskId);return JSON.stringify(validated,null,2)}function isRepairWorkflowReset(taskId,workflow){return workflow!=null&&workflow.state==="idle"&&workflow.retryCount===0&&workflow.retryEpoch===0&&workflow.retryHistory.length===0&&workflow.lastOutcome==="repair_idle"&&typeof workflow.lastTransitionId==="string"&&workflow.lastTransitionId.startsWith(`repair_gate_evidence:${taskId}:`)}function isReceiptlessLegacySentinelReset(taskId,evidence2){return evidence2!=null&&isRepairWorkflowReset(taskId,evidence2.workflow)&&evidence2.requirements_state==="unknown"&&evidence2.required_gates.length===1&&evidence2.required_gates[0]===TASK_GATE_REQUIREMENTS_RECONSTRUCTION_SENTINEL&&Object.keys(evidence2.gates).length===0&&evidence2.repair_provenance!=null&&typeof evidence2.repair_provenance.source_sha256==="string"&&(evidence2.repair_provenance.source_generation===null||evidence2.repair_provenance.source_generation<evidence2.workflow.generation)&&evidence2.repair_provenance.requirements_receipt_hash===null}function isAlreadyRepairedEvidence(taskId,evidence2,receipt){if(!evidence2||!isRepairWorkflowReset(taskId,evidence2.workflow))return!1;if(Object.keys(evidence2.gates).length!==0)return!1;if(hasLegacyReconstructionGate(evidence2.required_gates))return!1;let receiptIsTainted=receipt!=null&&hasLegacyReconstructionGate(receipt.requiredGates);if(receipt&&!receiptIsTainted)return evidence2.requirements_state==="known"&&JSON.stringify(evidence2.required_gates)===JSON.stringify(receipt.requiredGates)&&evidence2.workflow.generation>receipt.generation&&(evidence2.test_engineer_exempt??null)===(receipt.testEngineerExempt??null)&&evidence2.repair_provenance?.requirements_receipt_hash===receipt.chainHash;if(!receipt||!receiptIsTainted)return!1;return evidence2.requirements_state==="unknown"&&evidence2.workflow.generation>=1&&evidence2.repair_provenance!=null&&evidence2.repair_provenance.requirements_receipt_hash===receipt.chainHash&&withoutLegacyReconstructionGate(receipt.requiredGates).every((gate)=>evidence2.required_gates.includes(gate))}function repairedEvidenceMatchesCas(evidence2,args2){let provenance=evidence2.repair_provenance;if(!provenance)return args2.expected_sha256==null&&args2.expected_generation==null;return(args2.expected_sha256==null||provenance.source_sha256===args2.expected_sha256)&&(args2.expected_generation==null||provenance.source_generation===args2.expected_generation)}function buildRepairNextActions(taskId,evidence2){if(evidence2.requirements_state==="known")return[`Delegate coder on task ${taskId} to produce a fresh accepted_mutation for the repaired evidence generation ${evidence2.workflow?.generation}.`,`Rerun Stage A for task ${taskId} until pre_check passes for the new generation.`,`Rerun Stage B gates [${evidence2.required_gates.join(", ")}] for task ${taskId} before attempting completion again.`];return[`Delegate coder on task ${taskId} to produce a fresh accepted mutation and regenerate authoritative required gates for a new exact-task generation.`,`Rerun Stage A for task ${taskId} after the new mutation is recorded.`,`Rerun the exact Stage B gates for task ${taskId} only after authoritative required gates are re-recorded; the idle recovery generation cannot complete directly.`]}function invalidateTaskEvidenceSessionFallbacks(taskId){for(let session of swarmState.agentSessions.values()){if(session.currentTaskId===taskId)session.currentTaskId=null;if(session.lastCoderDelegationTaskId===taskId)session.lastCoderDelegationTaskId=null;if(session.taskWorkflowStates?.delete(taskId),session.taskWorkflowCache?.delete(taskId),session.stageBCompletion?.delete(taskId),session.taskCouncilApproved?.delete(taskId),session.taskCouncilWorkflowGeneration?.delete(taskId),session.gateLog?.delete(taskId),session.partialGateWarningsIssuedForTask?.delete(taskId),session.completionGateWarnedForTask?.delete(taskId),session.lastGateFailure?.taskId===taskId)session.lastGateFailure=null}}async function repairTaskGateEvidence(args2,directory,context){assertStrictTaskId(args2.task_id);let normalizedReason=normalizeRepairReason(args2.reason),canonicalDirectory=canonicalizeRepairRoot(directory);if(!(await loadPlan(canonicalDirectory))?.phases.flatMap((phase)=>phase.tasks).find((candidate2)=>candidate2.id===args2.task_id))return{success:!1,message:`TASK_GATE_EVIDENCE_TASK_MISSING: ${args2.task_id} is not present in the loaded plan`,errors:[`Task ${args2.task_id} is not present in .swarm/plan.json.`]};return withTaskEvidenceLock(canonicalDirectory,args2.task_id,"repair_gate_evidence",async()=>{let read=readTaskEvidenceForRepair(canonicalDirectory,args2.task_id),latestReceipt=(await readTaskGateRequirementsReceipts(canonicalDirectory,args2.task_id)).at(-1),evidenceHasLegacyMarker=read.status==="valid"&&read.evidence!=null&&hasLegacyReconstructionGate(read.evidence.required_gates),receiptHasLegacyMarker=latestReceipt!=null&&hasLegacyReconstructionGate(latestReceipt.requiredGates);if(read.status==="valid"&&isAlreadyRepairedEvidence(args2.task_id,read.evidence,latestReceipt)){if(!repairedEvidenceMatchesCas(read.evidence,args2))return{success:!1,message:"TASK_GATE_EVIDENCE_CAS_MISMATCH",errors:["TASK_GATE_EVIDENCE_CAS_MISMATCH: the existing repaired generation was created from a different source identity."]};let nextActions2=buildRepairNextActions(args2.task_id,read.evidence);return{success:!0,repaired:!1,task_id:args2.task_id,required_gates:[...read.evidence.required_gates],requirements_state:read.evidence.requirements_state,repaired_generation:read.evidence.workflow?.generation,next_actions:nextActions2,message:`Task gate evidence for ${args2.task_id} is already in repaired fail-closed state.`}}if(read.status==="valid"&&read.evidence?.workflow?.schema===TASK_WORKFLOW_SCHEMA_MARKER&&!evidenceHasLegacyMarker&&latestReceipt!=null&&!receiptHasLegacyMarker)return{success:!1,message:"TASK_GATE_EVIDENCE_REPAIR_NOT_REQUIRED",errors:[`TASK_GATE_EVIDENCE_REPAIR_NOT_REQUIRED: ${args2.task_id} has valid authoritative evidence. Use the normal workflow repair path; this tool only rebuilds corrupt or legacy evidence.`]};if(read.status==="valid"&&read.evidence?.requirements_state==="known"&&!evidenceHasLegacyMarker&&receiptHasLegacyMarker)return{success:!1,message:"TASK_GATE_REQUIREMENTS_RECEIPT_STALE",errors:[`TASK_GATE_REQUIREMENTS_RECEIPT_STALE: ${args2.task_id} has clean accepted-mutation evidence but its latest requirements receipt is legacy-tainted. Repair was refused without modifying evidence; replay the prepared coder settlement so it can publish the exact hash-linked receipt.`]};if(typeof args2.expected_sha256==="string"&&read.status!=="missing"&&read.sha256!==args2.expected_sha256)return{success:!1,message:"TASK_GATE_EVIDENCE_CAS_MISMATCH",errors:[`TASK_GATE_EVIDENCE_CAS_MISMATCH: expected sha256 ${args2.expected_sha256}, found ${read.sha256}.`]};if(typeof args2.expected_generation==="number"){let observedGeneration=read.status==="valid"?read.generation:latestReceipt?.generation;if(observedGeneration!==args2.expected_generation)return{success:!1,message:"TASK_GATE_EVIDENCE_CAS_MISMATCH",errors:[`TASK_GATE_EVIDENCE_CAS_MISMATCH: expected generation ${args2.expected_generation}, found ${observedGeneration??"unknown"}.`]}}if(read.status==="unreadable"||read.status==="oversized")return{success:!1,message:read.error?.message??"TASK_GATE_EVIDENCE_UNREADABLE: repair requires operator intervention before evidence can be rewritten.",errors:[read.error?.message??`TASK_GATE_EVIDENCE_UNREADABLE: ${args2.task_id} could not be read safely for repair.`]};if(evidenceHasLegacyMarker&&latestReceipt==null&&!isReceiptlessLegacySentinelReset(args2.task_id,read.evidence))return{success:!1,message:"TASK_GATE_REQUIREMENTS_RECEIPT_MISSING",errors:[`TASK_GATE_REQUIREMENTS_RECEIPT_MISSING: ${args2.task_id} is marker-bearing but does not match the exact receipt-less state emitted by the historical repair flow. Repair was refused without modifying evidence or session state.`]};let nextGeneration2=Math.max(read.status==="valid"?read.generation??-1:-1,latestReceipt?.generation??-1)+1,nextEvidence;if(evidenceHasLegacyMarker||receiptHasLegacyMarker){let preservedGates=withoutLegacyReconstructionGate([...read.status==="valid"?read.evidence?.required_gates??[]:[],...latestReceipt?.requiredGates??[]]);nextEvidence=buildUnknownRepairedEvidence(args2.task_id,preservedGates,Math.max(nextGeneration2,1),{sha256:read.status==="missing"?null:read.sha256,generation:read.status==="valid"?read.generation??null:latestReceipt?.generation??null},latestReceipt?.chainHash??null)}else if(latestReceipt)nextEvidence=buildKnownRepairedEvidence(args2.task_id,latestReceipt,nextGeneration2,{sha256:read.status==="missing"?null:read.sha256,generation:read.status==="valid"?read.generation??null:latestReceipt.generation??null});else if(read.status==="missing")return{success:!1,message:"TASK_GATE_EVIDENCE_ABSENT",errors:[`TASK_GATE_EVIDENCE_ABSENT: ${args2.task_id} has no evidence file and no authoritative requirements receipt to rebuild from.`]};else return{success:!1,message:"TASK_GATE_REQUIREMENTS_RECEIPT_MISSING",errors:[`TASK_GATE_REQUIREMENTS_RECEIPT_MISSING: ${args2.task_id} has no authoritative requirements receipt. Receipt-less repair was refused without modifying the original evidence because its required gates cannot be reconstructed safely.`]};let serialized3=canonicalizeTaskEvidence(args2.task_id,nextEvidence),quarantine;if(isQuarantinableTaskEvidenceRead(read))quarantine=await quarantineTaskEvidenceBytes(canonicalDirectory,args2.task_id,read,normalizedReason,context,latestReceipt?.generation??null);assertTaskEvidenceWriteAllowed(canonicalDirectory,args2.task_id),await atomicWriteFile(taskEvidenceFilePath(canonicalDirectory,args2.task_id),serialized3),invalidateTaskEvidenceSessionFallbacks(args2.task_id);let nextActions=buildRepairNextActions(args2.task_id,nextEvidence);return{success:!0,repaired:!0,task_id:args2.task_id,required_gates:[...nextEvidence.required_gates],requirements_state:nextEvidence.requirements_state,quarantine_digest:quarantine?.digest,quarantine_path:quarantine?.filePath,repaired_generation:nextEvidence.workflow?.generation,next_actions:nextActions,message:`Repaired task gate evidence for ${args2.task_id} into a fresh fail-closed generation ${nextEvidence.workflow?.generation}. Next actions: ${nextActions.join(" ")}`}})}init_create_tool();init_resolve_working_directory();async function executeRepairGateEvidence(args2,directory,_ctx){try{if(!_ctx||stripKnownSwarmPrefix(_ctx.agent??"").toLowerCase()!=="architect")return{success:!1,message:"Only the architect may repair task gate evidence.",errors:["TASK_GATE_EVIDENCE_ARCHITECT_ONLY"]};let resolved=resolveWorkingDirectory(args2.working_directory,directory);if(!resolved.success)return{success:!1,message:resolved.message,errors:[resolved.message]};return await repairTaskGateEvidence(args2,resolved.directory,{sessionID:_ctx?.sessionID,messageID:_ctx?.messageID})}catch(error93){return{success:!1,message:"repair_gate_evidence failed",errors:[error93 instanceof Error?error93.message:String(error93)]}}}var repair_gate_evidence=createSwarmTool({description:"Architect-only evidence repair for exact-task gate files. Rebuilds from a durable requirements receipt, recovers receipt-backed legacy marker wedges or the exact sentinel-only historical reset, and refuses every other receipt-less reconstruction.",args:{task_id:exports_external.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/,"Task ID must be in N.M or N.M.P format"),reason:exports_external.string().min(1).max(2000),expected_sha256:exports_external.string().regex(/^[a-f0-9]{64}$/).optional(),expected_generation:exports_external.number().int().min(0).optional(),working_directory:exports_external.string().optional()},execute:async(args2,directory,ctx)=>JSON.stringify(await executeRepairGateEvidence(args2,directory,ctx),null,2)});init_zod();init_schema();init_knowledge_receipt_ledger();init_create_tool();init_resolve_working_directory();async function executeRepairKnowledgeReceiptLedger(args2,directory,_ctx){try{if(_ctx&&stripKnownSwarmPrefix(_ctx.agent??"").toLowerCase()!=="architect")return{success:!1,message:"Only the architect may repair the knowledge receipt ledger.",errors:["RECEIPT_REPAIR_ARCHITECT_ONLY"]};if(_ctx?.sessionID&&args2.session_id!==_ctx.sessionID)return{success:!1,message:"repair_knowledge_receipt_ledger session_id must match the invoking tool context.",errors:["RECEIPT_REPAIR_SESSION_MISMATCH"]};let resolved=resolveWorkingDirectory(args2.working_directory,directory);if(!resolved.success)return{success:!1,message:resolved.message,errors:[resolved.message]};if(args2.operation==="backfill_phase_id"){let backfill=await backfillMembershipPhaseIds(resolved.directory);if(!backfill.ok)return{success:!1,message:"repair_knowledge_receipt_ledger backfill_phase_id failed",errors:[backfill.detail],code:backfill.code};return{success:!0,message:`phase_id backfill complete: ${backfill.backfilled} membership(s) backfilled, ${backfill.skipped.length} skipped (unparsable label), ${backfill.journal_records} journal record(s) appended. Stored labels are never rewritten.`,backfilled:backfill.backfilled,skipped:backfill.skipped.slice(0,20),skipped_total:backfill.skipped.length,journal_records:backfill.journal_records}}let result=await repairKnowledgeReceiptLedger(resolved.directory,args2);if(!result.ok)return{success:!1,message:"repair_knowledge_receipt_ledger failed",errors:[result.detail],code:result.code};let reEvaluationArgs=JSON.stringify({repair_id:result.repair_id,phase:args2.phase,...args2.task_id?{task_id:args2.task_id}:{},scope_complete:!0});return{success:!0,message:result.status==="validated_projection"?"knowledge receipt projection validated":result.status==="pending_re_evaluation"?`knowledge receipt ledger still pending re-evaluation; as architect, run knowledge_recall with a comprehensive query and repair_re_evaluation ${reEvaluationArgs}`:`knowledge receipt ledger repaired and blocked pending re-evaluation; as architect, run knowledge_recall with a comprehensive query and repair_re_evaluation ${reEvaluationArgs}`,...result}}catch(error93){return{success:!1,message:"repair_knowledge_receipt_ledger failed",errors:[error93 instanceof Error?error93.message:String(error93)]}}}var repair_knowledge_receipt_ledger=createSwarmTool({description:"Architect-only repair and validation for the authoritative knowledge receipt ledger. Default operation repairs: rebuilds the derived projection when authority is readable, or quarantines a bounded corrupt authority, salvages only the validated prefix, and blocks the exact phase/session until a fresh re-evaluation is committed. operation backfill_phase_id durably stamps the stable numeric phase_id on live memberships that lack one across the WHOLE ledger (phase/session_id are not used to scope the backfill; labels never rewritten).",args:{phase:exports_external.string().min(1),session_id:exports_external.string().min(1),task_id:exports_external.string().min(1).optional(),reason:exports_external.string().min(1).max(2000),operation:exports_external.enum(["repair","backfill_phase_id"]).optional(),grace_days:exports_external.number().int().min(0).optional(),working_directory:exports_external.string().optional()},execute:async(args2,directory,ctx)=>JSON.stringify(await executeRepairKnowledgeReceiptLedger(args2,directory,ctx),null,2)});init_zod();init_loader();init_schema();init_profiles();init_telemetry();init_path_security();init_create_tool();import*as path373 from"node:path";init_zod();init_external_tool_runner();init_path_security();init_create_tool();import*as fs230 from"node:fs";import{createRequire as createRequire7}from"node:module";import*as path372 from"node:path";var require2=createRequire7(import.meta.url),DEFAULT_MAX_RESULTS4=100,DEFAULT_MAX_LINES=200,REGEX_TIMEOUT_MS=5000,MAX_FILE_SIZE_BYTES8=1048576,HARD_CAP_RESULTS4=1e4,HARD_CAP_LINES=1e4,MAX_QUERY_LENGTH=20000,MAX_INCLUDE_PATTERNS=100,MAX_RG_STDOUT_BYTES=8388608,MAX_RG_STDERR_BYTES=65536,FALLBACK_MAX_FILES=20000,FALLBACK_MAX_DIRS=5000,FALLBACK_MAX_DEPTH=40,FALLBACK_MAX_TOTAL_BYTES=67108864,DEFAULT_SKIP_DIRS=new Set([".git",".swarm","node_modules","dist","build","out","coverage",".next",".turbo",".cache"]);function globMatch(pattern,filePath){let normalizedPattern=pattern.replace(/\\/g,"/"),normalizedPath=filePath.replace(/\\/g,"/"),regexPattern=normalizedPattern.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*\*/g,"{{DOUBLESTAR}}").replace(/\*/g,"[^/]*").replace(/\?/g,".").replace(/\{\{DOUBLESTAR\}\}/g,".*");try{return new RegExp(`^${regexPattern}$`).test(normalizedPath)}catch{return!1}}function matchesGlobs(filePath,globs){if(globs.length===0)return!0;return globs.some((glob)=>globMatch(glob,filePath))}var WINDOWS_RESERVED_NAMES5=/^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;function containsWindowsAttacks4(str){if(/:[^\\/]/.test(str))return!0;let parts=str.split(/[/\\]/);for(let part of parts)if(WINDOWS_RESERVED_NAMES5.test(part))return!0;return!1}function resolveWithinWorkspace(filePath,workspace){try{let resolvedPath=path372.resolve(workspace,filePath),realWorkspace=fs230.realpathSync(workspace),realResolvedPath=fs230.realpathSync(resolvedPath),relativePath2=path372.relative(realWorkspace,realResolvedPath);if(relativePath2.startsWith("..")||path372.isAbsolute(relativePath2))return null;return relativePath2}catch{return null}}function isPathInWorkspace3(filePath,workspace){return resolveWithinWorkspace(filePath,workspace)!==null}function validatePathForRead2(filePath,workspace){return isPathInWorkspace3(filePath,workspace)}function splitGlobPatterns2(value){return value?value.split(",").map((p)=>p.trim()).filter(Boolean):[]}var GLOB_METACHARACTERS=/[*?[\]{}]/;function isExactPath(pattern){return!GLOB_METACHARACTERS.test(pattern)}function targetsDotDirectory(pattern){let firstSegment=pattern.split(/[\\/]/)[0];return!!firstSegment&&firstSegment.startsWith(".")&&firstSegment!=="."&&firstSegment!==".."}function hasGitSegment(resolvedRelativePath){return resolvedRelativePath.split(/[\\/]/).some((segment)=>segment.toLowerCase()===".git")}function toWorkspaceRelativePath2(filePath,workspace){try{let resolved=path372.resolve(workspace,filePath),realWorkspace=fs230.realpathSync(workspace),realResolved=fs230.realpathSync(resolved),relative99=path372.relative(realWorkspace,realResolved);if(!relative99||relative99.startsWith("..")||path372.isAbsolute(relative99))return null;return relative99.split(path372.sep).join("/")}catch{return null}}function truncateLine(line,maxLines){let trimmed=line.trimEnd();if(trimmed.length>maxLines)return`${trimmed.substring(0,maxLines)}...`;return trimmed}function resolvePackagedRipgrep(){try{let mod=require2("@vscode/ripgrep");return typeof mod.rgPath==="string"&&mod.rgPath?mod.rgPath:null}catch{return null}}function resolveRipgrepBinary(){return _internals319.resolvePackagedRipgrep()??_internals319.resolveExecutableFromPath(["rg"])}async function ripgrepSearch(opts){let rgPath=_internals319.resolveRipgrepBinary();if(!rgPath)return{error:!0,type:"rg-not-found",message:"ripgrep (rg) not found; using fallback search was not possible"};let args2=["--json","--no-config","-n"],includes=splitGlobPatterns2(opts.include),promotablePaths=[],globIncludes=[];for(let pattern of includes){let resolvedRelative=resolveWithinWorkspace(pattern,opts.workspace);if(isExactPath(pattern)&&targetsDotDirectory(pattern)&&pattern.split(/[\\/]/)[0]?.toLowerCase()!==".git"&&resolvedRelative!==null&&!hasGitSegment(resolvedRelative))promotablePaths.push(pattern);else globIncludes.push(pattern)}let pathOperands;if(promotablePaths.length>0&&globIncludes.length===0)pathOperands=promotablePaths;else{for(let pattern of[...globIncludes,...promotablePaths])args2.push("--glob",pattern);if(includes.some((p)=>targetsDotDirectory(p)&&p.split(/[\\/]/)[0]?.toLowerCase()!==".git"))args2.push("--hidden","--no-ignore"),args2.push("--glob","!.git");pathOperands=["."]}for(let pattern of splitGlobPatterns2(opts.exclude))args2.push("--glob",`!${pattern}`);if(opts.mode!=="regex")args2.push("--fixed-strings");args2.push("--",opts.query,...pathOperands);let run=await _internals319.runExternalTool({executable:rgPath,args:args2,cwd:opts.workspace,timeoutMs:REGEX_TIMEOUT_MS,maxStdoutBytes:MAX_RG_STDOUT_BYTES,maxStderrBytes:MAX_RG_STDERR_BYTES});try{if(run.status==="timeout")return{error:!0,type:"regex-timeout",message:`Search timed out after ${REGEX_TIMEOUT_MS}ms`};if(run.status==="spawn-error")return{error:!0,type:"unknown",message:run.message??"ripgrep failed to start"};if(run.exitCode!==0&&run.stderr){if(run.stderr.includes("Invalid regex")||run.stderr.includes("regex parse error")||run.stderr.includes("SyntaxError"))return{error:!0,type:"invalid-query",message:`Invalid query: ${run.stderr.split(`
|
|
7855
|
+
`,r:"\r",b:"\b",f:"\f",v:"\v"};if(simple[escaped]!==void 0){appendText(simple[escaped]);continue}if(/[0-7]/.test(escaped)){let octal=escaped;for(let count4=0;count4<2;count4++){let next=value[index+1];if(!next||!/[0-7]/.test(next))break;octal+=next,index++}bytes.push(Number.parseInt(octal,8));continue}return null}return Buffer.from(bytes).toString("utf8")}function normalizeRepoPathKey(repoPath){let normalized=repoPath.replace(/\\/g,"/");return _internals318.platform()==="win32"||_internals318.platform()==="darwin"?normalized.toLowerCase():normalized}function normalizeDiffPath(rawPath){let pathToken=rawPath.startsWith('"')?rawPath:rawPath.split("\t",1)[0],decoded=decodeGitQuotedPath(pathToken);if(decoded===null||decoded==="/dev/null"||decoded.trim().length===0)return null;return normalizeRepoPathKey(decoded)}function parseDiffLineRangesChecked(diffOutput,requireGitFileHeaders){let result=new Map,currentFile=null,inGitFile=!1,expectingDestination=!1,destinationSeen=!1,destinationNeedsHunk=!1,collectedLines=0;for(let rawLine of diffOutput.split(/\r?\n/)){let line=rawLine.endsWith("\r")?rawLine.slice(0,-1):rawLine;if(line.startsWith("diff --git ")){if(expectingDestination||destinationNeedsHunk)return null;inGitFile=!0,currentFile=null,expectingDestination=!1,destinationSeen=!1;continue}if(line.startsWith("--- ")&&(inGitFile||!requireGitFileHeaders)){if(expectingDestination||destinationNeedsHunk)return null;expectingDestination=!0;continue}if(line.startsWith("+++ ")){if(requireGitFileHeaders&&(!inGitFile||!expectingDestination))return null;let rawDestination=line.slice(4);if(currentFile=normalizeDiffPath(rawDestination),currentFile===null&&rawDestination.trim()!=="/dev/null")return null;if(expectingDestination=!1,destinationSeen=!0,destinationNeedsHunk=!0,!currentFile)continue;if(!result.has(currentFile))result.set(currentFile,new Set);continue}if(!line.startsWith("@@"))continue;if(expectingDestination||requireGitFileHeaders&&(!inGitFile||!destinationSeen))return null;let match=/^@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/.exec(line);if(!match)return null;let start=Number.parseInt(match[1],10),count4=match[2]!==void 0?Number.parseInt(match[2],10):1;if(!Number.isSafeInteger(start)||!Number.isSafeInteger(count4)||count4<0||count4>0&&start<1||count4>MAX_CHANGED_LINE_ENTRIES||start+count4-1>Number.MAX_SAFE_INTEGER||collectedLines+count4>MAX_CHANGED_LINE_ENTRIES)return null;if(destinationNeedsHunk=!1,!currentFile)continue;let lines=result.get(currentFile);if(!lines)return null;for(let index=0;index<count4;index++)lines.add(start+index);collectedLines+=count4}if(expectingDestination||destinationNeedsHunk)return null;return result}function mergeChangedLines(target,source){for(let[file3,sourceLines]of source){let targetLines=target.get(file3)??new Set;for(let line of sourceLines)targetLines.add(line);target.set(file3,targetLines)}}function parseUntrackedStatus(output){if(output.length>0&&!output.endsWith("\x00"))return null;let untracked=[],records=output.split("\x00");for(let index=0;index<records.length-1;index++){let record3=records[index];if(!record3||record3.length<4||record3[2]!==" ")return null;let status2=record3.slice(0,2),filePath=record3.slice(3);if(!filePath||!isKnownPorcelainStatus(status2))return null;if(status2==="??"||status2==="!!")untracked.push(normalizeRepoPathKey(filePath));if(/[RC]/.test(status2)){let sourcePath=records[++index];if(!sourcePath||looksLikePorcelainStatusRecord(sourcePath))return null}}return untracked}function isKnownPorcelainStatus(status2){if(status2==="??"||status2==="!!")return!0;if(/U/.test(status2))return new Set(["DD","AU","UD","UA","DU","AA","UU"]).has(status2);return status2!==" "&&/^[ MTADRC]{2}$/.test(status2)}function looksLikePorcelainStatusRecord(value){return value.length>=4&&value[2]===" "&&isKnownPorcelainStatus(value.slice(0,2))}async function getChangedLineAmbiguousFiles(directory,abortSignal,requestedFiles=[]){let mergeBase=null;for(let baseBranch of["zaxbyhub/main","upstream/main","origin/main","main","origin/master","master"]){let candidate2=(await runGit8(["merge-base",baseBranch,"HEAD"],directory,abortSignal))?.trim();if(candidate2&&/^[0-9a-f]{40,64}$/i.test(candidate2)){mergeBase=candidate2;break}}if(!mergeBase)return null;let headSha=(await runGit8(["rev-parse","HEAD"],directory,abortSignal))?.trim();if(typeof headSha==="string"&&/^[0-9a-f]{40,64}$/i.test(headSha)&&headSha.toLowerCase()===mergeBase.toLowerCase())return null;let literalPathspecs=requestedFiles.map((file3)=>path368.relative(directory,file3).replace(/\\/g,"/")).filter((file3)=>file3.length>0&&file3!==".."&&!file3.startsWith("../")).map((file3)=>`:(literal)${file3}`),statusArgs=["-c","core.quotePath=false","status","--porcelain=v1","-z","--untracked-files=all",...literalPathspecs.length>0?["--",...literalPathspecs]:[]],[committedNames,status2]=await Promise.all([runGit8(["-c","core.quotePath=false","diff","--name-only","--no-ext-diff","--no-color","--no-prefix","-z",`${mergeBase}..HEAD`,"--",...literalPathspecs.length>0?literalPathspecs:[]],directory,abortSignal),runGit8(statusArgs,directory,abortSignal)]);if(committedNames===null||status2===null)return null;let committed=new Set(committedNames.split("\x00").filter(Boolean).map(normalizeRepoPathKey)),staged=new Set,unstaged=new Set;if(status2.length>0&&!status2.endsWith("\x00"))return null;let records=status2.split("\x00");for(let index=0;index<records.length-1;index++){let record3=records[index];if(!record3||record3.length<4||record3[2]!==" ")return null;let statusCode=record3.slice(0,2),filePath=record3.slice(3);if(!filePath||!isKnownPorcelainStatus(statusCode))return null;if(statusCode!=="??"&&statusCode!=="!!"){let key3=normalizeRepoPathKey(filePath);if(/[MADRCU]/.test(statusCode[0]))staged.add(key3);if(/[MADRCU]/.test(statusCode[1]))unstaged.add(key3)}if(/[RC]/.test(statusCode)){let sourcePath=records[++index];if(!sourcePath||looksLikePorcelainStatusRecord(sourcePath))return null}}let ambiguous=new Set;for(let key3 of committed)if(staged.has(key3)||unstaged.has(key3))ambiguous.add(key3);for(let key3 of staged)if(unstaged.has(key3))ambiguous.add(key3);return ambiguous}async function getChangedLineRanges(directory,abortSignal,requestedFiles=[]){let mergeBase=null;for(let baseBranch of["zaxbyhub/main","upstream/main","origin/main","main","origin/master","master"]){let candidate2=(await runGit8(["merge-base",baseBranch,"HEAD"],directory,abortSignal))?.trim();if(candidate2&&/^[0-9a-f]{40,64}$/i.test(candidate2)){mergeBase=candidate2;break}}if(!mergeBase)return null;let commonDiffArgs=["-c","core.quotePath=false","diff","--no-ext-diff","--no-color","--no-prefix","-U0"],requestedPathspecs=requestedFiles.map((file3)=>path368.relative(directory,file3).replace(/\\/g,"/")).filter((file3)=>file3.length>0&&file3!==".."&&!file3.startsWith("../")),statusArgs=["-c","core.quotePath=false","status","--porcelain=v1","-z","--untracked-files=all",...requestedPathspecs.length>0?["--ignored=matching"]:[],...requestedPathspecs.length>0?["--",...requestedPathspecs]:[]],[committed,staged,unstaged,status2]=await Promise.all([runGit8([...commonDiffArgs,`${mergeBase}..HEAD`,"--"],directory,abortSignal),runGit8([...commonDiffArgs,"--cached","HEAD","--"],directory,abortSignal),runGit8([...commonDiffArgs,"--"],directory,abortSignal),runGit8(statusArgs,directory,abortSignal)]);if(committed===null||staged===null||unstaged===null||status2===null)return null;let committedLines=parseDiffLineRangesChecked(committed,!0),stagedLines=parseDiffLineRangesChecked(staged,!0),unstagedLines=parseDiffLineRangesChecked(unstaged,!0);if(!committedLines||!stagedLines||!unstagedLines)return null;let result=new Map;mergeChangedLines(result,committedLines),mergeChangedLines(result,stagedLines),mergeChangedLines(result,unstagedLines);let untracked=parseUntrackedStatus(status2);if(untracked===null)return null;let requestedKeys=requestedPathspecs.map(normalizeRepoPathKey);for(let file3 of untracked)if(result.set(file3,new Set([ALL_LINES_CHANGED])),file3.endsWith("/")){for(let requestedFile of requestedKeys)if(requestedFile.startsWith(file3))result.set(requestedFile,new Set([ALL_LINES_CHANGED]))}return result}function classifySastFindings(findings,changedLineRanges,directory){if(!changedLineRanges)return{newFindings:findings,preexistingFindings:[]};let newFindings=[],preexistingFindings=[],pathApi=_internals318.platform()==="win32"?path368.win32:path368.posix,resolvedDirectory=pathApi.resolve(directory);for(let finding of findings){let filePath=finding.location.file,normalised;try{if(typeof filePath!=="string"||filePath.length===0||filePath.includes("\x00")){newFindings.push(finding);continue}let resolvedFinding=pathApi.isAbsolute(filePath)?pathApi.resolve(filePath):pathApi.resolve(resolvedDirectory,filePath),relative98=pathApi.relative(resolvedDirectory,resolvedFinding);if(pathApi.isAbsolute(relative98)||relative98===".."||relative98.startsWith(`..${pathApi.sep}`)){newFindings.push(finding);continue}normalised=normalizeRepoPathKey(relative98)}catch{newFindings.push(finding);continue}let changedLines=changedLineRanges.get(normalised);if(changedLines?.has(ALL_LINES_CHANGED)||changedLines?.has(finding.location.line))newFindings.push(finding);else preexistingFindings.push(finding)}return{newFindings,preexistingFindings}}function classifySecretFindings(findings,changedLineRanges,directory,ambiguousFiles){if(!changedLineRanges)return{newFindings:findings,preexistingFindings:[]};let newFindings=[],preexistingFindings=[],pathApi=_internals318.platform()==="win32"?path368.win32:path368.posix,resolvedDirectory=pathApi.resolve(directory);for(let finding of findings){let{path:filePath,line}=finding;if(typeof filePath!=="string"||filePath.length===0||filePath.includes("\x00")||typeof line!=="number"||!Number.isSafeInteger(line)||line<1){newFindings.push(finding);continue}let changedLines;try{let resolvedFinding=pathApi.isAbsolute(filePath)?pathApi.resolve(filePath):pathApi.resolve(resolvedDirectory,filePath),relative98=pathApi.relative(resolvedDirectory,resolvedFinding);if(pathApi.isAbsolute(relative98)||relative98===".."||relative98.startsWith(`..${pathApi.sep}`)){newFindings.push(finding);continue}let normalised=normalizeRepoPathKey(relative98);if(ambiguousFiles?.has(normalised)){newFindings.push(finding);continue}changedLines=changedLineRanges.get(normalised)}catch{newFindings.push(finding);continue}if(changedLines!==void 0&&changedLines.size>0&&!changedLines.has(ALL_LINES_CHANGED)&&!changedLines.has(line))preexistingFindings.push(finding);else newFindings.push(finding)}return{newFindings,preexistingFindings}}async function runPreCheckBatch(input,workspaceDir,contextDir,abortSignal){let effectiveWorkspaceDir=workspaceDir||input.directory||contextDir,{files,directory,sast_threshold="medium",gates:gatesOverrides,phase,sast_enabled=!0}=input,gates=gatesOverrides??(input.config?.gates?{sast_scan:input.config.gates.sast_scan,quality_budget:input.config.gates.quality_budget}:void 0),dirError=validateDirectory2(directory,effectiveWorkspaceDir);if(dirError)return warn(`pre_check_batch: Invalid directory: ${dirError}`),{batch_status:"invalid",gates_passed:!1,lint:{ran:!1,error:dirError,duration_ms:0},secretscan:{ran:!1,error:dirError,duration_ms:0},sast_scan:{ran:!1,error:dirError,duration_ms:0},quality_budget:{ran:!1,error:dirError,duration_ms:0},total_duration_ms:0};if(!files||files.length===0)return warn("pre_check_batch: No files provided, skipping all tools (fail-closed)"),{batch_status:"invalid",gates_passed:!1,lint:{ran:!1,error:"No files provided",duration_ms:0},secretscan:{ran:!1,error:"No files provided",duration_ms:0},sast_scan:{ran:!1,error:"No files provided",duration_ms:0},quality_budget:{ran:!1,error:"No files provided",duration_ms:0},total_duration_ms:0};let changedFiles=[],rawDeclaredCount=files.length;for(let file3 of files){if(typeof file3!=="string"){warn(`pre_check_batch: Non-string file entry rejected: ${String(file3)}`);continue}if(validatePath(file3,directory,effectiveWorkspaceDir)){warn(`pre_check_batch: Invalid file path: ${file3}`);continue}changedFiles.push(path368.resolve(directory,file3))}if(changedFiles.length===0)return warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)"),{batch_status:"invalid",gates_passed:!1,lint:{ran:!1,error:"No files provided",duration_ms:0},secretscan:{ran:!1,error:"No files provided",duration_ms:0},sast_scan:{ran:!1,error:"No files provided",duration_ms:0},quality_budget:{ran:!1,error:"No files provided",duration_ms:0},total_duration_ms:0};try{assertProjectRoot(directory)}catch(error93){let rootError=error93 instanceof Error?error93.message:String(error93);return warn(`pre_check_batch: Project-root validation failed: ${rootError}`),{batch_status:"invalid",gates_passed:!1,lint:{ran:!1,error:rootError,duration_ms:0},secretscan:{ran:!1,error:rootError,duration_ms:0},sast_scan:{ran:!1,error:rootError,duration_ms:0},quality_budget:{ran:!1,error:rootError,duration_ms:0},total_duration_ms:0}}if(changedFiles.length>MAX_FILES)throw Error(`Input exceeds maximum file count: ${changedFiles.length} > ${MAX_FILES}`);let limit=pLimit(MAX_CONCURRENT),sastDisabledByConfig=gates?.sast_scan?.enabled===!1,[lintResult,secretscanResult,sastScanResult,qualityBudgetResult]=await Promise.all([limit(()=>_internals318.runLintWrapped(changedFiles,directory,gates,abortSignal)),limit(()=>_internals318.runSecretscanWrapped(changedFiles,directory,gates,abortSignal,rawDeclaredCount)),sast_enabled&&!sastDisabledByConfig?limit(()=>_internals318.runSastScanWrapped(changedFiles,directory,sast_threshold,gates,phase,abortSignal)):Promise.resolve({ran:!1,duration_ms:0}),limit(()=>_internals318.runQualityBudgetWrapped(changedFiles,directory,gates,abortSignal))]),totalDuration=lintResult.duration_ms+secretscanResult.duration_ms+sastScanResult.duration_ms+qualityBudgetResult.duration_ms,gatesPassed=!0;if(lintResult.ran&&lintResult.result){let lintRes=lintResult.result;if("success"in lintRes&&lintRes.success===!1)warn("pre_check_batch: Lint found issues (informational only)")}else if(lintResult.error)warn(`pre_check_batch: Lint error (informational only): ${lintResult.error}`);let changedLineRangesMemo,getChangedLineRangesMemoized=async()=>{if(changedLineRangesMemo===void 0)changedLineRangesMemo=await _internals318.getChangedLineRanges(directory,abortSignal,changedFiles);return changedLineRangesMemo},secretscanClassification,secretscanPreexistingFindings,secretscanScanFindings=secretscanResult.ran&&secretscanResult.result&&!("error"in secretscanResult.result)?secretscanResult.result.findings:[];if(secretscanScanFindings.length>0){let changedLineRanges=await getChangedLineRangesMemoized(),ambiguousFiles=await _internals318.getChangedLineAmbiguousFiles(directory,abortSignal,changedFiles);if(ambiguousFiles===null)secretscanClassification={newFindings:secretscanScanFindings,preexistingFindings:[],diffScoped:!1};else{let{newFindings,preexistingFindings}=classifySecretFindings(secretscanScanFindings,changedLineRanges,directory,ambiguousFiles);if(secretscanClassification={newFindings,preexistingFindings,diffScoped:changedLineRanges!==null},preexistingFindings.length>0)secretscanPreexistingFindings=preexistingFindings,warn(`pre_check_batch: Secretscan found ${preexistingFindings.length} pre-existing secret finding(s) on unchanged lines - visible, non-gating, passed to reviewer for triage`)}}let secretscanDecision=evaluateSecretscanGate(secretscanResult,rawDeclaredCount,secretscanClassification);if(!secretscanDecision.passed)gatesPassed=!1,warn(`pre_check_batch: ${secretscanDecision.summary} - GATE FAILED`);if(secretscanResult.ran||secretscanResult.error)try{let scanResult=secretscanDecision.result,secretscanEvidence={task_id:"secretscan",type:"secretscan",timestamp:new Date().toISOString(),agent:"pre_check_batch",verdict:secretscanDecision.passed?"pass":"fail",summary:secretscanDecision.summary,findings_count:secretscanDecision.findingsCount,scan_directory:scanResult?.scan_dir??directory,files_scanned:scanResult?.files_scanned??0,skipped_files:scanResult?.skipped_files??0,ignored_files:scanResult?.ignored_files??0,policy_skipped_files:scanResult?.policy_skipped_files??0,requested_files:scanResult?.requested_files??rawDeclaredCount,new_findings_count:secretscanDecision.newFindingsCount??0,preexisting_findings_count:secretscanDecision.preexistingFindingsCount??0,diff_scoped:secretscanDecision.diffScoped??!1,incomplete_files:scanResult?.incomplete_files??changedFiles.length,incomplete_paths:scanResult?.incomplete_paths??[{path:".",reason:"missing_coverage_metadata"}]};await _internals318.saveEvidence(directory,"secretscan",secretscanEvidence,abortSignal)}catch(e){let persistError=`Failed to persist secretscan evidence: ${e instanceof Error?e.message:String(e)}`;secretscanResult.error=persistError,gatesPassed=!1,warn(`pre_check_batch: ${persistError} - GATE FAILED`)}let sastPreexistingFindings,sastDegraded=!1;if(sastScanResult.ran&&sastScanResult.result){let sastResult=sastScanResult.result;if(sastResult.error)if(sastResult.failure_kind==="semgrep_process_exit"&&sastResult.findings.length===0)sastDegraded=!0,warn(`pre_check_batch: SAST coverage degraded (${sastResult.error}) - continuing without a gate failure`);else gatesPassed=!1,warn(`pre_check_batch: SAST scan error (${sastResult.error}) - GATE FAILED`);else if(sastResult.baseline_used){let sastCarryFindings=[...sastResult.pre_existing_findings??[],...sastResult.moved_findings??[]];if(sastCarryFindings.length>0){if(sastPreexistingFindings=sastCarryFindings.filter((f)=>meetsThresholdForTriage(f.severity,sast_threshold)),sastPreexistingFindings.length>0)warn(`pre_check_batch: SAST baseline diff found ${sastPreexistingFindings.length} pre-existing/moved finding(s) - passing to reviewer for triage`)}if(sastResult.verdict==="fail")gatesPassed=!1,warn("pre_check_batch: SAST scan found new findings above threshold - GATE FAILED")}else if(sastResult.verdict==="fail"){let gateFindings=sastResult.findings.filter((f)=>GATE_SEVERITIES.has(f.severity));if(gateFindings.length>0){let changedLineRanges=await getChangedLineRangesMemoized(),{newFindings,preexistingFindings}=classifySastFindings(gateFindings,changedLineRanges,directory);if(newFindings.length>0)gatesPassed=!1,warn(`pre_check_batch: SAST scan found ${newFindings.length} new HIGH/CRITICAL finding(s) on changed lines - GATE FAILED`);else if(preexistingFindings.length>0)sastPreexistingFindings=preexistingFindings,warn(`pre_check_batch: SAST scan found ${preexistingFindings.length} pre-existing HIGH/CRITICAL finding(s) on unchanged lines - passing to reviewer for triage`)}else gatesPassed=!1,warn("pre_check_batch: SAST scan found vulnerabilities - GATE FAILED")}}else if(sastScanResult.error)gatesPassed=!1,warn(`pre_check_batch: SAST scan error - GATE FAILED: ${sastScanResult.error}`);if(qualityBudgetResult.ran&&qualityBudgetResult.result){if(qualityBudgetResult.result.verdict==="fail")warn("pre_check_batch: Quality budget exceeded (informational only)")}else if(qualityBudgetResult.error)warn(`pre_check_batch: Quality budget error (informational only): ${qualityBudgetResult.error}`);return{batch_status:[lintResult,secretscanResult,sastScanResult,qualityBudgetResult].every((toolResult)=>toolResult.ran===!1)?"skipped":"completed",gates_passed:gatesPassed,lint:lintResult,secretscan:secretscanResult,sast_scan:sastScanResult,quality_budget:qualityBudgetResult,total_duration_ms:Math.round(totalDuration),...sastDegraded&&{sast_degraded:!0},...(!sast_enabled||sastDisabledByConfig)&&{sast_skipped:!0},...sastPreexistingFindings&&sastPreexistingFindings.length>0&&{sast_preexisting_findings:sastPreexistingFindings},...secretscanPreexistingFindings&&secretscanPreexistingFindings.length>0&&{secretscan_preexisting_findings:secretscanPreexistingFindings}}}var pre_check_batch=createSwarmTool({allowWorkingDirectoryOverride:!0,description:"Run multiple verification tools in parallel: lint, secretscan, SAST scan, and quality budget. Returns unified result with gates_passed status. Security findings and incomplete SAST runs are hard failures; a Semgrep nonzero process exit with zero findings is returned as explicit sast_degraded coverage and does not block.",args:{files:exports_external.array(exports_external.string()).optional().describe("Specific files to check (optional, scans directory if not provided)"),directory:exports_external.string().describe("Project root directory — ordinary workspace subdirectories are rejected; direct .git or .opencode project boundaries are accepted"),sast_threshold:exports_external.enum(["low","medium","high","critical"]).optional().describe("Minimum severity for SAST findings to cause failure (default: medium)"),phase:exports_external.number().int().min(1).optional().describe("Current phase number (positive integer >= 1). When provided, enables SAST baseline diffing: only findings absent from the phase-scoped baseline fail the gate.")},async execute(args2,directory,ctx){if(!args2||typeof args2!=="object")return serializePreCheckResult({batch_status:"invalid",gates_passed:!1,lint:{ran:!1,error:"Invalid arguments",duration_ms:0},secretscan:{ran:!1,error:"Invalid arguments",duration_ms:0},sast_scan:{ran:!1,error:"Invalid arguments",duration_ms:0},quality_budget:{ran:!1,error:"Invalid arguments",duration_ms:0},total_duration_ms:0});if(!directory||typeof directory!=="string"||directory.trim()==="")return serializePreCheckResult({batch_status:"invalid",gates_passed:!1,lint:{ran:!1,error:"project directory is required but was not provided",duration_ms:0},secretscan:{ran:!1,error:"project directory is required but was not provided",duration_ms:0},sast_scan:{ran:!1,error:"project directory is required but was not provided",duration_ms:0},quality_budget:{ran:!1,error:"project directory is required but was not provided",duration_ms:0},total_duration_ms:0});let typedArgs=args2;if(!typedArgs.directory)return serializePreCheckResult({batch_status:"invalid",gates_passed:!1,lint:{ran:!1,error:"directory is required",duration_ms:0},secretscan:{ran:!1,error:"directory is required",duration_ms:0},sast_scan:{ran:!1,error:"directory is required",duration_ms:0},quality_budget:{ran:!1,error:"directory is required",duration_ms:0},total_duration_ms:0});let resolvedDirectory=path368.resolve(typedArgs.directory),workspaceAnchor=path368.resolve(directory);if(isStrictPathDescendant(resolvedDirectory,workspaceAnchor)&&!hasExplicitProjectBoundary(resolvedDirectory)){let subDirError=`directory "${typedArgs.directory}" is a subdirectory of the project root — pre_check_batch requires the project root directory "${workspaceAnchor}"`;return serializePreCheckResult({batch_status:"invalid",gates_passed:!1,lint:{ran:!1,error:subDirError,duration_ms:0},secretscan:{ran:!1,error:subDirError,duration_ms:0},sast_scan:{ran:!1,error:subDirError,duration_ms:0},quality_budget:{ran:!1,error:subDirError,duration_ms:0},total_duration_ms:0})}let dirError=validateDirectory2(resolvedDirectory,workspaceAnchor);if(dirError)return serializePreCheckResult({batch_status:"invalid",gates_passed:!1,lint:{ran:!1,error:dirError,duration_ms:0},secretscan:{ran:!1,error:dirError,duration_ms:0},sast_scan:{ran:!1,error:dirError,duration_ms:0},quality_budget:{ran:!1,error:dirError,duration_ms:0},total_duration_ms:0});try{let sastEnabled=!0;try{let preamble=await _internals318.resolveGatePreamble(resolvedDirectory,ctx?.sessionID);if(preamble.resolved&&preamble.effectiveGates)sastEnabled=preamble.effectiveGates.sast_enabled}catch{warn("pre_check_batch: QA-gate profile resolution failed; keeping SAST enabled")}let rawPhase=typedArgs.phase,safePhase=typeof rawPhase==="number"&&Number.isInteger(rawPhase)&&rawPhase>=1?rawPhase:void 0,result=await _internals318.runPreCheckBatch({files:typedArgs.files,directory:resolvedDirectory,sast_threshold:typedArgs.sast_threshold,config:typedArgs.config,gates:_internals318.loadGateOverrides(resolvedDirectory),phase:safePhase,sast_enabled:sastEnabled},workspaceAnchor,directory,ctx?.abort);return serializePreCheckResult(result)}catch(error93){let errorMessage3=error93 instanceof Error?error93.message:"Unknown error";return serializePreCheckResult({batch_status:"invalid",gates_passed:!1,lint:{ran:!1,error:errorMessage3,duration_ms:0},secretscan:{ran:!1,error:errorMessage3,duration_ms:0},sast_scan:{ran:!1,error:errorMessage3,duration_ms:0},quality_budget:{ran:!1,error:errorMessage3,duration_ms:0},total_duration_ms:0})}}});init_zod();init_pr_workflow_gate();init_atomic_write();init_create_tool();import{createHash as createHash119}from"node:crypto";import{mkdirSync as mkdirSync98,readdirSync as readdirSync57,realpathSync as realpathSync58,rmSync as rmSync36,statSync as statSync113}from"node:fs";import{tmpdir as tmpdir20}from"node:os";import path369 from"node:path";var MAX_COMMIT_MESSAGE_CHARS=8192,MESSAGE_FILE_TTL_MS=86400000,PreparePrFeedbackCommitMessageArgsSchema=exports_external.object({message:exports_external.string().refine((value)=>value.trim().length>0,{message:"message must not be empty or whitespace-only"}).refine((value)=>value.length<=MAX_COMMIT_MESSAGE_CHARS,{message:`message must be at most ${MAX_COMMIT_MESSAGE_CHARS} characters`}).refine((value)=>!value.includes("\x00"),{message:"message must not contain NUL bytes"}).transform((value)=>value.trim())}).strict();function commitMessageTargetDir(){return path369.join(tmpdir20(),"swarm-pr-feedback-commit-msg")}function resolvePrFeedbackCommitMessageFilePath(sessionID,message){let sanitizedSession=sessionID.replace(/[^A-Za-z0-9._-]/g,"_"),digest5=createHash119("sha256").update(message,"utf8").digest("hex").slice(0,16);return path369.join(commitMessageTargetDir(),`${sanitizedSession}-${digest5}.txt`)}function pruneStaleMessageFiles(){try{let dir=commitMessageTargetDir(),now2=Date.now();for(let entry of readdirSync57(dir)){if(!entry.endsWith(".txt"))continue;let full=path369.join(dir,entry);try{let stats2=statSync113(full);if(now2-stats2.mtimeMs>MESSAGE_FILE_TTL_MS)rmSync36(full,{force:!1})}catch{}}}catch{}}async function executePreparePrFeedbackCommitMessage(args2,directory,context={}){let parsed=PreparePrFeedbackCommitMessageArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid commit-message request: ${parsed.error.issues.map((issue3)=>issue3.path.length>0?`${issue3.path.join(".")}: ${issue3.message}`:issue3.message).join("; ")}`});let sessionID=context.sessionID?.trim();if(!sessionID)return JSON.stringify({success:!1,message:"Commit-message authoring requires an active sessionID"});let state2=await readPrWorkflowGateState(directory,sessionID);if(!state2||state2.mode!=="PR_FEEDBACK"||!state2.prHeadSha)return JSON.stringify({success:!1,message:"Commit-message authoring requires an active bound PR_FEEDBACK workflow; bind the PR head first"});let message=parsed.data.message,targetDir=commitMessageTargetDir(),targetPath=resolvePrFeedbackCommitMessageFilePath(sessionID,message),resolvedTarget=path369.resolve(targetPath),resolvedDir=path369.resolve(targetDir);if(!(resolvedTarget===resolvedDir||resolvedTarget.startsWith(resolvedDir+path369.sep)))return JSON.stringify({success:!1,message:"Commit-message file path escaped the swarm-pr-feedback-commit-msg directory; refusing to write"});let repoRoot=path369.resolve(directory),insideRepo=(value)=>{let rel3=path369.relative(repoRoot,value);return rel3===""||!rel3.startsWith("..")&&!path369.isAbsolute(rel3)};if(insideRepo(resolvedTarget)||insideRepo(resolvedDir))return JSON.stringify({success:!1,message:"TMPDIR resolves inside the repository; the commit-message file must live outside the repository — refusing to write"});try{mkdirSync98(resolvedDir,{recursive:!0});let realpathDir=resolvedDir;try{realpathDir=realpathSync58(resolvedDir)}catch{mkdirSync98(resolvedDir,{recursive:!0})}let realpathTarget=path369.join(realpathDir,path369.basename(resolvedTarget));if(!realpathTarget.startsWith(realpathDir+path369.sep)&&realpathTarget!==realpathDir)return JSON.stringify({success:!1,message:"Commit-message file path escaped the swarm-pr-feedback-commit-msg directory through a symlink; refusing to write"});if(insideRepo(realpathDir))return JSON.stringify({success:!1,message:"The resolved temp directory points inside the repository through a symlink; refusing to write"});pruneStaleMessageFiles(),await atomicWriteFileAnyRoot(realpathTarget,message,{mode:384})}catch(error93){return JSON.stringify({success:!1,message:`Could not author the commit-message file: ${error93 instanceof Error?error93.message:String(error93)}`})}return JSON.stringify({success:!0,path:resolvedTarget,message:"Commit-message file authored outside the repository; commit with git commit -F <path> (the classifier refuses in-repo message files). The file is mode 0600, lives in the OS temp directory, never touches the bound checkout, and is pruned after 24h."})}var prepare_pr_feedback_commit_message=createSwarmTool({description:"Author a PR_FEEDBACK commit message that contains shell metacharacters (e.g. a Co-Authored-By trailer with <...>) into a file OUTSIDE the repository, returning the path for the sanctioned git commit -F command. The inline -m form is rejected by the shell classifier by design; an in-repo message file would dirty the clean-tree arming check. Requires an active bound PR_FEEDBACK workflow.",args:{message:PreparePrFeedbackCommitMessageArgsSchema.shape.message},execute:executePreparePrFeedbackCommitMessage});init_zod();init_guardrails2();init_pr_workflow_gate();init_scope_binding();init_create_tool();var PreparePrFeedbackScopeArgsSchema=exports_external.object({task_id:exports_external.string().regex(/^\d+\.\d+(?:\.\d+)*$/,"task_id must use N.M notation"),files:exports_external.array(exports_external.string().min(1).max(4096)).min(1).max(1e4)}).strict();function failure3(message){return JSON.stringify({success:!1,message},null,2)}async function executePreparePrFeedbackScope(args2,directory,context={}){let parsed=PreparePrFeedbackScopeArgsSchema.safeParse(args2);if(!parsed.success)return failure3(`Invalid PR-feedback scope: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`);let sessionID=context.sessionID?.trim();if(!sessionID)return failure3("PR-feedback scope requires an active session");let files=normalizeScopeFiles(parsed.data.files);if(!files)return failure3("PR-feedback scope contains an unsafe file path");for(let file3 of files){let symlinkBlock=checkWriteTargetForSymlink(file3,directory);if(symlinkBlock)return failure3(symlinkBlock)}try{await declarePrFeedbackScope(directory,sessionID,parsed.data.task_id,files)}catch(error93){return failure3(error93 instanceof Error?error93.message:String(error93))}return JSON.stringify({success:!0,task_id:parsed.data.task_id,files,message:"Scope is bound to the verified PR-feedback revision and will authorize only the next matching coder Task."},null,2)}var prepare_pr_feedback_scope=createSwarmTool({description:"Prepare an exact file scope for one PR-feedback coder Task after immutable feedback verification settles.",args:{task_id:PreparePrFeedbackScopeArgsSchema.shape.task_id,files:PreparePrFeedbackScopeArgsSchema.shape.files},execute:executePreparePrFeedbackScope});init_quality_budget();init_zod();init_pr_workflow_gate();init_create_tool();var RebindPrFeedbackHeadArgsSchema=exports_external.object({pr_head_sha:exports_external.string().trim().regex(/^[0-9a-f]{40}$/i)}).strict();async function executeRebindPrFeedbackHead(args2,directory,context={}){let parsed=RebindPrFeedbackHeadArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid PR feedback rebind: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`});if(!context.sessionID?.trim())return JSON.stringify({success:!1,message:"PR feedback rebind requires an active sessionID"});try{let state2=await rebindPrFeedbackHead(directory,context.sessionID,parsed.data.pr_head_sha);return JSON.stringify({success:!0,pr_head_sha:state2.prHeadSha,rebind_count:state2.prFeedbackRebindCount??1,message:"Rebound the PR_FEEDBACK intake head; every Stage A / verification / gate receipt is invalidated — re-run the full mechanical ladder on the new ancestry."})}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:String(error93)})}}var rebind_pr_feedback_head=createSwarmTool({description:"Rebind a PR_FEEDBACK workflow to a new verified remote PR head after merge/rebase/conflict repair (base-sync). Use ONLY when the history genuinely changed to repair base drift or conflicts: it refuses a no-op rebind to the current intake head, refuses while publication is armed (to change approved content after arming use invalidate_pr_feedback_publication), and refuses while lanes are in flight. It invalidates every ancestry-bound receipt (Stage A, verification, ordered gates) so the full mechanical ladder re-runs on the new ancestry. Requires the full 40-char new PR head SHA; the current checkout must equal it.",args:{pr_head_sha:RebindPrFeedbackHeadArgsSchema.shape.pr_head_sha},execute:executeRebindPrFeedbackHead});init_zod();init_utils2();init_atomic_write();init_create_tool();var FreshnessValueSchema=exports_external.string().trim().min(1).max(500).regex(/^(synced|behind:[1-9][0-9]*|fetch-failed:\S+)$/,"must be 'synced', 'behind:<n>', or 'fetch-failed:<reason>' (reason contains no whitespace)"),RecordBranchFreshnessArgsSchema=exports_external.object({issueNumber:exports_external.number().int().min(1),freshness:FreshnessValueSchema,override:exports_external.string().trim().min(1).max(4000).optional()}).strict();async function executeRecordBranchFreshness(args2,directory,context={}){let parsed=RecordBranchFreshnessArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid branch-freshness receipt: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`});let data=parsed.data;if(data.freshness==="synced"&&data.override)return JSON.stringify({success:!1,message:"An override is only meaningful for a fetch-failed outcome; a synced base needs none."});let receipt={issueNumber:data.issueNumber,freshness:data.freshness,timestamp:new Date().toISOString()};if(data.override)receipt.override=data.override;if(context.sessionID?.trim())receipt.sessionId=context.sessionID.trim();let validatedPath;try{validatedPath=validateSwarmPath(directory,"branch-freshness.json")}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:"Failed to validate path"})}try{await atomicWriteSwarmFile(validatedPath,JSON.stringify(receipt,null,2));let permits=await branchFreshnessReceiptExists(directory,data.issueNumber);return JSON.stringify({success:!0,issueNumber:data.issueNumber,path:".swarm/branch-freshness.json",permits,message:permits?`Branch-freshness receipt recorded for issue #${data.issueNumber}; the trace's freshness gate is satisfied.`:`Branch-freshness receipt recorded for issue #${data.issueNumber}, but the outcome (${data.freshness}) does NOT permit the trace — ${data.freshness.startsWith("behind:")?"re-sync with the default branch and re-record as synced.":"a fetch-failed outcome without a recorded user override fails closed."}`})}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:String(error93)})}}var record_branch_freshness=createSwarmTool({description:`Record the Phase 0 branch-freshness outcome for the current traced issue (issue #2564): freshness is "synced", "behind:<n>", or "fetch-failed:<reason>" exactly as the fetch recorded it, plus an optional verbatim user override for a failed fetch. The /swarm issue --trace workflow will not transition to PLAN until the recorded outcome permits (synced, or fetch-failed with an override). The response's permits field mirrors the gate reader's verdict on the persisted receipt (advisory for the calling agent — the reducer always recomputes it independently).`,args:{issueNumber:RecordBranchFreshnessArgsSchema.shape.issueNumber,freshness:RecordBranchFreshnessArgsSchema.shape.freshness,override:RecordBranchFreshnessArgsSchema.shape.override},execute:executeRecordBranchFreshness});init_zod();init_plan_schema();init_schema();init_extractors();init_manager();init_create_tool();var recordDirectiveOverrideInternals={loadPlan,recordDirectiveOverrides};async function executeRecordDirectiveOverride(args2,directory,ctx){if(!ctx?.sessionID?.trim())return{success:!1,code:"DIRECTIVE_OVERRIDE_SESSION_REQUIRED",message:"An exact session identity is required to record an override."};if(stripKnownSwarmPrefix(ctx.agent??"").toLowerCase()!=="architect")return{success:!1,code:"DIRECTIVE_OVERRIDE_ARCHITECT_ONLY",message:"Only the architect may record a critical-directive override."};let plan=await recordDirectiveOverrideInternals.loadPlan(directory),requestedPhase=plan?.phases.find((candidate2)=>candidate2.id===args2.phase);if(!plan||!requestedPhase||getCurrentPhase(plan)!==args2.phase&&!isPhaseInWrapWindow(plan,args2.phase))return{success:!1,code:"DIRECTIVE_OVERRIDE_PHASE_MISMATCH",message:`Phase ${args2.phase} is neither the current plan phase nor the phase being wrapped.`};let phaseLabel=extractPhaseLabelFromPlan(plan,args2.phase)??`Phase ${args2.phase}`;return await recordDirectiveOverrideInternals.recordDirectiveOverrides(directory,[...new Set(args2.directive_ids)],args2.justification,ctx.sessionID,phaseLabel,args2.phase),{success:!0,code:"DIRECTIVE_OVERRIDE_RECORDED",phase:args2.phase,directive_ids:[...new Set(args2.directive_ids)],message:"Recorded the audited override. Retry phase_complete so every gate is re-evaluated from a fresh snapshot."}}var record_directive_override=createSwarmTool({description:"Architect-only audited override for identified critical-directive violations. Requires the current phase (or the phase being wrapped, whose last task already advanced the cursor), the session identity and substantive justification; it cannot repair or bypass unreadable authority.",args:{directive_ids:exports_external.array(exports_external.string().min(1).max(256)).min(1).max(64),justification:exports_external.string().trim().min(10).max(2000),phase:exports_external.number().int().min(1).max(9999)},execute:async(args2,directory,ctx)=>JSON.stringify(await executeRecordDirectiveOverride(args2,directory,ctx),null,2)});init_zod();init_utils2();init_atomic_write();init_create_tool();var RecordImplementationReviewArgsSchema=exports_external.object({issueNumber:exports_external.number().int().min(1),reviewerVerdict:exports_external.enum(["APPROVE","NEEDS_REVISION","BLOCKED"]),criticVerdict:exports_external.enum(["APPROVE","NEEDS_REVISION","BLOCKED"]),diffBase:exports_external.string().trim().regex(/^[0-9a-f]{7,40}$/i),diffHead:exports_external.string().trim().regex(/^[0-9a-f]{7,40}$/i),notes:exports_external.string().trim().min(8).max(4000)}).strict();async function executeRecordImplementationReview(args2,directory,context={}){let parsed=RecordImplementationReviewArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid implementation review receipt: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`});let data=parsed.data;if(data.reviewerVerdict!=="APPROVE"||data.criticVerdict!=="APPROVE")return JSON.stringify({success:!1,message:"A satisfying implementation-review receipt requires BOTH the reviewer and the critic to have delivered APPROVE; record non-approving verdicts in the working notes and fix the findings instead."});let receipt={issueNumber:data.issueNumber,reviewerVerdict:data.reviewerVerdict,criticVerdict:data.criticVerdict,diffBase:data.diffBase,diffHead:data.diffHead,notes:data.notes,timestamp:new Date().toISOString()};if(context.sessionID?.trim())receipt.sessionId=context.sessionID.trim();let validatedPath;try{validatedPath=validateSwarmPath(directory,"implementation-review.json")}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:"Failed to validate path"})}try{return await atomicWriteSwarmFile(validatedPath,JSON.stringify(receipt,null,2)),JSON.stringify({success:!0,issueNumber:data.issueNumber,path:".swarm/implementation-review.json",message:`Implementation review recorded for issue #${data.issueNumber} (reviewer APPROVE + critic APPROVE); the trace may now satisfy its review gate.`})}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:String(error93)})}}var record_implementation_review=createSwarmTool({description:"Record the independent implementation review for the current traced issue (issue #2131 residual B): dispatch FRESH-context reviewer and critic passes over the implementation diff (separate contexts from the implementer), and once BOTH approve call this with the issue number, both APPROVE verdicts, the reviewed diff base/head SHAs, and notes. The /swarm issue --trace workflow will not hand off to commit-pr until this receipt exists. Non-approving verdicts cannot be recorded here — fix the findings and re-review.",args:{issueNumber:RecordImplementationReviewArgsSchema.shape.issueNumber,reviewerVerdict:RecordImplementationReviewArgsSchema.shape.reviewerVerdict,criticVerdict:RecordImplementationReviewArgsSchema.shape.criticVerdict,diffBase:RecordImplementationReviewArgsSchema.shape.diffBase,diffHead:RecordImplementationReviewArgsSchema.shape.diffHead,notes:RecordImplementationReviewArgsSchema.shape.notes},execute:executeRecordImplementationReview});init_zod();init_url_security();init_loader();init_utils2();init_forge_provider();init_atomic_write();init_create_tool();function loadConfiguredForgeContext4(directory){try{let config3=loadPluginConfig(directory),remote=detectGitRemote(directory,void 0);return resolveForgeContextFromPluginConfig(config3,remote?[remote]:[])??void 0}catch{return}}var RecordIssuePublicationArgsSchema=exports_external.object({issueNumber:exports_external.number().int().min(1),prNumber:exports_external.number().int().min(1),prUrl:exports_external.string().url(),headSha:exports_external.string().min(1).optional()}).strict();async function executeRecordIssuePublication(args2,directory){let parsed=RecordIssuePublicationArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid publication receipt: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`});let{issueNumber,prNumber,prUrl,headSha}=parsed.data,sanitizedPrUrl=sanitizeUrl(prUrl);if(!isForgePrUrl(prUrl)){let configured=loadConfiguredForgeContext4(directory);if(!(configured&&isForgePrUrl(prUrl,configured)))return JSON.stringify({success:!1,message:"Invalid publication receipt: prUrl must be a canonical PR URL (GitHub https://github.com/<owner>/<repo>/pull/<number> or GitLab https://<gitlab-host>/<owner>/<repo>/-/merge_requests/<number>)"})}let receipt={published:!0,issueNumber,prNumber,prUrl:sanitizedPrUrl,publishedAt:new Date().toISOString()};if(headSha)receipt.headSha=headSha;let validatedPath;try{validatedPath=validateSwarmPath(directory,"issue-publication.json")}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:"Failed to validate path"})}try{return await atomicWriteSwarmFile(validatedPath,JSON.stringify(receipt,null,2)),JSON.stringify({success:!0,issueNumber,prNumber,prUrl,path:".swarm/issue-publication.json",message:`Publication receipt recorded for issue #${issueNumber} (PR #${prNumber}); the issue-trace workflow will transition to its terminal published state.`})}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:String(error93)})}}var record_issue_publication=createSwarmTool({description:'Record that the traced issue has been published (PR created/updated) so the /swarm issue --trace workflow can reach its terminal published state. The trace stops at publication_handoff (the commit-pr directive) until this receipt is observed — publication_handoff is NOT "issue resolved". commit-pr calls this after the PR is created/updated. Supply the traced issue number, the exact PR number, the canonical PR URL (GitHub or GitLab), and (optionally) the published HEAD sha. The receipt is issue-bound.',args:{issueNumber:RecordIssuePublicationArgsSchema.shape.issueNumber,prNumber:RecordIssuePublicationArgsSchema.shape.prNumber,prUrl:RecordIssuePublicationArgsSchema.shape.prUrl,headSha:RecordIssuePublicationArgsSchema.shape.headSha},execute:executeRecordIssuePublication});init_zod();init_utils2();init_atomic_write();init_create_tool();var RecordIssueReproductionArgsSchema=exports_external.object({issueNumber:exports_external.number().int().min(1),performed:exports_external.boolean(),commands:exports_external.array(exports_external.string().min(1)).min(1).optional(),output_summary:exports_external.string().min(1).optional()}).strict();async function executeRecordIssueReproduction(args2,directory,context={}){let parsed=RecordIssueReproductionArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid reproduction receipt: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`});let{issueNumber,performed,commands,output_summary}=parsed.data;if(performed&&(!commands||commands.length===0||!output_summary))return JSON.stringify({success:!1,message:"A performed=true reproduction receipt requires non-empty commands and output_summary."});let receipt={performed,issueNumber,timestamp:new Date().toISOString()};if(commands)receipt.commands=commands;if(output_summary)receipt.output_summary=output_summary;if(context.sessionID?.trim())receipt.sessionId=context.sessionID.trim();let validatedPath;try{validatedPath=validateSwarmPath(directory,"reproduction.json")}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:"Failed to validate path"})}try{return await atomicWriteSwarmFile(validatedPath,JSON.stringify(receipt,null,2)),JSON.stringify({success:!0,issueNumber,performed,path:".swarm/reproduction.json",message:performed?`Reproduction receipt recorded for issue #${issueNumber}; the trace may now transition to PLAN.`:`Reproduction receipt recorded (performed=false) for issue #${issueNumber}; it does NOT satisfy the reproduction gate.`})}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:String(error93)})}}var record_issue_reproduction=createSwarmTool({description:"Record the reproduction outcome for the current traced issue. The /swarm issue --trace workflow requires reproduction evidence (or a typed --no-repro waiver) before it can leave localization and transition to PLAN. Call this with performed=true, the exact commands run, and a concrete output_summary after attempting a minimal reproduction; the receipt binds to issueNumber (and records the calling session) and is read by the issue-trace engine. A performed=true receipt MUST include commands and output_summary. A performed=false receipt is recorded but does NOT satisfy the gate.",args:{issueNumber:RecordIssueReproductionArgsSchema.shape.issueNumber,performed:RecordIssueReproductionArgsSchema.shape.performed,commands:RecordIssueReproductionArgsSchema.shape.commands,output_summary:RecordIssueReproductionArgsSchema.shape.output_summary},execute:executeRecordIssueReproduction});init_zod();init_utils2();init_atomic_write();init_create_tool();var HEX40=/^[0-9a-f]{40}$/,RecordMergeApprovalArgsSchema=exports_external.object({issueNumber:exports_external.number().int().min(1),prHeadSha:exports_external.string().regex(HEX40,"must be a 40-hex commit SHA"),finalCriticReviewedCommit:exports_external.string().regex(HEX40,"must be a 40-hex commit SHA"),userApprovalVerbatim:exports_external.string().trim().min(1).max(8000)}).strict();async function executeRecordMergeApproval(args2,directory,context={}){let parsed=RecordMergeApprovalArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid merge-approval receipt: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`});let data=parsed.data;if(data.prHeadSha!==data.finalCriticReviewedCommit)return JSON.stringify({success:!1,message:"Merge-approval binding failed: prHeadSha must equal finalCriticReviewedCommit (the final critic approval must be bound to the exact PR head)."});let receipt={issueNumber:data.issueNumber,prHeadSha:data.prHeadSha,finalCriticReviewedCommit:data.finalCriticReviewedCommit,userApprovalVerbatim:data.userApprovalVerbatim,timestamp:new Date().toISOString()};if(context.sessionID?.trim())receipt.sessionId=context.sessionID.trim();let validatedPath;try{validatedPath=validateSwarmPath(directory,"merge-approval.json")}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:"Failed to validate path"})}try{return await atomicWriteSwarmFile(validatedPath,JSON.stringify(receipt,null,2)),JSON.stringify({success:!0,issueNumber:data.issueNumber,path:".swarm/merge-approval.json",message:`Merge approval recorded for issue #${data.issueNumber}, bound to PR head ${data.prHeadSha}. The approval is captured verbatim for audit; the merge itself is human-enforced and this plugin neither drives nor certifies it.`})}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:String(error93)})}}var record_merge_approval=createSwarmTool({description:"Record the human merge approval for the current traced issue (issue #2564): prHeadSha and finalCriticReviewedCommit must be the same 40-hex SHA (the final critic approval bound to the exact PR head), and userApprovalVerbatim is the user approval quoted verbatim. The receipt is recorded for audit only — the merge stays human-enforced and the plugin never certifies or drives it.",args:{issueNumber:RecordMergeApprovalArgsSchema.shape.issueNumber,prHeadSha:RecordMergeApprovalArgsSchema.shape.prHeadSha,finalCriticReviewedCommit:RecordMergeApprovalArgsSchema.shape.finalCriticReviewedCommit,userApprovalVerbatim:RecordMergeApprovalArgsSchema.shape.userApprovalVerbatim},execute:executeRecordMergeApproval});init_zod();init_utils2();init_atomic_write();init_create_tool();var DispositionSchema=exports_external.object({ref:exports_external.string().trim().min(1).max(500),disposition:exports_external.enum(["FIX","FALSE_POSITIVE","OUT_OF_CLASS","DEFERRED_WITH_USER_APPROVAL"]),note:exports_external.string().trim().max(1000).optional()}).strict(),GuardrailSchema=exports_external.object({kind:exports_external.enum(["lint-static-analysis","type-level","runtime-assertion","ci-check","documented-invariant-plus-regression-test"]),description:exports_external.string().trim().min(8).max(2000),proof:exports_external.string().trim().min(8).max(4000)}).strict(),RelatedProblemSchema=exports_external.object({ref:exports_external.string().trim().min(1).max(500),note:exports_external.string().trim().max(1000).optional()}).strict(),RecordRecurrenceSweepArgsSchema=exports_external.object({issueNumber:exports_external.number().int().min(1),defectClass:exports_external.string().trim().min(1).max(1000),justification:exports_external.string().trim().min(1).max(1000).optional(),predicates:exports_external.array(exports_external.string().trim().min(1).max(500)).min(1).max(32).optional(),dispositions:exports_external.array(DispositionSchema).min(1).max(200).optional(),guardrail:GuardrailSchema.optional(),relatedProblems:exports_external.array(RelatedProblemSchema).min(1).max(200)}).strict();async function executeRecordRecurrenceSweep(args2,directory,context={}){let parsed=RecordRecurrenceSweepArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid recurrence sweep receipt: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`});let data=parsed.data,noDefectClass=data.defectClass==="no defect class";if(noDefectClass){if(!data.justification)return JSON.stringify({success:!1,message:'The "no defect class" fast path requires a one-line justification.'})}else if(!data.predicates||data.predicates.length===0||!data.dispositions||data.dispositions.length===0||!data.guardrail)return JSON.stringify({success:!1,message:"A defect-class sweep requires search predicates, a non-empty disposition for every hit (at least one — the original defect site itself, dispositioned FIX), and a guardrail with proof it catches the original defect. An empty dispositions array is indistinguishable from a sweep that never ran."});let receipt={issueNumber:data.issueNumber,defectClass:data.defectClass,timestamp:new Date().toISOString()};if(data.justification)receipt.justification=data.justification;if(data.predicates)receipt.predicates=data.predicates;if(data.dispositions)receipt.dispositions=data.dispositions;if(data.guardrail)receipt.guardrail=data.guardrail;if(receipt.relatedProblems=data.relatedProblems,context.sessionID?.trim())receipt.sessionId=context.sessionID.trim();let validatedPath;try{validatedPath=validateSwarmPath(directory,"recurrence-sweep.json")}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:"Failed to validate path"})}try{return await atomicWriteSwarmFile(validatedPath,JSON.stringify(receipt,null,2)),JSON.stringify({success:!0,issueNumber:data.issueNumber,path:".swarm/recurrence-sweep.json",message:noDefectClass?`Recurrence sweep recorded for issue #${data.issueNumber} (no defect class fast path).`:`Recurrence sweep recorded for issue #${data.issueNumber}; the trace may now satisfy its recurrence gate.`})}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:String(error93)})}}var record_recurrence_sweep=createSwarmTool({description:'Record the recurrence sweep for the current traced issue (issue #2131 residual B; widened in #2564 and #2600). The /swarm issue --trace workflow will not hand off to commit-pr until this receipt exists. Supply relatedProblems (the Phase 1 related-problems sweep results — at least one {ref, note?} entry) plus, for a real defect class: defectClass (one-sentence characterization), predicates (the exact search predicates), dispositions (non-empty — every hit as FIX / FALSE_POSITIVE / OUT_OF_CLASS / DEFERRED_WITH_USER_APPROVAL, including the original defect site), and a guardrail (kind + description + proof it catches the original defect). If the change corrects no incorrect behavior, use the literal defectClass "no defect class" with a one-line justification (relatedProblems still required).',args:{issueNumber:RecordRecurrenceSweepArgsSchema.shape.issueNumber,defectClass:RecordRecurrenceSweepArgsSchema.shape.defectClass,justification:RecordRecurrenceSweepArgsSchema.shape.justification,predicates:RecordRecurrenceSweepArgsSchema.shape.predicates,dispositions:RecordRecurrenceSweepArgsSchema.shape.dispositions,guardrail:RecordRecurrenceSweepArgsSchema.shape.guardrail,relatedProblems:RecordRecurrenceSweepArgsSchema.shape.relatedProblems},execute:executeRecordRecurrenceSweep});init_zod();import*as fs227 from"node:fs";init_utils2();init_file_locks();init_atomic_write();init_create_tool();var HEX402=/^[0-9a-f]{40}$/,TRACE_VALIDATION_PHASES2=["0","1","2","2.5","3","4","4.2","4.5","4.6","5"],ValidationEntrySchema=exports_external.object({phase:exports_external.enum(TRACE_VALIDATION_PHASES2),outcome:exports_external.enum(["pass","fail"]),reviewedCommit:exports_external.string().regex(HEX402,"must be a 40-hex commit SHA"),treeId:exports_external.string().regex(HEX402,"must be a 40-hex tree id")}).strict(),RecordTraceValidationArgsSchema=ValidationEntrySchema.extend({issueNumber:exports_external.number().int().min(1)}).strict();async function executeRecordTraceValidation(args2,directory,context={}){let parsed=RecordTraceValidationArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid trace-validation receipt: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`});let data=parsed.data,validatedPath;try{validatedPath=validateSwarmPath(directory,"trace-validation.json")}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:"Failed to validate path"})}try{let lockResult=await tryAcquireLock(directory,"trace-validation.json","trace-validation","trace-validation");if(!lockResult.acquired)return JSON.stringify({success:!1,message:"The trace-validation receipt is locked by another concurrent writer; no write was attempted. Re-run record_trace_validation for this phase once the other writer finishes."});try{let validations=[];try{let raw=await fs227.promises.readFile(validatedPath,"utf-8"),existing=JSON.parse(raw);if(typeof existing==="object"&&existing!==null&&Array.isArray(existing.validations))validations=existing.validations.filter((v)=>typeof v==="object"&&v!==null&&typeof v.phase==="string")}catch{}let entry={phase:data.phase,outcome:data.outcome,reviewedCommit:data.reviewedCommit,treeId:data.treeId,timestamp:new Date().toISOString()},idx=validations.findIndex((v)=>v.phase===data.phase);if(idx===-1)validations.push(entry);else validations[idx]=entry;let receipt={issueNumber:data.issueNumber,timestamp:new Date().toISOString(),validations};if(context.sessionID?.trim())receipt.sessionId=context.sessionID.trim();await atomicWriteSwarmFile(validatedPath,JSON.stringify(receipt,null,2));let allGreen=await traceValidationReceiptExists(directory,data.issueNumber);return JSON.stringify({success:!0,issueNumber:data.issueNumber,path:".swarm/trace-validation.json",allGreen,message:allGreen?`Validator receipt recorded for issue #${data.issueNumber} phase ${data.phase} (${data.outcome}); every recorded phase is green.`:`Validator receipt recorded for issue #${data.issueNumber} phase ${data.phase} (${data.outcome}), but at least one recorded phase is failing — fix and re-record that phase as a pass before handoff.`})}finally{try{await lockResult.lock._release?.()}catch{}}}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:String(error93)})}}var record_trace_validation=createSwarmTool({description:"Record one per-phase trace-check.sh validator outcome for the current traced issue (issue #2564): the phase (v3 enum 0..5 incl. 2.5/4.2/4.5/4.6), the outcome (pass or fail), and the exact reviewedCommit and treeId the validator reported. Re-running a phase replaces its entry. The /swarm issue --trace workflow will not hand off to commit-pr while any recorded phase is failing or none is recorded. The receipt write is serialized by a per-file receipt lock, and the response's allGreen field mirrors the gate reader's verdict on the persisted receipt (advisory for the calling agent — the reducer always recomputes it independently).",args:{issueNumber:RecordTraceValidationArgsSchema.shape.issueNumber,phase:RecordTraceValidationArgsSchema.shape.phase,outcome:RecordTraceValidationArgsSchema.shape.outcome,reviewedCommit:RecordTraceValidationArgsSchema.shape.reviewedCommit,treeId:RecordTraceValidationArgsSchema.shape.treeId},execute:executeRecordTraceValidation});init_zod();init_schema();init_gate_evidence();init_manager();init_path_identity();init_state();init_stage_a_repair();import*as fs228 from"node:fs";import*as path370 from"node:path";async function forceRecoverReworkTask(directory,sessionID,options){let session=ensureAgentSession(sessionID,void 0,directory);if(!session||!session.agentName||stripKnownSwarmPrefix(session.agentName)!=="architect")throw Error("RECOVER_REWORK_ARCHITECT_REQUIRED: recover_rework_task requires an active architect session. The rework escape hatch is architect-only; a coder/reviewer/test_engineer cannot self-unblock a task.");let taskId=typeof options.taskId==="string"?options.taskId.trim():"";if(!taskId)throw Error('RECOVER_REWORK_UNKNOWN_TASK: recover_rework_task requires the exact plan task id (e.g. "1.1").');let plan=await loadPlanJsonOnly(directory);if(!plan){let planPath=path370.join(directory,".swarm","plan.json");if(fs228.existsSync(planPath))throw Error("PLAN_CORRUPT: .swarm/plan.json exists but could not be parsed (corrupt or schema-invalid). Repair or re-save the plan before recovering a rework_required task.");throw Error("PLAN_NOT_FOUND: no .swarm/plan.json — cannot recover a rework_required "+"task without a plan. Save a plan first.")}if(!new Set(plan.phases.flatMap((phase)=>phase.tasks.map((task2)=>task2.id))).has(taskId))throw Error(`RECOVER_REWORK_UNKNOWN_TASK: task ${taskId} is not in the current plan. Refusing to recover a foreign task id.`);let evidenceRead=await readTaskEvidenceState(directory,taskId);if(evidenceRead.kind==="unparseable")throw Error(`RECOVER_REWORK_EVIDENCE_CORRUPT: the workflow evidence file for task ${taskId} exists but could not be parsed (${evidenceRead.evidencePath}). Repair the evidence first (repair_gate_evidence or /swarm doctor); recovery cannot classify a corrupt evidence state.`);let evidence2=evidenceRead.kind==="ok"?evidenceRead.evidence:null,workflow=getTaskWorkflowSnapshot(evidence2);if(!evidence2||!workflow.authoritative)throw Error(`RECOVER_REWORK_NO_WORKFLOW: no durable task workflow evidence exists for task ${taskId} — there is no rework state to recover.`);if(workflow.state!=="rework_required")throw Error(`RECOVER_REWORK_STATE_REQUIRED: task ${taskId} is at ${workflow.state}, not rework_required. This recovery applies only to a task whose Stage B verdict moved it to rework_required without a code change. From coder_delegated, run pre_check_batch; for a genuine code defect, delegate the coder to repair it first.`);let wedgeMs=Date.parse(workflow.updatedAt);if(!Number.isFinite(wedgeMs))throw Error(`RECOVER_REWORK_GREEN_PRECHECK_REQUIRED: cannot prove pre-check recency (workflow updatedAt "${workflow.updatedAt}" is not a parseable timestamp — the evidence file for task ${taskId} is likely corrupt). Repair the evidence (repair_gate_evidence or /swarm doctor); re-running pre_check_batch cannot fix an unparseable timestamp.`);let greenness=await hasGreenPostSettlementPreCheck(directory,wedgeMs);if(!greenness.green){let sastHint=greenness.reason==="no_pre_check_bundles"?" Note: if gates.sast_scan.enabled is false, no sast_scan bundle is ever persisted and this recovery is unavailable by design — enable gates.sast_scan.enabled and run sast_scan, or use the coder repair loop.":"";throw Error(`RECOVER_REWORK_GREEN_PRECHECK_REQUIRED: refusing to mark Stage A passed without proof (${greenness.reason}). `+"The bar is a green secretscan AND sast_scan evidence pair newer than the failing verdict — normally provided by a fresh pre_check_batch run (bundle proof is global, not correlated to the task's changed files)."+sastHint)}let sanitizedReason=typeof options.reason==="string"&&options.reason.trim().length>0?sanitizeDiagnosticText(options.reason.trim(),500):void 0,recordedAt=new Date().toISOString(),transitionId=`rework-recovery:${taskId}:gen${workflow.generation}`,updated=await transitionTaskWorkflowEvidence(directory,taskId,{type:"stage_a_passed",supervisedRecovery:!0,expectedGeneration:workflow.generation,transitionId}),updatedWorkflow=getTaskWorkflowSnapshot(updated),auditEventRecorded=await appendStageARepairEvent(directory,{action:"rework_recovered",taskId,transitionId,generation:workflow.generation,sessionId:sessionID,...sanitizedReason?{reason:sanitizedReason}:{}});return{taskId,generation:updatedWorkflow.generation,state:updatedWorkflow.state,transitionId,recordedAt,auditEventRecorded}}init_create_tool();var RecoverReworkTaskArgsSchema=exports_external.object({task_id:exports_external.string().trim().min(1).max(64).describe('Exact plan task id of the rework_required task (e.g. "1.1"). Must exist in the current plan and have durable workflow evidence at state rework_required.'),reason:exports_external.string().trim().min(1).max(500).describe('Why the Stage B verdict did not require a code change (e.g. "test_engineer returned SKIPPED for a tool-argument error while pytest passes"). Audited to .swarm/events.jsonl.')}).strict();async function executeRecoverReworkTask(args2,directory,context={}){let parsed=RecoverReworkTaskArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid recover_rework_task call: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`});if(!context.sessionID?.trim())return JSON.stringify({success:!1,message:"recover_rework_task requires an active sessionID"});try{let summary=await forceRecoverReworkTask(directory,context.sessionID,{taskId:parsed.data.task_id,reason:parsed.data.reason}),auditNote=summary.auditEventRecorded?"The recovery is audited to .swarm/events.jsonl (stage_a_repair action rework_recovered).":"WARNING: the audit event could NOT be appended to .swarm/events.jsonl (see the plugin log); the durable workflow evidence still records the supervised recovery via the rework-recovery: transition id.";return JSON.stringify({success:!0,task_id:summary.taskId,generation:summary.generation,state:summary.state,transition_id:summary.transitionId,recorded_at:summary.recordedAt,audit_event_recorded:summary.auditEventRecorded,method:"supervised_recovery",message:`Task ${summary.taskId} recovered from rework_required: a supervised stage_a_passed was written at generation ${summary.generation} (transition id `+summary.transitionId+"). Reviewer/test_engineer dispatch is permitted again — re-run the Stage B gates that the failed verdict cleared. "+auditNote+" Use it ONLY when the Stage B verdict did not require a code change; a genuine defect still needs the coder repair loop."})}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:String(error93)})}}var recover_rework_task=createSwarmTool({description:"Recover a task wedged at rework_required when the Stage B verdict did NOT require a code change (issue #2755): writes a supervised stage_a_passed for the current generation so reviewer/test_engineer can be re-dispatched, without re-running the coder. Requires the exact plan task id, an active architect session, durable workflow state exactly rework_required, and green pre-check proof: green secretscan AND sast_scan evidence bundles newer than the failing verdict (normally from a fresh pre_check_batch run; bundle recency is global, not file-correlated; projects with SAST disabled cannot use this path). Fail-closed otherwise; the mechanical stage_a_passed path still requires an accepted coder mutation. A reason is required and audited to .swarm/events.jsonl (stage_a_repair action rework_recovered). Prefer the coder repair loop when the code actually has a defect.",args:{task_id:RecoverReworkTaskArgsSchema.shape.task_id,reason:RecoverReworkTaskArgsSchema.shape.reason},execute:executeRecoverReworkTask});init_zod();init_schema();init_gate_evidence();init_path_identity();init_state();init_coder_settlement();init_session_view();init_stage_a_repair();async function recoverStageATaskSupervised(directory,sessionID,options){let session=ensureAgentSession(sessionID,void 0,directory);if(!session||!session.agentName||stripKnownSwarmPrefix(session.agentName)!=="architect")throw Error("RECOVER_STAGE_A_ARCHITECT_REQUIRED: recover_stage_a_task requires an active architect session. The settlement-backed Stage A escape hatch is architect-only; a coder/reviewer/test_engineer cannot self-unblock a task.");let taskId=typeof options.taskId==="string"?options.taskId.trim():"";if(!taskId)throw Error('RECOVER_STAGE_A_UNKNOWN_TASK: recover_stage_a_task requires the exact task id of the settlement-wedged task (e.g. "1.1").');let sanitizedReason=typeof options.reason==="string"&&options.reason.trim().length>0?sanitizeDiagnosticText(options.reason.trim(),500):void 0;if(!sanitizedReason)throw Error("RECOVER_STAGE_A_REASON_REQUIRED: recover_stage_a_task requires a reason describing why the settlement-backed recovery is justified; it is audited to .swarm/events.jsonl.");let evidenceRead=await readTaskEvidenceState(directory,taskId);if(evidenceRead.kind==="unparseable")throw Error(`RECOVER_STAGE_A_EVIDENCE_CORRUPT: the workflow evidence file for task ${taskId} exists but could not be parsed (${evidenceRead.evidencePath}). Repair the evidence first (repair_gate_evidence or /swarm doctor); recovery cannot classify a corrupt evidence state.`);let evidence2=evidenceRead.kind==="ok"?evidenceRead.evidence:null,workflow=getTaskWorkflowSnapshot(evidence2);if(!evidence2||!workflow.authoritative)throw Error(`RECOVER_STAGE_A_NO_WORKFLOW: no durable task workflow evidence exists for task ${taskId} — there is no settlement wedge to recover.`);if(workflow.state==="pre_check_passed"||workflow.state==="reviewer_run"||workflow.state==="tests_run"){if(isStageARecoveredState(workflow.state)&&shouldRefreshStageARecoveryView(session.taskWorkflowStates.get(taskId),workflow.state))applySessionWorkflowView(session,taskId,workflow);return{taskId,generation:workflow.generation,state:workflow.state,transitionId:`stage-a-supervised:${taskId}:noop`,recordedAt:new Date().toISOString(),alreadyRecovered:!0,auditEventRecorded:!1}}if(workflow.state!=="idle"&&workflow.state!=="blocked")throw Error(`RECOVER_STAGE_A_STATE_REQUIRED: task ${taskId} is at ${workflow.state}, not idle/blocked. This recovery applies only to the settlement-backed wedge (a COMMITTED accepted coder settlement while the workflow drifted to idle or blocked). From coder_delegated, run pre_check_batch or /swarm recover; from rework_required without a code change, use recover_rework_task.`);let{states:walStates}=await listCoderSettlementWalStates(directory),settledAfterMs=latestCommittedAcceptedSettlementMs(taskId,walStates);if(settledAfterMs===null)throw Error(`RECOVER_STAGE_A_SETTLEMENT_REQUIRED: refusing to recover task ${taskId} — no COMMITTED accepted coder settlement exists for it. `+"The settlement receipt is what distinguishes this wedge from a not-yet-started or deliberately stopped task; recovery without it would fabricate Stage A justification. Background-dispatched coder tasks never write a settlement WAL and cannot use this path.");let greenness=await hasGreenPostSettlementPreCheck(directory,settledAfterMs);if(!greenness.green){let sastHint=greenness.reason==="no_pre_check_bundles"?" Note: if gates.sast_scan.enabled is false, no sast_scan bundle is ever persisted and this recovery is unavailable by design — enable gates.sast_scan.enabled and run sast_scan, or use the coder repair loop.":"";throw Error(`RECOVER_STAGE_A_GREEN_PRECHECK_REQUIRED: refusing to mark Stage A passed without proof (${greenness.reason}). `+"The bar is a green secretscan AND sast_scan evidence pair newer than the settlement commit — normally provided by a fresh pre_check_batch run (bundle proof is global, not correlated to the task's changed files)."+sastHint)}let recordedAt=new Date().toISOString(),transitionId=`stage-a-supervised:${taskId}:${workflow.generation}`,updated=await transitionTaskWorkflowEvidence(directory,taskId,{type:"stage_a_passed",settlementRecovery:!0,expectedGeneration:workflow.generation,transitionId}),updatedWorkflow=getTaskWorkflowSnapshot(updated);if(isStageARecoveredState(updatedWorkflow.state)){if(shouldRefreshStageARecoveryView(session.taskWorkflowStates.get(taskId),updatedWorkflow.state))applySessionWorkflowView(session,taskId,updatedWorkflow)}let auditEventRecorded=await appendStageARepairEvent(directory,{action:"repaired",via:"recover_stage_a_task",taskId,transitionId,generation:workflow.generation,settlementRecovery:!0,predecessorTransitionId:workflow.lastTransitionId??null,sessionId:sessionID,reason:sanitizedReason});return{taskId,generation:updatedWorkflow.generation,state:updatedWorkflow.state,transitionId,recordedAt,alreadyRecovered:!1,auditEventRecorded}}init_create_tool();var RecoverStageATaskArgsSchema=exports_external.object({task_id:exports_external.string().trim().min(1).max(64).describe('Exact task id of the settlement-wedged task (e.g. "1.1"). Must have durable workflow evidence at state idle or blocked, a COMMITTED accepted coder settlement, and green post-settlement pre-check proof.'),reason:exports_external.string().trim().min(1).max(500).describe('Why the settlement-backed recovery is justified (e.g. "settlement COMMITTED and pre_check_batch green but stage_a_passed never fired; force-repair cleared the proofs"). Audited to .swarm/events.jsonl.')}).strict();async function executeRecoverStageATask(args2,directory,context={}){let parsed=RecoverStageATaskArgsSchema.safeParse(args2);if(!parsed.success)return JSON.stringify({success:!1,message:`Invalid recover_stage_a_task call: ${parsed.error.issues.map((issue3)=>`${issue3.path.join(".")}: ${issue3.message}`).join("; ")}`});if(!context.sessionID?.trim())return JSON.stringify({success:!1,message:"recover_stage_a_task requires an active sessionID"});try{let summary=await recoverStageATaskSupervised(directory,context.sessionID,{taskId:parsed.data.task_id,reason:parsed.data.reason});if(summary.alreadyRecovered)return JSON.stringify({success:!0,task_id:summary.taskId,generation:summary.generation,state:summary.state,already_recovered:!0,message:`Task ${summary.taskId} already has Stage A recorded (state ${summary.state}, generation ${summary.generation}) — nothing to recover.`});let auditNote=summary.auditEventRecorded?"The recovery is audited to .swarm/events.jsonl (stage_a_repair action repaired, via recover_stage_a_task).":"WARNING: the audit event could NOT be appended to .swarm/events.jsonl (see the plugin log); the durable workflow evidence still records the settlement-backed recovery via the stage-a-supervised: transition id and the settlementRecovery marker.";return JSON.stringify({success:!0,task_id:summary.taskId,generation:summary.generation,state:summary.state,transition_id:summary.transitionId,recorded_at:summary.recordedAt,audit_event_recorded:summary.auditEventRecorded,method:"settlement_recovery",message:`Task ${summary.taskId} recovered from the settlement wedge: a settlement-backed stage_a_passed was written at generation ${summary.generation} (transition id `+summary.transitionId+"). Reviewer/test_engineer dispatch is permitted again — run the Stage B gates the task still needs. "+auditNote+" Use it ONLY when a COMMITTED accepted settlement and green post-settlement pre-check proof already justify Stage A; it never re-runs the coder and never edits gate evidence."})}catch(error93){return JSON.stringify({success:!1,message:error93 instanceof Error?error93.message:String(error93)})}}var recover_stage_a_task=createSwarmTool({description:"Recover a task wedged in the settlement-backed Stage A deadlock (issue #2828): workflow at idle or blocked while a COMMITTED accepted coder settlement and green post-settlement pre-check proof (green secretscan AND sast_scan evidence newer than the settlement commit) still justify Stage A — the shape where stage_a_passed never fired, a force-repair cleared the proofs, and every other recovery path refuses. Writes a settlement-backed stage_a_passed for the current generation so reviewer/test_engineer can be dispatched, without re-running the coder and without editing gate evidence. Requires the exact task id (bound by its durable workflow evidence and settlement WAL — deliberately no plan-membership precondition, mirroring the /swarm recover scan), an active architect session, a reason (audited), and durable workflow evidence at exactly idle/blocked. Fail-closed otherwise (RECOVER_STAGE_A_* errors); the mechanical stage_a_passed path still requires an accepted coder mutation or the #2665 live_wedge scan.",args:{task_id:RecoverStageATaskArgsSchema.shape.task_id,reason:RecoverStageATaskArgsSchema.shape.reason},execute:executeRecoverStageATask});init_zod();init_schema();init_gate_evidence();init_utils2();init_manager();init_utils3();init_state();init_project_boundary();init_swarm_artifact_cache();init_task_id();init_task_file();init_task_gate_requirements();init_gate_evidence();import{createHash as createHash120,randomUUID as randomUUID48}from"node:crypto";import*as fs229 from"node:fs";import*as path371 from"node:path";var TASK_GATE_EVIDENCE_QUARANTINE_DIR=path371.join("evidence","task-gate-quarantine"),MAX_TASK_GATE_EVIDENCE_BYTES=262144,MAX_TASK_GATE_EVIDENCE_QUARANTINE_FILES=32,MAX_TASK_GATE_EVIDENCE_QUARANTINE_BYTES=12582912,MAX_TASK_GATE_EVIDENCE_QUARANTINE_DIRECTORY_ENTRIES=128,MAX_TASK_GATE_EVIDENCE_QUARANTINE_RECORD_BYTES=786432,TASK_GATE_EVIDENCE_QUARANTINE_SCHEMA_VERSION=1,GENERIC_REPAIR_REASONS=new Set(["fix","repair","test","debug","unknown","n/a","na","none"]);function isQuarantinableTaskEvidenceRead(read){return read.status==="corrupt"||read.status==="valid"}function sha25614(bytes){return createHash120("sha256").update(bytes).digest("hex")}function normalizeRepairReason(reason){let normalized=reason.trim().replace(/\s+/g," ");if(normalized.length<12)throw Error("TASK_GATE_EVIDENCE_REASON_REQUIRED: repair_gate_evidence requires a substantive reason of at least 12 characters.");if(GENERIC_REPAIR_REASONS.has(normalized.toLowerCase()))throw Error("TASK_GATE_EVIDENCE_REASON_REQUIRED: repair_gate_evidence requires a substantive reason, not a placeholder.");return normalized}function canonicalizeRepairRoot(directory){let requestedRoot=path371.resolve(directory),requestedStat=fs229.lstatSync(requestedRoot);if(requestedStat.isSymbolicLink()||!requestedStat.isDirectory())throw Error("TASK_GATE_EVIDENCE_ROOT_UNSAFE: repair_gate_evidence requires a canonical project root directory, not a symlink, junction, reparse point, or non-directory path.");let canonicalRoot2=fs229.realpathSync(requestedRoot);return assertProjectRoot(canonicalRoot2),canonicalRoot2}function assertExistingRegularPath(root,relativePath2){let segments=relativePath2.replace(/\\/g,"/").split("/").filter(Boolean),cursor=root;for(let segment of segments){if(cursor=path371.join(cursor,segment),!fs229.existsSync(cursor))return;if(fs229.lstatSync(cursor).isSymbolicLink())throw Error(`TASK_GATE_EVIDENCE_PATH_UNSAFE: ${relativePath2} contains a symlink, junction, or reparse point.`)}}function taskEvidenceFilePath(directory,taskId){let relativePath2=taskEvidenceRelPath(taskId);return assertExistingRegularPath(directory,".swarm"),assertExistingRegularPath(directory,path371.join(".swarm","evidence")),assertExistingRegularPath(directory,path371.join(".swarm",relativePath2)),validateSwarmPath(directory,relativePath2)}function readTaskEvidenceForRepair(directory,taskId){let filePath=taskEvidenceFilePath(directory,taskId),pathStat;try{pathStat=fs229.lstatSync(filePath)}catch(error93){if(error93.code==="ENOENT")return{status:"missing"};return{status:"unreadable",filePath,bytes:Buffer.alloc(0),sha256:sha25614(""),error:error93}}if(pathStat.isSymbolicLink()||!pathStat.isFile())return{status:"unreadable",filePath,bytes:Buffer.alloc(0),sha256:sha25614(""),error:Error("TASK_GATE_EVIDENCE_UNREADABLE: evidence path is not a regular file")};if(pathStat.size>MAX_TASK_GATE_EVIDENCE_BYTES)return{status:"oversized",filePath,bytes:Buffer.alloc(0),sha256:sha25614(""),error:Error(`TASK_GATE_EVIDENCE_OVERSIZED: ${pathStat.size} bytes exceeds ${MAX_TASK_GATE_EVIDENCE_BYTES}`)};let descriptor=fs229.openSync(filePath,fs229.constants.O_RDONLY|(fs229.constants.O_NOFOLLOW??0));try{let openedStat=fs229.fstatSync(descriptor);if(!openedStat.isFile()||openedStat.dev!==pathStat.dev||openedStat.ino!==pathStat.ino)return{status:"unreadable",filePath,bytes:Buffer.alloc(0),sha256:sha25614(""),error:Error("TASK_GATE_EVIDENCE_UNREADABLE: evidence changed while being opened")};let bytes=fs229.readFileSync(descriptor);if(bytes.byteLength>MAX_TASK_GATE_EVIDENCE_BYTES)return{status:"oversized",filePath,bytes:Buffer.alloc(0),sha256:sha25614(""),error:Error(`TASK_GATE_EVIDENCE_OVERSIZED: ${bytes.byteLength} bytes exceeds ${MAX_TASK_GATE_EVIDENCE_BYTES}`)};let digest5=sha25614(bytes);try{let evidence2=parseTaskEvidence(bytes.toString("utf8"),taskId);return{status:"valid",filePath,bytes,sha256:digest5,evidence:evidence2,generation:evidence2.workflow?.generation}}catch(error93){return{status:"corrupt",filePath,bytes,sha256:digest5,error:error93}}}finally{try{fs229.closeSync(descriptor)}catch{}}}function taskGateEvidenceQuarantinePath(directory,taskId,digest5){return validateSwarmPath(directory,path371.join(TASK_GATE_EVIDENCE_QUARANTINE_DIR,`${taskId}.${digest5}.v${TASK_GATE_EVIDENCE_QUARANTINE_SCHEMA_VERSION}.json`))}function parseErrorMetadata(error93){if(!error93)return null;return{name:error93.name||"Error",message:error93.message||String(error93),code:typeof error93.code==="string"?error93.code:null}}function parseQuarantineRecord(raw){try{let parsed=JSON.parse(raw);if(parsed?.schemaVersion!==TASK_GATE_EVIDENCE_QUARANTINE_SCHEMA_VERSION||typeof parsed.taskId!=="string"||typeof parsed.recordedAt!=="string"||typeof parsed.reason!=="string"||typeof parsed.original?.path!=="string"||typeof parsed.original?.sha256!=="string"||typeof parsed.content?.bytes!=="string"||parsed.content?.encoding!=="base64")return null;return parsed}catch{return null}}function buildQuarantineRecord(taskId,read,reason,context,receiptGeneration){let agentName=context?.sessionID!=null?swarmState.activeAgent.get(context.sessionID)??swarmState.agentSessions.get(context.sessionID)?.agentName??null:null;return{schemaVersion:TASK_GATE_EVIDENCE_QUARANTINE_SCHEMA_VERSION,taskId,recordedAt:new Date().toISOString(),reason,caller:{sessionId:context?.sessionID?.trim()||null,messageId:context?.messageID?.trim()||null,agentName},original:{path:read.filePath,sha256:read.sha256,sizeBytes:read.bytes.byteLength,status:read.status,observedGeneration:read.generation??null,receiptGeneration,requirementsState:read.evidence?.requirements_state??null},parseError:parseErrorMetadata(read.error),content:{encoding:"base64",bytes:read.bytes.toString("base64")}}}async function quarantineTaskEvidenceBytes(directory,taskId,read,reason,context,receiptGeneration){let digest5=read.sha256,quarantineDir=validateSwarmPath(directory,TASK_GATE_EVIDENCE_QUARANTINE_DIR);await fs229.promises.mkdir(quarantineDir,{recursive:!0});let dirStat=await fs229.promises.lstat(quarantineDir);if(dirStat.isSymbolicLink()||!dirStat.isDirectory())throw Error("TASK_GATE_EVIDENCE_QUARANTINE_UNREADABLE: quarantine is not a regular directory");let target=taskGateEvidenceQuarantinePath(directory,taskId,digest5),record3=buildQuarantineRecord(taskId,read,reason,context,receiptGeneration),serialized3=JSON.stringify(record3,null,2),serializedBytes=Buffer.byteLength(serialized3,"utf8");if(serializedBytes>MAX_TASK_GATE_EVIDENCE_QUARANTINE_RECORD_BYTES)throw Error("TASK_GATE_EVIDENCE_QUARANTINE_FULL: quarantine payload exceeds the bounded record size limit");let reconcileExisting=async()=>{let existingStat;try{existingStat=await fs229.promises.lstat(target)}catch(error93){if(error93.code==="ENOENT")return!1;throw error93}if(existingStat.isSymbolicLink()||!existingStat.isFile())throw Error("TASK_GATE_EVIDENCE_QUARANTINE_MISMATCH: existing quarantine path is not a regular immutable record");let existingRaw=await fs229.promises.readFile(target,"utf8"),existingRecord=parseQuarantineRecord(existingRaw);if(existingRecord&&existingRecord.taskId===taskId&&existingRecord.original.path===read.filePath&&existingRecord.original.sha256===read.sha256&&existingRecord.content.bytes===read.bytes.toString("base64"))return!0;throw Error("TASK_GATE_EVIDENCE_QUARANTINE_MISMATCH: existing quarantine record does not match the repaired evidence source")};if(await reconcileExisting())return{digest:digest5,filePath:target};let count4=0,totalBytes=0,scanned=0,handle=await fs229.promises.opendir(quarantineDir,{bufferSize:16});try{for await(let entry of handle){if(scanned+=1,scanned>MAX_TASK_GATE_EVIDENCE_QUARANTINE_DIRECTORY_ENTRIES)throw Error("TASK_GATE_EVIDENCE_QUARANTINE_FULL: too many quarantine entries");if(!entry.isFile()||!/^[0-9.]+\.[a-f0-9]{64}\.v1\.json$/.test(entry.name))continue;count4+=1;let candidate2=path371.join(quarantineDir,entry.name),candidateStat=await fs229.promises.lstat(candidate2);if(candidateStat.isSymbolicLink()||!candidateStat.isFile())throw Error("TASK_GATE_EVIDENCE_QUARANTINE_UNREADABLE: invalid quarantine artifact");if(totalBytes+=candidateStat.size,count4>=MAX_TASK_GATE_EVIDENCE_QUARANTINE_FILES||totalBytes+serializedBytes>MAX_TASK_GATE_EVIDENCE_QUARANTINE_BYTES)throw Error("TASK_GATE_EVIDENCE_QUARANTINE_FULL: quarantine retention limit reached")}}finally{try{await handle.close()}catch{}}let tempPath=path371.join(quarantineDir,`.pending.${process.pid}.${randomUUID48()}.json`),fileHandle;try{fileHandle=await fs229.promises.open(tempPath,"wx"),await fileHandle.writeFile(serialized3,"utf8"),await fileHandle.sync(),await fileHandle.close(),fileHandle=void 0,invalidateCachedArtifact(tempPath),await fs229.promises.link(tempPath,target),invalidateCachedArtifact(target)}catch(error93){if(error93.code!=="EEXIST")throw error93;if(await reconcileExisting())return{digest:digest5,filePath:target};throw error93}finally{await fileHandle?.close().catch(()=>{return}),await fs229.promises.unlink(tempPath).catch(()=>{return})}return{digest:digest5,filePath:target}}function buildRepairTransitionId(taskId,source){return`repair_gate_evidence:${taskId}:${source.slice(0,32)}`}function withoutLegacyReconstructionGate(gates){return[...new Set(gates.filter((gate)=>gate!==TASK_GATE_REQUIREMENTS_RECONSTRUCTION_SENTINEL))].sort()}function hasLegacyReconstructionGate(gates){return gates.includes(TASK_GATE_REQUIREMENTS_RECONSTRUCTION_SENTINEL)}function buildKnownRepairedEvidence(taskId,receipt,generation,source){let requiredGates=withoutLegacyReconstructionGate(receipt.requiredGates);if(requiredGates.length!==receipt.requiredGates.length)throw Error("TASK_GATE_REQUIREMENTS_RECEIPT_TAINTED: legacy reconstruction markers cannot seed known requirements.");return{taskId,required_gates:requiredGates,gates:{},requirements_state:"known",test_engineer_exempt:receipt.testEngineerExempt??void 0,workflow:{schema:TASK_WORKFLOW_SCHEMA_MARKER,generation,state:"idle",retryCount:0,retryHistory:[],retryEpoch:0,lastOutcome:"repair_idle",lastTransitionId:buildRepairTransitionId(taskId,receipt.chainHash),updatedAt:new Date().toISOString()},repair_provenance:{source_sha256:source.sha256,source_generation:source.generation,requirements_receipt_hash:receipt.chainHash}}}function buildUnknownRepairedEvidence(taskId,requiredGates,seedGeneration,source,receiptHash){return{taskId,required_gates:withoutLegacyReconstructionGate(requiredGates),gates:{},requirements_state:"unknown",workflow:{schema:TASK_WORKFLOW_SCHEMA_MARKER,generation:seedGeneration,state:"idle",retryCount:0,retryHistory:[],retryEpoch:0,lastOutcome:"repair_idle",lastTransitionId:buildRepairTransitionId(taskId,"unknown"),updatedAt:new Date().toISOString()},repair_provenance:{source_sha256:source.sha256,source_generation:source.generation,requirements_receipt_hash:receiptHash}}}function canonicalizeTaskEvidence(taskId,evidence2){let validated=parseTaskEvidence(JSON.stringify({...evidence2,taskId}),taskId);return JSON.stringify(validated,null,2)}function isRepairWorkflowReset(taskId,workflow){return workflow!=null&&workflow.state==="idle"&&workflow.retryCount===0&&workflow.retryEpoch===0&&workflow.retryHistory.length===0&&workflow.lastOutcome==="repair_idle"&&typeof workflow.lastTransitionId==="string"&&workflow.lastTransitionId.startsWith(`repair_gate_evidence:${taskId}:`)}function isReceiptlessLegacySentinelReset(taskId,evidence2){return evidence2!=null&&isRepairWorkflowReset(taskId,evidence2.workflow)&&evidence2.requirements_state==="unknown"&&evidence2.required_gates.length===1&&evidence2.required_gates[0]===TASK_GATE_REQUIREMENTS_RECONSTRUCTION_SENTINEL&&Object.keys(evidence2.gates).length===0&&evidence2.repair_provenance!=null&&typeof evidence2.repair_provenance.source_sha256==="string"&&(evidence2.repair_provenance.source_generation===null||evidence2.repair_provenance.source_generation<evidence2.workflow.generation)&&evidence2.repair_provenance.requirements_receipt_hash===null}function isAlreadyRepairedEvidence(taskId,evidence2,receipt){if(!evidence2||!isRepairWorkflowReset(taskId,evidence2.workflow))return!1;if(Object.keys(evidence2.gates).length!==0)return!1;if(hasLegacyReconstructionGate(evidence2.required_gates))return!1;let receiptIsTainted=receipt!=null&&hasLegacyReconstructionGate(receipt.requiredGates);if(receipt&&!receiptIsTainted)return evidence2.requirements_state==="known"&&JSON.stringify(evidence2.required_gates)===JSON.stringify(receipt.requiredGates)&&evidence2.workflow.generation>receipt.generation&&(evidence2.test_engineer_exempt??null)===(receipt.testEngineerExempt??null)&&evidence2.repair_provenance?.requirements_receipt_hash===receipt.chainHash;if(!receipt||!receiptIsTainted)return!1;return evidence2.requirements_state==="unknown"&&evidence2.workflow.generation>=1&&evidence2.repair_provenance!=null&&evidence2.repair_provenance.requirements_receipt_hash===receipt.chainHash&&withoutLegacyReconstructionGate(receipt.requiredGates).every((gate)=>evidence2.required_gates.includes(gate))}function repairedEvidenceMatchesCas(evidence2,args2){let provenance=evidence2.repair_provenance;if(!provenance)return args2.expected_sha256==null&&args2.expected_generation==null;return(args2.expected_sha256==null||provenance.source_sha256===args2.expected_sha256)&&(args2.expected_generation==null||provenance.source_generation===args2.expected_generation)}function buildRepairNextActions(taskId,evidence2){if(evidence2.requirements_state==="known")return[`Delegate coder on task ${taskId} to produce a fresh accepted_mutation for the repaired evidence generation ${evidence2.workflow?.generation}.`,`Rerun Stage A for task ${taskId} until pre_check passes for the new generation.`,`Rerun Stage B gates [${evidence2.required_gates.join(", ")}] for task ${taskId} before attempting completion again.`];return[`Delegate coder on task ${taskId} to produce a fresh accepted mutation and regenerate authoritative required gates for a new exact-task generation.`,`Rerun Stage A for task ${taskId} after the new mutation is recorded.`,`Rerun the exact Stage B gates for task ${taskId} only after authoritative required gates are re-recorded; the idle recovery generation cannot complete directly.`]}function invalidateTaskEvidenceSessionFallbacks(taskId){for(let session of swarmState.agentSessions.values()){if(session.currentTaskId===taskId)session.currentTaskId=null;if(session.lastCoderDelegationTaskId===taskId)session.lastCoderDelegationTaskId=null;if(session.taskWorkflowStates?.delete(taskId),session.taskWorkflowCache?.delete(taskId),session.stageBCompletion?.delete(taskId),session.taskCouncilApproved?.delete(taskId),session.taskCouncilWorkflowGeneration?.delete(taskId),session.gateLog?.delete(taskId),session.partialGateWarningsIssuedForTask?.delete(taskId),session.completionGateWarnedForTask?.delete(taskId),session.lastGateFailure?.taskId===taskId)session.lastGateFailure=null}}async function repairTaskGateEvidence(args2,directory,context){assertStrictTaskId(args2.task_id);let normalizedReason=normalizeRepairReason(args2.reason),canonicalDirectory=canonicalizeRepairRoot(directory),plan=await loadPlan(canonicalDirectory);if(!plan?.phases.flatMap((phase)=>phase.tasks).find((candidate2)=>candidate2.id===args2.task_id))return{success:!1,message:`TASK_GATE_EVIDENCE_TASK_MISSING: ${args2.task_id} is not present in the loaded plan`,errors:[`Task ${args2.task_id} is not present in .swarm/plan.json.`]};return withTaskEvidenceLock(canonicalDirectory,args2.task_id,"repair_gate_evidence",async()=>{let read=readTaskEvidenceForRepair(canonicalDirectory,args2.task_id),latestReceipt=(await readTaskGateRequirementsReceipts(canonicalDirectory,args2.task_id)).at(-1),evidenceHasLegacyMarker=read.status==="valid"&&read.evidence!=null&&hasLegacyReconstructionGate(read.evidence.required_gates),receiptHasLegacyMarker=latestReceipt!=null&&hasLegacyReconstructionGate(latestReceipt.requiredGates);if(read.status==="valid"&&isAlreadyRepairedEvidence(args2.task_id,read.evidence,latestReceipt)){if(!repairedEvidenceMatchesCas(read.evidence,args2))return{success:!1,message:"TASK_GATE_EVIDENCE_CAS_MISMATCH",errors:["TASK_GATE_EVIDENCE_CAS_MISMATCH: the existing repaired generation was created from a different source identity."]};let nextActions2=buildRepairNextActions(args2.task_id,read.evidence);return{success:!0,repaired:!1,task_id:args2.task_id,required_gates:[...read.evidence.required_gates],requirements_state:read.evidence.requirements_state,repaired_generation:read.evidence.workflow?.generation,next_actions:nextActions2,message:`Task gate evidence for ${args2.task_id} is already in repaired fail-closed state.`}}if(read.status==="valid"&&read.evidence?.workflow?.schema===TASK_WORKFLOW_SCHEMA_MARKER&&!evidenceHasLegacyMarker&&latestReceipt!=null&&!receiptHasLegacyMarker&&!evidenceStampedForDifferentPlan(read.evidence,plan?derivePlanIdentityHash(plan):null))return{success:!1,message:"TASK_GATE_EVIDENCE_REPAIR_NOT_REQUIRED",errors:[`TASK_GATE_EVIDENCE_REPAIR_NOT_REQUIRED: ${args2.task_id} has valid authoritative evidence. Use the normal workflow repair path; this tool only rebuilds corrupt or legacy evidence, or evidence stamped for a different plan than the current .swarm/plan.json.`]};if(read.status==="valid"&&read.evidence?.requirements_state==="known"&&!evidenceHasLegacyMarker&&receiptHasLegacyMarker)return{success:!1,message:"TASK_GATE_REQUIREMENTS_RECEIPT_STALE",errors:[`TASK_GATE_REQUIREMENTS_RECEIPT_STALE: ${args2.task_id} has clean accepted-mutation evidence but its latest requirements receipt is legacy-tainted. Repair was refused without modifying evidence; replay the prepared coder settlement so it can publish the exact hash-linked receipt.`]};if(typeof args2.expected_sha256==="string"&&read.status!=="missing"&&read.sha256!==args2.expected_sha256)return{success:!1,message:"TASK_GATE_EVIDENCE_CAS_MISMATCH",errors:[`TASK_GATE_EVIDENCE_CAS_MISMATCH: expected sha256 ${args2.expected_sha256}, found ${read.sha256}.`]};if(typeof args2.expected_generation==="number"){let observedGeneration=read.status==="valid"?read.generation:latestReceipt?.generation;if(observedGeneration!==args2.expected_generation)return{success:!1,message:"TASK_GATE_EVIDENCE_CAS_MISMATCH",errors:[`TASK_GATE_EVIDENCE_CAS_MISMATCH: expected generation ${args2.expected_generation}, found ${observedGeneration??"unknown"}.`]}}if(read.status==="unreadable"||read.status==="oversized")return{success:!1,message:read.error?.message??"TASK_GATE_EVIDENCE_UNREADABLE: repair requires operator intervention before evidence can be rewritten.",errors:[read.error?.message??`TASK_GATE_EVIDENCE_UNREADABLE: ${args2.task_id} could not be read safely for repair.`]};if(evidenceHasLegacyMarker&&latestReceipt==null&&!isReceiptlessLegacySentinelReset(args2.task_id,read.evidence))return{success:!1,message:"TASK_GATE_REQUIREMENTS_RECEIPT_MISSING",errors:[`TASK_GATE_REQUIREMENTS_RECEIPT_MISSING: ${args2.task_id} is marker-bearing but does not match the exact receipt-less state emitted by the historical repair flow. Repair was refused without modifying evidence or session state.`]};let nextGeneration2=Math.max(read.status==="valid"?read.generation??-1:-1,latestReceipt?.generation??-1)+1,nextEvidence;if(evidenceHasLegacyMarker||receiptHasLegacyMarker){let preservedGates=withoutLegacyReconstructionGate([...read.status==="valid"?read.evidence?.required_gates??[]:[],...latestReceipt?.requiredGates??[]]);nextEvidence=buildUnknownRepairedEvidence(args2.task_id,preservedGates,Math.max(nextGeneration2,1),{sha256:read.status==="missing"?null:read.sha256,generation:read.status==="valid"?read.generation??null:latestReceipt?.generation??null},latestReceipt?.chainHash??null)}else if(latestReceipt)nextEvidence=buildKnownRepairedEvidence(args2.task_id,latestReceipt,nextGeneration2,{sha256:read.status==="missing"?null:read.sha256,generation:read.status==="valid"?read.generation??null:latestReceipt.generation??null});else if(read.status==="missing")return{success:!1,message:"TASK_GATE_EVIDENCE_ABSENT",errors:[`TASK_GATE_EVIDENCE_ABSENT: ${args2.task_id} has no evidence file and no authoritative requirements receipt to rebuild from.`]};else return{success:!1,message:"TASK_GATE_REQUIREMENTS_RECEIPT_MISSING",errors:[`TASK_GATE_REQUIREMENTS_RECEIPT_MISSING: ${args2.task_id} has no authoritative requirements receipt. Receipt-less repair was refused without modifying the original evidence because its required gates cannot be reconstructed safely.`]};if(plan)nextEvidence.planId=derivePlanId(plan),nextEvidence.planIdentityHash=derivePlanIdentityHash(plan);let serialized3=canonicalizeTaskEvidence(args2.task_id,nextEvidence),quarantine;if(isQuarantinableTaskEvidenceRead(read))quarantine=await quarantineTaskEvidenceBytes(canonicalDirectory,args2.task_id,read,normalizedReason,context,latestReceipt?.generation??null);assertTaskEvidenceWriteAllowed(canonicalDirectory,args2.task_id),await atomicWriteFile(taskEvidenceFilePath(canonicalDirectory,args2.task_id),serialized3),invalidateTaskEvidenceSessionFallbacks(args2.task_id);let nextActions=buildRepairNextActions(args2.task_id,nextEvidence);return{success:!0,repaired:!0,task_id:args2.task_id,required_gates:[...nextEvidence.required_gates],requirements_state:nextEvidence.requirements_state,quarantine_digest:quarantine?.digest,quarantine_path:quarantine?.filePath,repaired_generation:nextEvidence.workflow?.generation,next_actions:nextActions,message:`Repaired task gate evidence for ${args2.task_id} into a fresh fail-closed generation ${nextEvidence.workflow?.generation}. Next actions: ${nextActions.join(" ")}`}})}init_create_tool();init_resolve_working_directory();async function executeRepairGateEvidence(args2,directory,_ctx){try{if(!_ctx||stripKnownSwarmPrefix(_ctx.agent??"").toLowerCase()!=="architect")return{success:!1,message:"Only the architect may repair task gate evidence.",errors:["TASK_GATE_EVIDENCE_ARCHITECT_ONLY"]};let resolved=resolveWorkingDirectory(args2.working_directory,directory);if(!resolved.success)return{success:!1,message:resolved.message,errors:[resolved.message]};return await repairTaskGateEvidence(args2,resolved.directory,{sessionID:_ctx?.sessionID,messageID:_ctx?.messageID})}catch(error93){return{success:!1,message:"repair_gate_evidence failed",errors:[error93 instanceof Error?error93.message:String(error93)]}}}var repair_gate_evidence=createSwarmTool({description:"Architect-only evidence repair for exact-task gate files. Rebuilds from a durable requirements receipt, recovers receipt-backed legacy marker wedges or the exact sentinel-only historical reset, rebuilds otherwise-valid evidence stamped for a different plan than the current .swarm/plan.json (stamping the rebuilt record with the current plan identity), and refuses every other receipt-less reconstruction.",args:{task_id:exports_external.string().min(1).regex(/^\d+\.\d+(\.\d+)*$/,"Task ID must be in N.M or N.M.P format"),reason:exports_external.string().min(1).max(2000),expected_sha256:exports_external.string().regex(/^[a-f0-9]{64}$/).optional(),expected_generation:exports_external.number().int().min(0).optional(),working_directory:exports_external.string().optional()},execute:async(args2,directory,ctx)=>JSON.stringify(await executeRepairGateEvidence(args2,directory,ctx),null,2)});init_zod();init_schema();init_knowledge_receipt_ledger();init_create_tool();init_resolve_working_directory();async function executeRepairKnowledgeReceiptLedger(args2,directory,_ctx){try{if(_ctx&&stripKnownSwarmPrefix(_ctx.agent??"").toLowerCase()!=="architect")return{success:!1,message:"Only the architect may repair the knowledge receipt ledger.",errors:["RECEIPT_REPAIR_ARCHITECT_ONLY"]};if(_ctx?.sessionID&&args2.session_id!==_ctx.sessionID)return{success:!1,message:"repair_knowledge_receipt_ledger session_id must match the invoking tool context.",errors:["RECEIPT_REPAIR_SESSION_MISMATCH"]};let resolved=resolveWorkingDirectory(args2.working_directory,directory);if(!resolved.success)return{success:!1,message:resolved.message,errors:[resolved.message]};if(args2.operation==="backfill_phase_id"){let backfill=await backfillMembershipPhaseIds(resolved.directory);if(!backfill.ok)return{success:!1,message:"repair_knowledge_receipt_ledger backfill_phase_id failed",errors:[backfill.detail],code:backfill.code};return{success:!0,message:`phase_id backfill complete: ${backfill.backfilled} membership(s) backfilled, ${backfill.skipped.length} skipped (unparsable label), ${backfill.journal_records} journal record(s) appended. Stored labels are never rewritten.`,backfilled:backfill.backfilled,skipped:backfill.skipped.slice(0,20),skipped_total:backfill.skipped.length,journal_records:backfill.journal_records}}let result=await repairKnowledgeReceiptLedger(resolved.directory,args2);if(!result.ok)return{success:!1,message:"repair_knowledge_receipt_ledger failed",errors:[result.detail],code:result.code};let reEvaluationArgs=JSON.stringify({repair_id:result.repair_id,phase:args2.phase,...args2.task_id?{task_id:args2.task_id}:{},scope_complete:!0});return{success:!0,message:result.status==="validated_projection"?"knowledge receipt projection validated":result.status==="pending_re_evaluation"?`knowledge receipt ledger still pending re-evaluation; as architect, run knowledge_recall with a comprehensive query and repair_re_evaluation ${reEvaluationArgs}`:`knowledge receipt ledger repaired and blocked pending re-evaluation; as architect, run knowledge_recall with a comprehensive query and repair_re_evaluation ${reEvaluationArgs}`,...result}}catch(error93){return{success:!1,message:"repair_knowledge_receipt_ledger failed",errors:[error93 instanceof Error?error93.message:String(error93)]}}}var repair_knowledge_receipt_ledger=createSwarmTool({description:"Architect-only repair and validation for the authoritative knowledge receipt ledger. Default operation repairs: rebuilds the derived projection when authority is readable, or quarantines a bounded corrupt authority, salvages only the validated prefix, and blocks the exact phase/session until a fresh re-evaluation is committed. operation backfill_phase_id durably stamps the stable numeric phase_id on live memberships that lack one across the WHOLE ledger (phase/session_id are not used to scope the backfill; labels never rewritten).",args:{phase:exports_external.string().min(1),session_id:exports_external.string().min(1),task_id:exports_external.string().min(1).optional(),reason:exports_external.string().min(1).max(2000),operation:exports_external.enum(["repair","backfill_phase_id"]).optional(),grace_days:exports_external.number().int().min(0).optional(),working_directory:exports_external.string().optional()},execute:async(args2,directory,ctx)=>JSON.stringify(await executeRepairKnowledgeReceiptLedger(args2,directory,ctx),null,2)});init_zod();init_loader();init_schema();init_profiles();init_telemetry();init_path_security();init_create_tool();import*as path373 from"node:path";init_zod();init_external_tool_runner();init_path_security();init_create_tool();import*as fs230 from"node:fs";import{createRequire as createRequire7}from"node:module";import*as path372 from"node:path";var require2=createRequire7(import.meta.url),DEFAULT_MAX_RESULTS4=100,DEFAULT_MAX_LINES=200,REGEX_TIMEOUT_MS=5000,MAX_FILE_SIZE_BYTES8=1048576,HARD_CAP_RESULTS4=1e4,HARD_CAP_LINES=1e4,MAX_QUERY_LENGTH=20000,MAX_INCLUDE_PATTERNS=100,MAX_RG_STDOUT_BYTES=8388608,MAX_RG_STDERR_BYTES=65536,FALLBACK_MAX_FILES=20000,FALLBACK_MAX_DIRS=5000,FALLBACK_MAX_DEPTH=40,FALLBACK_MAX_TOTAL_BYTES=67108864,DEFAULT_SKIP_DIRS=new Set([".git",".swarm","node_modules","dist","build","out","coverage",".next",".turbo",".cache"]);function globMatch(pattern,filePath){let normalizedPattern=pattern.replace(/\\/g,"/"),normalizedPath=filePath.replace(/\\/g,"/"),regexPattern=normalizedPattern.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*\*/g,"{{DOUBLESTAR}}").replace(/\*/g,"[^/]*").replace(/\?/g,".").replace(/\{\{DOUBLESTAR\}\}/g,".*");try{return new RegExp(`^${regexPattern}$`).test(normalizedPath)}catch{return!1}}function matchesGlobs(filePath,globs){if(globs.length===0)return!0;return globs.some((glob)=>globMatch(glob,filePath))}var WINDOWS_RESERVED_NAMES5=/^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;function containsWindowsAttacks4(str){if(/:[^\\/]/.test(str))return!0;let parts=str.split(/[/\\]/);for(let part of parts)if(WINDOWS_RESERVED_NAMES5.test(part))return!0;return!1}function resolveWithinWorkspace(filePath,workspace){try{let resolvedPath=path372.resolve(workspace,filePath),realWorkspace=fs230.realpathSync(workspace),realResolvedPath=fs230.realpathSync(resolvedPath),relativePath2=path372.relative(realWorkspace,realResolvedPath);if(relativePath2.startsWith("..")||path372.isAbsolute(relativePath2))return null;return relativePath2}catch{return null}}function isPathInWorkspace3(filePath,workspace){return resolveWithinWorkspace(filePath,workspace)!==null}function validatePathForRead2(filePath,workspace){return isPathInWorkspace3(filePath,workspace)}function splitGlobPatterns2(value){return value?value.split(",").map((p)=>p.trim()).filter(Boolean):[]}var GLOB_METACHARACTERS=/[*?[\]{}]/;function isExactPath(pattern){return!GLOB_METACHARACTERS.test(pattern)}function targetsDotDirectory(pattern){let firstSegment=pattern.split(/[\\/]/)[0];return!!firstSegment&&firstSegment.startsWith(".")&&firstSegment!=="."&&firstSegment!==".."}function hasGitSegment(resolvedRelativePath){return resolvedRelativePath.split(/[\\/]/).some((segment)=>segment.toLowerCase()===".git")}function toWorkspaceRelativePath2(filePath,workspace){try{let resolved=path372.resolve(workspace,filePath),realWorkspace=fs230.realpathSync(workspace),realResolved=fs230.realpathSync(resolved),relative99=path372.relative(realWorkspace,realResolved);if(!relative99||relative99.startsWith("..")||path372.isAbsolute(relative99))return null;return relative99.split(path372.sep).join("/")}catch{return null}}function truncateLine(line,maxLines){let trimmed=line.trimEnd();if(trimmed.length>maxLines)return`${trimmed.substring(0,maxLines)}...`;return trimmed}function resolvePackagedRipgrep(){try{let mod=require2("@vscode/ripgrep");return typeof mod.rgPath==="string"&&mod.rgPath?mod.rgPath:null}catch{return null}}function resolveRipgrepBinary(){return _internals319.resolvePackagedRipgrep()??_internals319.resolveExecutableFromPath(["rg"])}async function ripgrepSearch(opts){let rgPath=_internals319.resolveRipgrepBinary();if(!rgPath)return{error:!0,type:"rg-not-found",message:"ripgrep (rg) not found; using fallback search was not possible"};let args2=["--json","--no-config","-n"],includes=splitGlobPatterns2(opts.include),promotablePaths=[],globIncludes=[];for(let pattern of includes){let resolvedRelative=resolveWithinWorkspace(pattern,opts.workspace);if(isExactPath(pattern)&&targetsDotDirectory(pattern)&&pattern.split(/[\\/]/)[0]?.toLowerCase()!==".git"&&resolvedRelative!==null&&!hasGitSegment(resolvedRelative))promotablePaths.push(pattern);else globIncludes.push(pattern)}let pathOperands;if(promotablePaths.length>0&&globIncludes.length===0)pathOperands=promotablePaths;else{for(let pattern of[...globIncludes,...promotablePaths])args2.push("--glob",pattern);if(includes.some((p)=>targetsDotDirectory(p)&&p.split(/[\\/]/)[0]?.toLowerCase()!==".git"))args2.push("--hidden","--no-ignore"),args2.push("--glob","!.git");pathOperands=["."]}for(let pattern of splitGlobPatterns2(opts.exclude))args2.push("--glob",`!${pattern}`);if(opts.mode!=="regex")args2.push("--fixed-strings");args2.push("--",opts.query,...pathOperands);let run=await _internals319.runExternalTool({executable:rgPath,args:args2,cwd:opts.workspace,timeoutMs:REGEX_TIMEOUT_MS,maxStdoutBytes:MAX_RG_STDOUT_BYTES,maxStderrBytes:MAX_RG_STDERR_BYTES});try{if(run.status==="timeout")return{error:!0,type:"regex-timeout",message:`Search timed out after ${REGEX_TIMEOUT_MS}ms`};if(run.status==="spawn-error")return{error:!0,type:"unknown",message:run.message??"ripgrep failed to start"};if(run.exitCode!==0&&run.stderr){if(run.stderr.includes("Invalid regex")||run.stderr.includes("regex parse error")||run.stderr.includes("SyntaxError"))return{error:!0,type:"invalid-query",message:`Invalid query: ${run.stderr.split(`
|
|
7856
7856
|
`)[0]}`};if(run.exitCode===2)return{error:!0,type:"unknown",message:`ripgrep error: ${run.stderr.split(`
|
|
7857
7857
|
`)[0]}`}}let matches=[],total=0;for(let line of run.stdout.split(`
|
|
7858
7858
|
`)){if(!line.trim())continue;try{let entry=JSON.parse(line);if(entry.type==="match"){let rawPath=entry.data?.path?.text??entry.data?.path,relativePath2=typeof rawPath==="string"?toWorkspaceRelativePath2(rawPath,opts.workspace):null;if(!relativePath2)continue;if(total++,matches.length<opts.maxResults){let match={file:relativePath2,lineNumber:entry.data.line_number,lineText:truncateLine(entry.data.lines.text,opts.maxLines)};matches.push(match)}}}catch{}}return{matches,truncated:total>opts.maxResults||run.stdoutTruncated||run.stderrTruncated,total,query:opts.query,mode:opts.mode,maxResults:opts.maxResults,engine:"ripgrep",outputTruncated:run.stdoutTruncated||run.stderrTruncated}}catch(err){return{error:!0,type:"unknown",message:err instanceof Error?err.message:String(err)}}}function escapeRegex4(str){return str.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function collectFiles(dir,workspace,includeGlobs,excludeGlobs,state2,depth=0){if(depth>FALLBACK_MAX_DEPTH||state2.files.length>=FALLBACK_MAX_FILES||state2.dirCount>=FALLBACK_MAX_DIRS)return state2.truncated=!0,state2.files;try{let realDir=fs230.realpathSync(dir);if(state2.seenRealPaths.has(realDir))return state2.files;state2.seenRealPaths.add(realDir),state2.dirCount++}catch{return state2.files}if(!validatePathForRead2(dir,workspace))return state2.files;try{let entries2=fs230.readdirSync(dir,{withFileTypes:!0});for(let entry of entries2){if(state2.files.length>=FALLBACK_MAX_FILES||state2.dirCount>=FALLBACK_MAX_DIRS){state2.truncated=!0;break}let fullPath=path372.join(dir,entry.name),relativePath2=path372.relative(workspace,fullPath);if(!validatePathForRead2(fullPath,workspace))continue;if(entry.isDirectory()){if(entry.name.toLowerCase()===".git"||DEFAULT_SKIP_DIRS.has(entry.name)&&!includeGlobs.some((g)=>g.split(/[\\/]/)[0]===entry.name))continue;collectFiles(fullPath,workspace,includeGlobs,excludeGlobs,state2,depth+1)}else if(entry.isFile()){if(includeGlobs.length>0&&!matchesGlobs(relativePath2,includeGlobs))continue;if(excludeGlobs.length>0&&matchesGlobs(relativePath2,excludeGlobs))continue;let normalized=toWorkspaceRelativePath2(fullPath,workspace);if(!normalized)continue;state2.files.push(normalized)}}}catch{}return state2.files}async function searchWorkspaceLiteral(opts){let includeGlobs=opts.include?opts.include.split(",").map((p)=>p.trim()).filter(Boolean):[],excludeGlobs=opts.exclude?opts.exclude.split(",").map((p)=>p.trim()).filter(Boolean):[],collectState={files:[],seenRealPaths:new Set,dirCount:0,truncated:!1},files=collectFiles(opts.workspace,opts.workspace,includeGlobs,excludeGlobs,collectState),regex;try{if(opts.mode==="regex")regex=new RegExp(opts.query);else regex=new RegExp(escapeRegex4(opts.query))}catch(err){return{error:!0,type:"invalid-query",message:err instanceof Error?err.message:"Invalid regex pattern"}}let matches=[],total=0,totalBytesRead=0,truncated=collectState.truncated;for(let file3 of files){let fullPath=path372.join(opts.workspace,file3);if(!validatePathForRead2(fullPath,opts.workspace))continue;let stats2;try{if(stats2=fs230.statSync(fullPath),stats2.size>MAX_FILE_SIZE_BYTES8)continue;if(totalBytesRead+stats2.size>FALLBACK_MAX_TOTAL_BYTES){truncated=!0;break}totalBytesRead+=stats2.size}catch{continue}let content;try{let bytes=fs230.readFileSync(fullPath);if(bytes.includes(0))continue;content=bytes.toString("utf-8")}catch{continue}let lines=content.split(`
|