pi-crew 0.11.25 → 0.11.27

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/CHANGELOG.md CHANGED
@@ -6,6 +6,29 @@
6
6
 
7
7
  - **fix(gate): RT24-F1 root-gate config/autonomy read over-block** — `rootGateBlockReason` counted the `args` subcommand carrier as a config patch key, so worker-origin `config {args:"show"}` READS were rejected as "writes user-scope config" (live-caught in the v0.11.24 real-test battery; docblock promised reads open). `args` added to the carrier-key sets for `config` and `autonomy`; unknown junk keys stay write-classified (fail-closed). Pinned: reads with carrier keys open, writes hidden behind the same key still gated (`unset`/patch keys), user config byte-untouched. Live-verified end-to-end (fresh `pi -p`, worker env): read allowed + dumps config; `unset` write gate-blocked verbatim "root-session required".
8
8
 
9
+ ## [0.11.27] — Residual backlog: chain DSL constructs now have real consumers (`:N` loops, `--with-context`, positional args) + `--timeout` wired
10
+
11
+ ### Fixed
12
+ - **R14-C1 tail / M3-F (silent no-op DSL features)**: the chain parser accepted `:N`, `--with-context`, and quoted positional args, and the runner dutifully parked them in `step.context` — where nothing ever read them. A user writing `polish:3` got ONE run, silently. All three now have real consumers:
13
+ - `:N` executes N sequential iterations (chain is sequential by contract). Each iteration is its own `ChainStepResult` (`name#k` for k>1), so a failing iteration stays visible; the R14-C5 success predicate counts planned EXECUTIONS, so a chain that breaks inside a loop cannot pass unexecuted iterations off as done. `:N` is clamped to 1..10 at the parser — clamped, not thrown, because a throw would fall back to the simple splitter and turn `step:99` into ONE literal step named "step:99" (the exact R14-C1 corruption class).
14
+ - `--with-context` forwards the previous step's FULL worker output (`__chainPrevOutput`, capped 20k chars) — distinct from the default `__chainHistory` channel, which carries only size-capped handoff summaries. Rendered as a `# Previous Step Output (--with-context)` block in the next step's goal.
15
+ - Quoted positional args append to the step goal: `"research" "topic X"` → goal "research topic X".
16
+ - **R14-C2 (dead `--timeout` flag + unit confusion)**: `--timeout` parsed into `step.timeout` that no consumer ever read, with a seconds value compared against a 1000-day ms bound. Now: parsed as seconds 1..86400 (1 day), forwarded as `runParams.timeoutMs` into the step's run — honored by the CORE-8 unified deadline (params > config `limits.maxRunMinutes` > 1h default) for foreground runs.
17
+
18
+ ### Verified
19
+ - Pins: parser clamp (0→1, 99→10) · 3-iteration loop with visible `#k` results · in-loop failure breaks the chain (planned-execution accounting — mutation-pinned: reverting to `spec.steps.length` accounting turns the loop test RED) · `continueOnError` runs remaining iterations · args→goal · `--with-context` full-output forwarding + 20k cap + absence without flag · timeout seconds→ms + 1-day boundary + `__chainStepTimeoutMs` packet channel · executor renders the prev-output block and forwards `timeoutMs` (absent flag → no key).
20
+
21
+ ## [0.11.26] — Fix: verifier verdict consumer blocked runs whose verifier returned a prose verdict (live-caught by the post-release real-test battery)
22
+
23
+ ### Fixed
24
+ - **Verifier verdict consumption (R47-3/V4 follow-up, live regression)**: the wave-6 verdict consumer required the exact `PASS:`/`FAIL:` line, but every child-process verifier prompt still asked for a prose verdict ("Give PASS or FAIL with evidence"). A FAILED-gate run whose verifier followed its prompt wrote a bare/decorated verdict → the consumer read `none` → `observed=none` → the green contract **blocked** the run (`green_unsatisfied`) instead of resolving it. Live-proven twice (before/after). Fix, two sides:
25
+ - `extractVerifierVerdict` now accepts bare/decorated verdicts at line start (`PASS`, `**PASS**`, `PASS — …`, `PASS. …`, `PASS (…)`) while still rejecting mid-line mentions and word continuations (`PASSED`, `PASSing`); FAIL-wins and source-priority semantics unchanged. Pins 11/11 incl. mutation.
26
+ - Prompts now demand the exact line: `workflows/{fast-fix,plan-execute,review,strict-fast-fix,default}.workflow.md`, `agents/verifier.md`, and both `plan-templates.ts` verifier taskTemplates require `PASS: <what verified> — <evidence>` / `FAIL: <what failed> — <reason>` (green-contract consumer reads it; no verdict line = UNVERIFIED).
27
+ - **Settings catalog refresh**: `docs/ui-samples/captures|png/18-settings` regenerated — the Runtime tab now renders the schema key `runtime.isolationPolicy.defaultRuntime` (was a stale label/key).
28
+
29
+ ### Verified
30
+ - Post-release battery (docs/real-test/reports/real-test-2026-10-19-fix-wave-6-battery.md): T1 124/124 · T2 3-path · T3/T4/T8 md5 · T5 /team-help live · T7×2 (PASS skipVerifier / FAIL verifier-with-context, verdict consumed) · T9a 13/13 · T9b 5 paths · T9b-W ask round-trip + message + delegate + loadout · T9g steer boot-window · T10a tmux 4/4 + herdr 5/5 · T10b live surface run (provider=tmux, spawn/close ×2, 0 degraded) · T11 a–j · T12 18 agents both parsers · T13 real-run render, sweeps clean + PNG inspected.
31
+
9
32
  ## [0.11.25] — Fix-wave 6: deep-review R1-R51 close-out (security cluster, state/verification families, doc tail) (2026-10-19)
10
33
 
11
34
  Close-out wave for the 51-round / ~150-finding deep review recorded in
@@ -74,7 +74,7 @@ For **implementation** workflows:
74
74
 
75
75
  ## Output Format
76
76
 
77
- End with exactly this block:
77
+ Start your report with the verdict line — `PASS: <what verified> — <evidence>` or `FAIL: <what failed> — <reason>` (exact single-line format, colon required or the line may be bare `PASS`/`FAIL`; the leader's green-contract consumer reads this line — a report with no verdict line is treated as UNVERIFIED). Then end with exactly this block:
78
78
 
79
79
  ```
80
80
  VERIFICATION: PASS|FAIL
package/dist/index.mjs CHANGED
@@ -603,7 +603,7 @@ ${n.step.task}`,transcriptPath:i==="child-process"?$:T?.path,stdout:C}):void 0;q
603
603
  `,producer:o.id}),vn=ye(r.artifactsRoot,{kind:"metadata",relativePath:`metadata/${o.id}.capabilities.json`,content:`${JSON.stringify(Bne({taskId:o.id,role:o.role,agent:n.agent,runtime:i,permissionMode:l,skillNames:f,skillPaths:p,skillsDisabled:n.skillOverride===!1||n.teamRoleSkills===!1,modelOverride:n.modelOverride,teamRoleModel:n.teamRoleModel,stepModel:n.step.model}),null,2)}
604
604
  `,producer:o.id}),sr=ye(r.artifactsRoot,{kind:"metadata",relativePath:`metadata/${o.id}.prompt-pipeline.json`,content:`${JSON.stringify(Hne({artifactsRoot:r.artifactsRoot,taskId:o.id,promptArtifact:m,inputsArtifact:w,skillArtifact:b,capabilityArtifact:vn,coordinationArtifact:h,skillInstructionCount:f?.length??0,skillsDisabled:n.skillOverride===!1||n.teamRoleSkills===!1}),null,2)}
605
605
  `,producer:o.id}),Ye=ee?ye(r.artifactsRoot,{kind:"metadata",relativePath:`metadata/${o.id}.output-validation.json`,content:`${JSON.stringify(ee,null,2)}
606
- `,producer:o.id}):void 0;r={...r,updatedAt:new Date().toISOString(),artifacts:[...r.artifacts,m,...g?[g]:[],...S?[S]:[],w,h,...b?[b]:[],D,pe,oe,yt,vn,sr,...Ye?[Ye]:[],...ie?[ie]:[],...x?[x]:[],...T?[T]:[],...N?[N]:[],...U?[U]:[],...G?[G]:[]]},s=await Or(r,async()=>(await kt(r),oi(r,s,o,void 0,!0)));let me=s.find(ke=>ke.id===o.id)??o,Ze=me.status!==o.status?me.status:void 0,Je=Ze??o.status;er(r,sn(r,me,i));let ce=await Po("task_result",{runId:r.runId,taskId:o.id,cwd:r.cwd});Mo(r,ce);let Re=oHe[Je];if(Re!==void 0){let ke={...o.failureCause?{failureCause:o.failureCause}:{},...Ze?{preservedFrom:o.status}:{}};await Q(r.eventsPath,{type:Re,runId:r.runId,taskId:o.id,message:Ze?me.error??R:R,...Object.keys(ke).length>0?{data:ke}:{}})}let lt=await Po("after_task_complete",{runId:r.runId,taskId:o.id,cwd:r.cwd,status:Je});return Mo(r,lt),{manifest:r,tasks:s}}var oHe,ere,tre=v(()=>{"use strict";zl();qt();Te();pr();we();US();Nj();Lj();dt();Pb();dd();Pne();Qp();xA();jj();AA();tS();Gne();qne();Qne();My();oHe={completed:"task.completed",failed:"task.failed",cancelled:"task.cancelled",skipped:"task.skipped",needs_attention:"task.needs_attention"},ere=/^[\s*_>#`=-]*(PASS|FAIL)\s*:/i});async function nre(e,t,n){let r=await Rne(t,e.task,e.step.seedPaths),o=r.worktreePath&&r.branch?{path:r.worktreePath,branch:r.branch,reused:r.reused??!1}:e.task.worktree,s=O4({manifest:t,step:e.step,taskId:e.task.id,cwd:r.cwd,worktreePath:o?.path,...e.step.specRefs&&e.step.specRefs.length>0?{specRefs:e.step.specRefs}:{},...e.step.specStrict===!0?{specStrict:!0}:{}});(s.specRefs?.length||s.unresolvedSpecRefs?.length)&&qe(t.eventsPath,{type:"spec.frozen",runId:t.runId,taskId:e.task.id,data:{specIds:s.specSnapshots?.map(M=>M.specId)??[],versions:s.specSnapshots?.map(M=>`${M.specId}@v${M.version}(trusted=${M.trustedAtFreeze})`)??[],...s.unresolvedSpecRefs?.length?{unresolvedSpecRefs:s.unresolvedSpecRefs}:{},...s.specStrict===!0?{strict:!0}:{}}});let i=K4(t,e.tasks,e.task,e.step,e.resultReadCache),a=e.dependencyContextText??J4(i,{budgetTokens:e.runtimeConfig?.handoffBudgetTokens}),c={...e.task,cwd:r.cwd,worktree:o,taskPacket:s,status:"running",startedAt:new Date().toISOString(),claim:yL(`task-runner:${e.task.id}`),heartbeat:Pi(e.task.id),agentProgress:e.task.agentProgress??da(),lifetimeUsage:{input:0,output:0,cacheWrite:0},...a?{dependencyContextText:a}:{}},u=$o(e.tasks,c);if(c.planItem)try{H5(t,c.planItem,c.id)}catch(M){k("task-runner.plan-link-failed",M instanceof Error?M:new Error(String(M)),`taskId=${c.id}`)}let d=e.taskRuntimeOverride??e.runtimeKind??(e.executeWorkers?"child-process":"scaffold"),l=d!=="child-process"&&(e.runtimeConfig?.yield?.enabled??eS.enabled);if(e.signal?.aborted){let M=Qa(e.signal),$={...c,status:"cancelled",error:`${M.code}: ${M.message}`,finishedAt:new Date().toISOString()};return{kind:"cancelled",result:{manifest:e.manifest,tasks:$o(u,$)}}}u=oi(t,u,c,"started"),d==="child-process"&&({task:c,tasks:u}=Py(t,u,c,"started")),er(t,sn(t,c,d)),await Q(t.eventsPath,{type:"task.started",runId:t.runId,taskId:c.id,data:{role:c.role,agent:c.agent,runtime:d,cwd:c.cwd,worktreePath:r.worktreePath,worktreeBranch:r.branch,worktreeReused:r.reused}}),n?.handler({runId:t.runId,taskId:c.id,eventType:"task.started",timestamp:Date.now()});let f=wr(c.role),p=e.skillBlock===void 0?Bb({cwd:c.cwd,role:c.role,agent:e.agent,teamRole:{skills:e.teamRoleSkills},step:e.step,override:e.skillOverride,runId:t.runId,advertisedByHost:d==="child-process"&&e.skillPaths===void 0}):void 0,m=e.skillBlock??p?.block,g=e.skillNames??p?.names,w=e.skillPaths??p?.paths,b;if(e.step.preStepScript&&e.step.source!=="builtin"&&e.step.source!=="user")qe(t.eventsPath,{type:"hook.pre_step_skipped",runId:t.runId,taskId:c.id,message:`preStepScript '${e.step.preStepScript}' skipped: only builtin/user-sourced workflows may execute pre-step scripts for security (F-02).`,data:{script:e.step.preStepScript,source:e.step.source??"unknown"}}),b=void 0;else if(e.step.preStepScript){let M=e.step.preStepTimeout??3e4,$=e.step.preStepArgs??[];qe(t.eventsPath,{type:"hook.pre_step_started",runId:t.runId,taskId:c.id,data:{script:e.step.preStepScript,argCount:$.length,timeoutMs:M}}),de(t.cwd,e.step.preStepScript);try{let{execFileSync:B}=await import("node:child_process");b=B(e.step.preStepScript,$,{timeout:M,encoding:"utf-8",cwd:t.cwd,maxBuffer:1024*1024}),qe(t.eventsPath,{type:"hook.pre_step_completed",runId:t.runId,taskId:c.id,data:{script:e.step.preStepScript,outputBytes:Buffer.byteLength(b,"utf8")}})}catch(B){let L=B instanceof Error?B.message:String(B),V=B.status;if(qe(t.eventsPath,{type:"hook.pre_step_failed",runId:t.runId,taskId:c.id,message:`pre-step hook failed (exit ${V??"?"})`,data:{script:e.step.preStepScript,exitCode:V??null,optional:e.step.preStepOptional===!0}}),e.step.preStepOptional){let j=`[preStepOptional] pre-step hook '${e.step.preStepScript}' failed (exit ${V??"?"}) but preStepOptional=true; continuing without its output.`;try{qe(t.eventsPath,{type:"hook.pre_step_optional_failed",runId:t.runId,taskId:c.id,message:j,data:{script:e.step.preStepScript,exitCode:V??null}})}catch{}b=void 0}else throw Eo.preStepFailed(e.step.preStepScript,V,L)}}let h=await f9(t,e.step,c,e.agent,m,void 0,g??[]),S=h.full;b&&(S+=`
606
+ `,producer:o.id}):void 0;r={...r,updatedAt:new Date().toISOString(),artifacts:[...r.artifacts,m,...g?[g]:[],...S?[S]:[],w,h,...b?[b]:[],D,pe,oe,yt,vn,sr,...Ye?[Ye]:[],...ie?[ie]:[],...x?[x]:[],...T?[T]:[],...N?[N]:[],...U?[U]:[],...G?[G]:[]]},s=await Or(r,async()=>(await kt(r),oi(r,s,o,void 0,!0)));let me=s.find(ke=>ke.id===o.id)??o,Ze=me.status!==o.status?me.status:void 0,Je=Ze??o.status;er(r,sn(r,me,i));let ce=await Po("task_result",{runId:r.runId,taskId:o.id,cwd:r.cwd});Mo(r,ce);let Re=oHe[Je];if(Re!==void 0){let ke={...o.failureCause?{failureCause:o.failureCause}:{},...Ze?{preservedFrom:o.status}:{}};await Q(r.eventsPath,{type:Re,runId:r.runId,taskId:o.id,message:Ze?me.error??R:R,...Object.keys(ke).length>0?{data:ke}:{}})}let lt=await Po("after_task_complete",{runId:r.runId,taskId:o.id,cwd:r.cwd,status:Je});return Mo(r,lt),{manifest:r,tasks:s}}var oHe,ere,tre=v(()=>{"use strict";zl();qt();Te();pr();we();US();Nj();Lj();dt();Pb();dd();Pne();Qp();xA();jj();AA();tS();Gne();qne();Qne();My();oHe={completed:"task.completed",failed:"task.failed",cancelled:"task.cancelled",skipped:"task.skipped",needs_attention:"task.needs_attention"},ere=/^[\s*_>#`=-]*(PASS|FAIL)[\s*_`]*(?=[:.\u2014\u2013-]|$|\()/i});async function nre(e,t,n){let r=await Rne(t,e.task,e.step.seedPaths),o=r.worktreePath&&r.branch?{path:r.worktreePath,branch:r.branch,reused:r.reused??!1}:e.task.worktree,s=O4({manifest:t,step:e.step,taskId:e.task.id,cwd:r.cwd,worktreePath:o?.path,...e.step.specRefs&&e.step.specRefs.length>0?{specRefs:e.step.specRefs}:{},...e.step.specStrict===!0?{specStrict:!0}:{}});(s.specRefs?.length||s.unresolvedSpecRefs?.length)&&qe(t.eventsPath,{type:"spec.frozen",runId:t.runId,taskId:e.task.id,data:{specIds:s.specSnapshots?.map(M=>M.specId)??[],versions:s.specSnapshots?.map(M=>`${M.specId}@v${M.version}(trusted=${M.trustedAtFreeze})`)??[],...s.unresolvedSpecRefs?.length?{unresolvedSpecRefs:s.unresolvedSpecRefs}:{},...s.specStrict===!0?{strict:!0}:{}}});let i=K4(t,e.tasks,e.task,e.step,e.resultReadCache),a=e.dependencyContextText??J4(i,{budgetTokens:e.runtimeConfig?.handoffBudgetTokens}),c={...e.task,cwd:r.cwd,worktree:o,taskPacket:s,status:"running",startedAt:new Date().toISOString(),claim:yL(`task-runner:${e.task.id}`),heartbeat:Pi(e.task.id),agentProgress:e.task.agentProgress??da(),lifetimeUsage:{input:0,output:0,cacheWrite:0},...a?{dependencyContextText:a}:{}},u=$o(e.tasks,c);if(c.planItem)try{H5(t,c.planItem,c.id)}catch(M){k("task-runner.plan-link-failed",M instanceof Error?M:new Error(String(M)),`taskId=${c.id}`)}let d=e.taskRuntimeOverride??e.runtimeKind??(e.executeWorkers?"child-process":"scaffold"),l=d!=="child-process"&&(e.runtimeConfig?.yield?.enabled??eS.enabled);if(e.signal?.aborted){let M=Qa(e.signal),$={...c,status:"cancelled",error:`${M.code}: ${M.message}`,finishedAt:new Date().toISOString()};return{kind:"cancelled",result:{manifest:e.manifest,tasks:$o(u,$)}}}u=oi(t,u,c,"started"),d==="child-process"&&({task:c,tasks:u}=Py(t,u,c,"started")),er(t,sn(t,c,d)),await Q(t.eventsPath,{type:"task.started",runId:t.runId,taskId:c.id,data:{role:c.role,agent:c.agent,runtime:d,cwd:c.cwd,worktreePath:r.worktreePath,worktreeBranch:r.branch,worktreeReused:r.reused}}),n?.handler({runId:t.runId,taskId:c.id,eventType:"task.started",timestamp:Date.now()});let f=wr(c.role),p=e.skillBlock===void 0?Bb({cwd:c.cwd,role:c.role,agent:e.agent,teamRole:{skills:e.teamRoleSkills},step:e.step,override:e.skillOverride,runId:t.runId,advertisedByHost:d==="child-process"&&e.skillPaths===void 0}):void 0,m=e.skillBlock??p?.block,g=e.skillNames??p?.names,w=e.skillPaths??p?.paths,b;if(e.step.preStepScript&&e.step.source!=="builtin"&&e.step.source!=="user")qe(t.eventsPath,{type:"hook.pre_step_skipped",runId:t.runId,taskId:c.id,message:`preStepScript '${e.step.preStepScript}' skipped: only builtin/user-sourced workflows may execute pre-step scripts for security (F-02).`,data:{script:e.step.preStepScript,source:e.step.source??"unknown"}}),b=void 0;else if(e.step.preStepScript){let M=e.step.preStepTimeout??3e4,$=e.step.preStepArgs??[];qe(t.eventsPath,{type:"hook.pre_step_started",runId:t.runId,taskId:c.id,data:{script:e.step.preStepScript,argCount:$.length,timeoutMs:M}}),de(t.cwd,e.step.preStepScript);try{let{execFileSync:B}=await import("node:child_process");b=B(e.step.preStepScript,$,{timeout:M,encoding:"utf-8",cwd:t.cwd,maxBuffer:1024*1024}),qe(t.eventsPath,{type:"hook.pre_step_completed",runId:t.runId,taskId:c.id,data:{script:e.step.preStepScript,outputBytes:Buffer.byteLength(b,"utf8")}})}catch(B){let L=B instanceof Error?B.message:String(B),V=B.status;if(qe(t.eventsPath,{type:"hook.pre_step_failed",runId:t.runId,taskId:c.id,message:`pre-step hook failed (exit ${V??"?"})`,data:{script:e.step.preStepScript,exitCode:V??null,optional:e.step.preStepOptional===!0}}),e.step.preStepOptional){let j=`[preStepOptional] pre-step hook '${e.step.preStepScript}' failed (exit ${V??"?"}) but preStepOptional=true; continuing without its output.`;try{qe(t.eventsPath,{type:"hook.pre_step_optional_failed",runId:t.runId,taskId:c.id,message:j,data:{script:e.step.preStepScript,exitCode:V??null}})}catch{}b=void 0}else throw Eo.preStepFailed(e.step.preStepScript,V,L)}}let h=await f9(t,e.step,c,e.agent,m,void 0,g??[]),S=h.full;b&&(S+=`
607
607
 
608
608
  ---
609
609
  ## Pre-Step Script Output
@@ -710,7 +710,7 @@ Do not block shard work; summarize routing notes only.`},...o,{id:"synthesize",r
710
710
  `});for(let u of s)Ne(e.eventsPath,{type:u.action==="escalate"?"policy.escalated":"policy.action",runId:e.runId,taskId:u.taskId,message:u.message,data:{action:u.action,reason:u.reason}}).catch(d=>k("finalize-run.buffered",d,`type=${u.action==="escalate"?"policy.escalated":"policy.action"}`));for(let u of a.entries)Ne(e.eventsPath,{type:u.state==="escalation_required"?"recovery.escalated":"recovery.attempted",runId:e.runId,taskId:u.taskId,message:u.message,data:{scenario:u.scenario,steps:u.steps,attempt:u.attempt,state:u.state}}).catch(d=>k("finalize-run.buffered",d,`type=${u.state==="escalation_required"?"recovery.escalated":"recovery.attempted"}`));return{...e,updatedAt:new Date().toISOString(),policyDecisions:s,artifacts:[...e.artifacts.filter(u=>!(u.kind==="metadata"&&(u.path.endsWith("policy-decisions.json")||u.path.endsWith("recovery-ledger.json")||u.path.endsWith("branch-freshness.json")))),o,i,c]}}async function QA(e){oQ();let t=e.input,n=e.tasks,r=e.manifest;if(e.pendingUnits.size===0&&n.some(h=>h.status==="running"||h.status==="waiting"))try{Er();let h=JSON.parse(ZA.readFileSync(r.tasksPath,"utf8")),S=new Map(h.map(T=>[T.id,T])),x=[];n=n.map(T=>{if(T.status!=="running"&&T.status!=="waiting")return T;let I=S.get(T.id);return I&&Hc.has(I.status)?(x.push(`${T.id}:${T.status}->${I.status}`),I):T}),x.length>0&&(e.tasks=n,qe(r.eventsPath,{type:"task.reconciled_from_disk",runId:r.runId,message:`Finalize healed stale non-terminal snapshot(s) from durable tasks.json: ${x.join(", ")}`,data:{healed:x}}))}catch(h){k("finalize-run.disk-reconcile",h,r.runId,"debug")}let o=n.find(h=>h.status==="failed"),s=n.find(h=>h.status==="waiting"),i=n.find(h=>h.status==="running");if(r=mqe(r,n,t.limits),t.workflow?.steps){let h=[];for(let S of t.workflow.steps)if(S.output&&typeof S.output=="string"){let x=Uy.join(r.artifactsRoot,S.output);ZA.existsSync(x)||h.push(S.output)}h.length>0&&qe(r.eventsPath,{type:"run.deliverable_warning",runId:r.runId,message:`Missing workflow output files: ${h.join(", ")}`,data:{missingFiles:h}})}let a=cv({manifest:r,tasks:n,executeWorkers:t.executeWorkers,runtimeConfig:t.runtimeConfig,delegateCompleted:r.eventsPath?av(Ai(r.eventsPath)):void 0}),c=Uoe(a);c&&(r={...r,policyDecisions:[...r.policyDecisions??[],c],updatedAt:new Date().toISOString()},await Q(r.eventsPath,{type:"run.effectiveness",runId:r.runId,message:c.message,data:{effectiveness:a,policyDecision:c}}));let u=r.policyDecisions?.find(h=>h.action==="block"||h.action==="escalate"),d=r.status,l=!1,f=(h,S)=>(l=!0,{...r,status:h,summary:S,updatedAt:new Date().toISOString()});if(o)r=f("failed",`Failed at task '${o.id}'.`);else if(s)r=f("blocked",`Waiting for response to task '${s.id}'.`);else if(i)r=f("blocked",`Task '${i.id}' is still running.`);else if(a.severity==="failed")r=f("failed",c?.message??"Run effectiveness guard failed.");else if(a.severity==="blocked")r=f("blocked",c?.message??"Run effectiveness guard blocked completion.");else if(u)r=f("blocked",u.message);else if(n.some(h=>h.status==="queued"))r=f("blocked","Run exited with queued tasks still pending.");else if(!(r.status==="failed"||r.status==="cancelled")){let h=n.filter(S=>S.status==="needs_attention").length;r=f("completed",h>0?`Team workflow completed with ${h} task(s) needing attention (no result submitted).`:t.executeWorkers?"Team workflow completed.":"Team workflow scaffold completed without launching child workers.")}r=lv(r,n,"team-runner",t.executeWorkers,t.runtimeConfig);let p=Is(n),m=await Or(r,async()=>{Er();let h=F(r.cwd,r.runId),S=h?.manifest,x=S&&uv(S.status),T=e.input.signal?.aborted===!0,I,R=n;if(x||T){let C=x?S.status:"cancelled";I={...r,status:C,summary:x?S.summary??r.summary:"Run cancelled during finalization.",updatedAt:new Date().toISOString()},R=h?.tasks??n,await Q(r.eventsPath,{type:"run.terminal_preserved",runId:r.runId,message:`Run terminal status '${C}' preserved from disk; finalize did not overwrite it.`,data:{preservedStatus:C,derivedStatus:r.status,signalAborted:T}})}else l?I=$e({...r,status:d},r.status,r.summary):I={...r,updatedAt:new Date().toISOString()};let A=ye(I.artifactsRoot,{kind:"summary",relativePath:"summary.md",producer:"team-runner",content:[`# pi-crew run ${I.runId}`,"",`Status: ${I.status}`,`Team: ${I.team}`,`Workflow: ${I.workflow??"(none)"}`,`Goal: ${I.goal}`,`Usage: ${Fp(p)}`,"","## Tasks",...R.map(Koe),"","## Effectiveness",...Voe(I,n,t.executeWorkers,t.runtimeConfig),"","## Policy decisions",...I.policyDecisions?.length?Hoe(I.policyDecisions):["- (none)"],"",...pqe(I)].join(`
711
711
  `)}),P={...I,updatedAt:new Date().toISOString(),artifacts:[...I.artifacts,A]};return await kt(P),await vr(P,R),{manifest:P,tasks:R}});r=m.manifest;let g=m.tasks,w=Uy.dirname(Uy.dirname(Uy.dirname(m.manifest.stateRoot)));return new JA(w).saveSnapshot({runId:m.manifest.runId,tasks:g.map(h=>({id:h.id,status:h.status,heartbeat:h.heartbeat})),createdAt:m.manifest.createdAt}),e.manifest=r,e.tasks=g,{manifest:r,tasks:g}}var dv,zoe,Joe,Yoe,e_=v(()=>{"use strict";Ge();Co();qt();Te();pr();Doe();we();fc();K();Foe();R1();XA();qoe();Xx();Ry();CW();dv=new Map;zoe=dv,Joe=lv,Yoe=QA});import{spawnSync as gqe}from"node:child_process";function yqe(e){return(e?.steps??[]).some(n=>typeof n?.role=="string"&&hqe.has(n.role))}function wqe(e){try{let t=To(e);if(!t)return{clean:"unknown",repoRoot:void 0};let n=gqe("git",["-C",t,"status","--porcelain"],{encoding:"utf8",timeout:5e3});return n.error||n.status!==0?{clean:"unknown",repoRoot:void 0}:{clean:n.stdout.trim().length===0,repoRoot:t}}catch{return{clean:"unknown",repoRoot:void 0}}}function bqe(e){if(typeof e!="string"||e.length===0)return!1;let t=e.toLowerCase().replace(/\s+/g," ").trim();return kqe.some(n=>t.includes(n))}function Xoe(e,t,n){if(!yqe(n))return{achieved:"unknown",reason:"read-only / doc-only workflow (no executor/test-engineer steps)",signals:[]};if(bqe(e.goal))return{achieved:"unknown",reason:"goal declared read-only (no edits expected)",signals:[]};let r=wqe(e.cwd);if(r.clean==="unknown"||!r.repoRoot)return{achieved:"unknown",reason:"not a git repo or git unavailable",signals:[]};if(!r.clean)return{achieved:!0,reason:"git working tree has changes (mutating run edited project files)",signals:[`repoRoot=${r.repoRoot}`]};let o=t.find(i=>i.status==="failed"),s=["git working tree clean despite mutating workflow"];return o&&s.push(`corroborating failed task: ${o.id} (${o.role})`),{achieved:!1,reason:"code-mutating run completed but made no project edits (false-green)",signals:s}}function Zoe(e,t){let n=t.achieved===!1?`goal-achievement: FALSE-GREEN \u2014 ${t.reason}. ${t.signals.join("; ")}`:t.achieved===!0?`goal-achievement: OK \u2014 ${t.reason}`:`goal-achievement: unknown \u2014 ${t.reason}`,r={...e,goalAchieved:t.achieved,goalAchievementNote:n},o=t.signals.some(s=>s.startsWith("corroborating failed task"));return t.achieved===!1&&o&&r.status==="completed"?{manifest:{...r,status:"failed"},downgraded:!0}:{manifest:r,downgraded:!1}}var hqe,kqe,Qoe=v(()=>{"use strict";Fe();hqe=new Set(["executor","test-engineer"]);kqe=["read-only","read only","do not modify","don't modify","no file modifications","kh\xF4ng s\u1EEDa","kh\xF4ng ch\u1EC9nh s\u1EEDa","ch\u1EC9 \u0111\u1ECDc"]});function ese(e){return e?.groupJoin??"smart"}function Sqe(e,t){return e==="off"?!1:e==="group"?t.length>0:t.length>1}function vqe(e,t){return`${e}_${t.join("+").replace(/[^a-zA-Z0-9_+-]/g,"_")}`}function Tqe(e,t,n){return`${e}:group-join:${n?"partial":"completed"}:${t}`}function x1(e,t){return e.filter(n=>n.status===t).map(n=>n.id)}function tse(e){if(!Sqe(e.mode,e.batch))return;let t=e.batch.map(h=>h.id),n=new Map;for(let h of e.allTasks)n.has(h.id)||n.set(h.id,h);let r=t.map(h=>n.get(h)).filter(h=>!!h),o=x1(r,"completed"),s=x1(r,"failed"),i=x1(r,"skipped"),a=r.filter(h=>h.status==="queued"||h.status==="running").map(h=>h.id),c=e.partial??a.length>0,u=vqe(e.manifest.runId,t),d=KE(r,e.manifest,e.cache),l=Tqe(e.manifest.runId,u,c),f=QX(e.manifest,l),p=f?Cs(e.manifest).messages[f.id]??f.status:void 0,m={batchId:u,mode:e.mode,partial:c,taskIds:t,completed:o,failed:s,skipped:i,remaining:a,requestId:l,ackRequired:!0,ackStatus:p==="acknowledged"?"acknowledged":"pending"},g=`${JSON.stringify({...m,createdAt:new Date().toISOString()},null,2)}
712
712
  `,w=ye(e.manifest.artifactsRoot,{kind:"metadata",relativePath:`metadata/group-joins/${u}.json`,producer:"group-join",content:g}),b=f??wc(e.manifest,{direction:"outbox",from:"group-join",to:"leader",body:[`Group join ${c?"partial":"completed"}: ${t.join(", ")}`,`Request: ${l}`,`Completed: ${o.join(", ")||"none"}`,`Failed: ${s.join(", ")||"none"}`,`Skipped: ${i.join(", ")||"none"}`,`Remaining: ${a.join(", ")||"none"}`,"",d].join(`
713
- `),status:"delivered",data:{kind:"group_join",requestId:l,batchId:u,partial:c,ackRequired:!0,taskIds:t,completed:o,failed:s,skipped:i,remaining:a}});return Ce(e.manifest.eventsPath,{type:c?"agent.group_join.partial":"agent.group_join.completed",runId:e.manifest.runId,message:`Group join ${c?"partial":"completed"} for ${t.length} task(s).`,data:{...m,artifactPath:w.path,messageId:b.id,fallback:"mailbox-delivered",reused:!!f}}),f&&Ce(e.manifest.eventsPath,{type:"agent.group_join.delivery_reused",runId:e.manifest.runId,message:`Reused group join mailbox delivery for ${t.length} task(s).`,data:{requestId:l,messageId:b.id,batchId:u,partial:c}}),{...m,artifact:w,messageId:b.id}}var nse=v(()=>{"use strict";Qs();Te();pr();Qp()});async function E1(e){let t=e.wfMachine,n=e.tasks,r=e.manifest,o=new Set(["completed","failed","skipped","cancelled","needs_attention"]),s=new Map;for(let a of n){if(!a.stepId)continue;let c=s.get(a.stepId)??[];c.push(a.id),s.set(a.stepId,c)}let i=new Map(n.map(a=>[a.id,a]));for(let a=t.currentPhaseIndex;a<t.phases.length;a++){let c=t.phases[a],u=s.get(c.name)??[];if(u.length===0)continue;if(!u.every(l=>{let f=i.get(l);return f?o.has(f.status):!1}))break;if(c.status!=="completed"&&c.status!=="failed"&&c.status!=="skipped"){let l=r.artifacts.filter(h=>h.kind==="result"||h.kind==="summary").map(h=>h.path),f=a>0?t.phases[a-1]?.status??"pending":"completed",p={completedArtifacts:l,previousPhaseStatus:f,taskResults:n.filter(h=>h.status==="completed"||h.status==="needs_attention").map(h=>({taskId:h.id,status:h.status,outputPath:h.resultArtifact?.path}))},w=u.map(h=>i.get(h)).filter(h=>h!==void 0).some(h=>h.status==="failed"||h.status==="cancelled")?"failed":"completed",b=Ere(t,a,w,p);if(t=b.machine,b.guardResult&&!b.guardResult.allowed){await Q(r.eventsPath,{type:"workflow.phase_guard_blocked",runId:r.runId,message:`Workflow phase '${c.name}' guard blocked: ${b.guardResult.reason??"unknown"}`,data:{phaseIndex:a,phaseName:c.name,reason:b.guardResult.reason}});break}await Q(r.eventsPath,{type:w==="failed"?"workflow.phase_failed":"workflow.phase_completed",runId:r.runId,message:`Workflow phase '${c.name}' ${w}.`,data:{phaseIndex:a,phaseStatus:w}})}t={...t,currentPhaseIndex:a+1}}e.wfMachine=t}var rse,C1=v(()=>{"use strict";Te();LA();rse=E1});function ose(e){A1.set(e.name,e)}function sse(e){return A1.get(e)}function t_(e,t){let n=A1.get(e);if(!n){k("plan-templates",new Error(`Template not found: ${e}`));return}let r=n.phases.map(o=>({name:o.name,role:o.role,task:Rqe(o.taskTemplate,t),dependsOn:o.dependsOn,verificationCommand:o.verificationCommand??n.verificationCommands[o.name]}));return{templateName:e,phases:r,variables:t}}function Rqe(e,t){return e.replace(/\{\{(\w+)\}\}/g,(n,r)=>t[r]??n)}var A1,_1=v(()=>{"use strict";K();A1=new Map;ose({name:"standard-review",description:"Standard code review workflow: explore \u2192 review \u2192 verify",phases:[{name:"explore",role:"explorer",taskTemplate:"Map the codebase and identify the key files related to: {{goal}}. Focus on: {{focusAreas}}.",maxTasks:1,dependsOn:[]},{name:"review",role:"reviewer",taskTemplate:"Review the code identified in the explore phase for: {{goal}}. Check correctness, maintainability, and security.",maxTasks:1,dependsOn:["explore"]},{name:"verify",role:"verifier",taskTemplate:"Verify that all review findings are addressed. Run FAST checks (completes in <2 min): `npm run test:critical && npx tsc --noEmit`. Do NOT run `npm run test:unit` or `npm test` \u2014 too slow (642 files, >4 min). Confirm: {{goal}} is achieved.",maxTasks:1,dependsOn:["review"],verificationCommand:"npm run test:critical && npx tsc --noEmit"}],verificationCommands:{verify:"npm run test:critical && npx tsc --noEmit"}});ose({name:"full-implementation",description:"Full implementation workflow: explore \u2192 plan \u2192 execute \u2192 review \u2192 verify",phases:[{name:"explore",role:"explorer",taskTemplate:"Explore the codebase to understand the current state relevant to: {{goal}}. Identify affected files and patterns.",maxTasks:1,dependsOn:[]},{name:"plan",role:"planner",taskTemplate:"Create a detailed implementation plan for: {{goal}}. Break down into concrete steps with file-level changes.",maxTasks:1,dependsOn:["explore"]},{name:"execute",role:"executor",taskTemplate:"Implement the plan for: {{goal}}. Make all planned changes, write tests, and ensure TypeScript compiles.",maxTasks:3,dependsOn:["plan"]},{name:"review",role:"reviewer",taskTemplate:"Review the implementation of: {{goal}}. Check for correctness, security, performance, and code quality.",maxTasks:1,dependsOn:["execute"]},{name:"verify",role:"verifier",taskTemplate:"Verify the complete implementation of: {{goal}}. Run FAST checks (`npm run test:critical && npx tsc --noEmit`, completes in <2 min). Do NOT run `npm run test:unit` or `npm test` \u2014 too slow for in-loop verification (642 files, >4 min). Validate all acceptance criteria.",maxTasks:1,dependsOn:["review"],verificationCommand:"npm run test:critical && npx tsc --noEmit"}],verificationCommands:{verify:"npm run test:critical && npx tsc --noEmit"}})});import{randomUUID as Iqe}from"node:crypto";import*as ase from"node:fs";function fv(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,32)||"task"}function ise(e){let t=e.trim();if(t.startsWith("```")){let n=t.indexOf(`
713
+ `),status:"delivered",data:{kind:"group_join",requestId:l,batchId:u,partial:c,ackRequired:!0,taskIds:t,completed:o,failed:s,skipped:i,remaining:a}});return Ce(e.manifest.eventsPath,{type:c?"agent.group_join.partial":"agent.group_join.completed",runId:e.manifest.runId,message:`Group join ${c?"partial":"completed"} for ${t.length} task(s).`,data:{...m,artifactPath:w.path,messageId:b.id,fallback:"mailbox-delivered",reused:!!f}}),f&&Ce(e.manifest.eventsPath,{type:"agent.group_join.delivery_reused",runId:e.manifest.runId,message:`Reused group join mailbox delivery for ${t.length} task(s).`,data:{requestId:l,messageId:b.id,batchId:u,partial:c}}),{...m,artifact:w,messageId:b.id}}var nse=v(()=>{"use strict";Qs();Te();pr();Qp()});async function E1(e){let t=e.wfMachine,n=e.tasks,r=e.manifest,o=new Set(["completed","failed","skipped","cancelled","needs_attention"]),s=new Map;for(let a of n){if(!a.stepId)continue;let c=s.get(a.stepId)??[];c.push(a.id),s.set(a.stepId,c)}let i=new Map(n.map(a=>[a.id,a]));for(let a=t.currentPhaseIndex;a<t.phases.length;a++){let c=t.phases[a],u=s.get(c.name)??[];if(u.length===0)continue;if(!u.every(l=>{let f=i.get(l);return f?o.has(f.status):!1}))break;if(c.status!=="completed"&&c.status!=="failed"&&c.status!=="skipped"){let l=r.artifacts.filter(h=>h.kind==="result"||h.kind==="summary").map(h=>h.path),f=a>0?t.phases[a-1]?.status??"pending":"completed",p={completedArtifacts:l,previousPhaseStatus:f,taskResults:n.filter(h=>h.status==="completed"||h.status==="needs_attention").map(h=>({taskId:h.id,status:h.status,outputPath:h.resultArtifact?.path}))},w=u.map(h=>i.get(h)).filter(h=>h!==void 0).some(h=>h.status==="failed"||h.status==="cancelled")?"failed":"completed",b=Ere(t,a,w,p);if(t=b.machine,b.guardResult&&!b.guardResult.allowed){await Q(r.eventsPath,{type:"workflow.phase_guard_blocked",runId:r.runId,message:`Workflow phase '${c.name}' guard blocked: ${b.guardResult.reason??"unknown"}`,data:{phaseIndex:a,phaseName:c.name,reason:b.guardResult.reason}});break}await Q(r.eventsPath,{type:w==="failed"?"workflow.phase_failed":"workflow.phase_completed",runId:r.runId,message:`Workflow phase '${c.name}' ${w}.`,data:{phaseIndex:a,phaseStatus:w}})}t={...t,currentPhaseIndex:a+1}}e.wfMachine=t}var rse,C1=v(()=>{"use strict";Te();LA();rse=E1});function ose(e){A1.set(e.name,e)}function sse(e){return A1.get(e)}function t_(e,t){let n=A1.get(e);if(!n){k("plan-templates",new Error(`Template not found: ${e}`));return}let r=n.phases.map(o=>({name:o.name,role:o.role,task:Rqe(o.taskTemplate,t),dependsOn:o.dependsOn,verificationCommand:o.verificationCommand??n.verificationCommands[o.name]}));return{templateName:e,phases:r,variables:t}}function Rqe(e,t){return e.replace(/\{\{(\w+)\}\}/g,(n,r)=>t[r]??n)}var A1,_1=v(()=>{"use strict";K();A1=new Map;ose({name:"standard-review",description:"Standard code review workflow: explore \u2192 review \u2192 verify",phases:[{name:"explore",role:"explorer",taskTemplate:"Map the codebase and identify the key files related to: {{goal}}. Focus on: {{focusAreas}}.",maxTasks:1,dependsOn:[]},{name:"review",role:"reviewer",taskTemplate:"Review the code identified in the explore phase for: {{goal}}. Check correctness, maintainability, and security.",maxTasks:1,dependsOn:["explore"]},{name:"verify",role:"verifier",taskTemplate:"Verify that all review findings are addressed. Run FAST checks (completes in <2 min): `npm run test:critical && npx tsc --noEmit`. Do NOT run `npm run test:unit` or `npm test` \u2014 too slow (642 files, >4 min). Confirm: {{goal}} is achieved. Start the report with the verdict line `PASS: <what verified> \u2014 <evidence>` or `FAIL: <what failed> \u2014 <reason>` (the green-contract consumer reads it; no verdict line = UNVERIFIED).",maxTasks:1,dependsOn:["review"],verificationCommand:"npm run test:critical && npx tsc --noEmit"}],verificationCommands:{verify:"npm run test:critical && npx tsc --noEmit"}});ose({name:"full-implementation",description:"Full implementation workflow: explore \u2192 plan \u2192 execute \u2192 review \u2192 verify",phases:[{name:"explore",role:"explorer",taskTemplate:"Explore the codebase to understand the current state relevant to: {{goal}}. Identify affected files and patterns.",maxTasks:1,dependsOn:[]},{name:"plan",role:"planner",taskTemplate:"Create a detailed implementation plan for: {{goal}}. Break down into concrete steps with file-level changes.",maxTasks:1,dependsOn:["explore"]},{name:"execute",role:"executor",taskTemplate:"Implement the plan for: {{goal}}. Make all planned changes, write tests, and ensure TypeScript compiles.",maxTasks:3,dependsOn:["plan"]},{name:"review",role:"reviewer",taskTemplate:"Review the implementation of: {{goal}}. Check for correctness, security, performance, and code quality.",maxTasks:1,dependsOn:["execute"]},{name:"verify",role:"verifier",taskTemplate:"Verify the complete implementation of: {{goal}}. Run FAST checks (`npm run test:critical && npx tsc --noEmit`, completes in <2 min). Do NOT run `npm run test:unit` or `npm test` \u2014 too slow for in-loop verification (642 files, >4 min). Validate all acceptance criteria. Start the report with the verdict line `PASS: <what verified> \u2014 <evidence>` or `FAIL: <what failed> \u2014 <reason>` (the green-contract consumer reads it; no verdict line = UNVERIFIED).",maxTasks:1,dependsOn:["review"],verificationCommand:"npm run test:critical && npx tsc --noEmit"}],verificationCommands:{verify:"npm run test:critical && npx tsc --noEmit"}})});import{randomUUID as Iqe}from"node:crypto";import*as ase from"node:fs";function fv(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,32)||"task"}function ise(e){let t=e.trim();if(t.startsWith("```")){let n=t.indexOf(`
714
714
  `);n>=0?t=t.slice(n+1):t=t.slice(3)}return t.endsWith("```")&&(t=t.slice(0,-3)),t.trim()}function use(e){let t=e.match(/ADAPTIVE_PLAN_JSON_START\s*([\s\S]*?)\s*ADAPTIVE_PLAN_JSON_END/);if(t?.[1])return ise(t[1]);let n=e.indexOf("ADAPTIVE_PLAN_JSON_START");return n>=0?ise(e.slice(n+24)):e.match(/```(?:json)?\s*([\s\S]*?)```/i)?.[1]}function dse(e,t){let n=e.match(/^template:([a-zA-Z0-9_-]+)/);if(n?.[1]&&sse(n[1])){let u={};try{let l=e.slice(n[0].length).trim();l&&(u=JSON.parse(l))}catch{}let d=t_(n[1],u);if(d){let l=d.phases.map(f=>({name:f.name,tasks:[{role:f.role,task:f.task}]}));return l.length?{phases:l}:void 0}}let r=use(e);if(!r)return;let o;try{o=JSON.parse(r)}catch{return}if(!o||typeof o!="object"||Array.isArray(o))return;let s=Array.isArray(o.phases)?o.phases:Array.isArray(o.tasks)?[{name:"adaptive",tasks:o.tasks}]:void 0;if(!s)return;let i=new Set(t),a=[];for(let[c,u]of s.entries()){if(!u||typeof u!="object"||Array.isArray(u))return;let d=u;if(!Array.isArray(d.tasks)||d.tasks.length===0)return;let l=[];for(let f of d.tasks){if(!f||typeof f!="object"||Array.isArray(f))return;let p=f;if(typeof p.role!="string"||!i.has(p.role)||typeof p.task!="string"||!p.task.trim()||l.length>=cse)return;l.push({role:p.role,title:typeof p.title=="string"?p.title:void 0,task:p.task.trim()})}a.push({name:typeof d.name=="string"&&d.name.trim()?d.name.trim():`phase-${c+1}`,tasks:l})}return a.length?{phases:a}:void 0}function xqe(e){let t=e.trim(),n=[],r=!1,o=!1;for(let s of t){if(o){o=!1;continue}if(s==="\\"&&r){o=!0;continue}if(s==='"'){r=!r;continue}r||(s==="{"?n.push("}"):s==="["?n.push("]"):(s==="}"||s==="]")&&n.at(-1)===s&&n.pop())}for(;n.length;)t+=n.pop();return r?{text:t,status:"unstable",warning:"JSON string was truncated \u2014 values may be incorrect"}:{text:t,status:"repaired"}}function Eqe(e){let t=e.indexOf('"phases"');if(t<0)return;let n=e.indexOf("[",t);if(n<0)return;let r=[],o=-1,s=0,i=!1,a=!1;for(let c=n+1;c<e.length;c++){let u=e[c];if(a){a=!1;continue}if(u==="\\"&&i){a=!0;continue}if(u==='"'){i=!i;continue}if(!i){if(u==="{"){s===0&&(o=c),s++;continue}if(u==="}"){if(s<=0)continue;if(s--,s===0&&o>=0){try{r.push(JSON.parse(e.slice(o,c+1)))}catch{}o=-1}}}}return r.length?{phases:r}:void 0}function Cqe(e,t){if(t.has(e))return e;let n=fv(e),r={reviewer:["code-reviewer","review","code-review","critic"],"security-reviewer":["security","security-review","sec-review"],"test-engineer":["tester","qa","test"],executor:["developer","implementer","coder","engineer"],explorer:["researcher","scout"],analyst:["analysis","analyzer"]};for(let[o,s]of Object.entries(r))if(t.has(o)&&s.includes(n))return o}function lse(e,t){let n=use(e);if(!n)return{repaired:!1,reason:"missing-json"};let r=xqe(n),o=[n,r.text],s,i=!1;for(let l of o)try{s=JSON.parse(l);break}catch{}if(s||(s=Eqe(n),i=s!==void 0),!s||typeof s!="object"||Array.isArray(s))return{repaired:!1,reason:"invalid-json"};let a=Array.isArray(s.phases)?s.phases:Array.isArray(s.tasks)?[{name:"adaptive",tasks:s.tasks}]:void 0;if(!a)return{repaired:!1,reason:"missing-phases"};let c=new Set(t),u=[],d=i||n!==r.text;for(let[l,f]of a.entries()){if(!f||typeof f!="object"||Array.isArray(f))continue;let p=f;if(!Array.isArray(p.tasks))continue;let m=[];for(let g of p.tasks){if(m.length>=cse){d=!0;break}if(!g||typeof g!="object"||Array.isArray(g)){d=!0;continue}let w=g,b=typeof w.role=="string"?Cqe(w.role,c):void 0,h=typeof w.task=="string"?w.task.trim():"";if(!b||!h){d=!0;continue}m.push({role:b,title:typeof w.title=="string"?w.title:void 0,task:h})}m.length&&u.push({name:typeof p.name=="string"&&p.name.trim()?p.name.trim():`phase-${l+1}`,tasks:m})}return u.length?{plan:{phases:u},repaired:!0,reason:d?"repaired":"normalized"}:{repaired:!1,reason:"empty-plan"}}function Aqe(e,t){let n=new Set(e.steps.map(o=>o.id)),r=[];for(let o of t)!o.stepId?.startsWith("adaptive-")||!o.adaptive?.task||n.has(o.stepId)||r.push({id:o.stepId,role:o.role,dependsOn:o.graph?.dependencies??o.dependsOn,parallelGroup:`adaptive-${fv(o.adaptive.phase)}`,task:o.adaptive.task});return r.length?{...e,steps:[...e.steps,...r]}:e}function P1(e){return e.adaptive===!0||e.name==="implementation"}async function fse(e){if(!P1(e.workflow)||e.executeWorkers===!1)return{tasks:e.tasks,workflow:e.workflow,injected:!1,missingPlan:!1};if(e.tasks.some(x=>x.stepId?.startsWith("adaptive-")))return{tasks:e.tasks,workflow:Aqe(e.workflow,e.tasks),injected:!1,missingPlan:!1};let t=e.tasks.find(x=>x.stepId==="assess"&&(x.status==="completed"||x.status==="needs_attention"));if(!t)return{tasks:e.tasks,workflow:e.workflow,injected:!1,missingPlan:!1};if(!t.resultArtifact?.path)return qe(e.manifest.eventsPath,{type:"adaptive.plan_missing",runId:e.manifest.runId,taskId:t.id,message:"Adaptive planner result artifact is missing."}),{tasks:e.tasks,workflow:e.workflow,injected:!1,missingPlan:!0};let n=t,r=e.manifest,o=t.resultArtifact.path,s="";try{s=ase.readFileSync(o,"utf-8")}catch{return qe(e.manifest.eventsPath,{type:"adaptive.plan_missing",runId:e.manifest.runId,taskId:n.id,message:"Adaptive planner result artifact could not be read."}),{tasks:e.tasks,workflow:e.workflow,injected:!1,missingPlan:!0}}let i=e.team.roles.map(x=>x.name),a=dse(s,i);if(!a){let x=Y("PI_CREW_ADAPTIVE_REPAIR")==="0"||Y("PI_TEAMS_ADAPTIVE_REPAIR")==="0"?{repaired:!1,reason:"disabled"}:lse(s,i);if(x.plan){a=x.plan;let T=ye(e.manifest.artifactsRoot,{kind:"metadata",relativePath:"metadata/adaptive-repair.json",producer:n.id,content:`${JSON.stringify({reason:x.reason,phases:x.plan.phases.map(I=>({name:I.name,count:I.tasks.length,roles:I.tasks.map(R=>R.role)}))},null,2)}
715
715
  `});r={...e.manifest,updatedAt:new Date().toISOString(),artifacts:[...e.manifest.artifacts,T]},await kt(r),qe(e.manifest.eventsPath,{type:"adaptive.plan_repaired",runId:e.manifest.runId,taskId:n.id,message:"Adaptive planner output was repaired before dynamic subagents were spawned.",data:{reason:x.reason}})}else return qe(e.manifest.eventsPath,{type:"adaptive.plan_repair_failed",runId:e.manifest.runId,taskId:n.id,message:"Adaptive planner output could not be repaired.",data:{reason:x.reason}}),qe(e.manifest.eventsPath,{type:"adaptive.plan_missing",runId:e.manifest.runId,taskId:n.id,message:"Adaptive planner did not produce a valid plan; no dynamic subagents were spawned."}),{tasks:e.tasks,workflow:e.workflow,injected:!1,missingPlan:!0}}let c=[],u=[],d=[],l=[],f=["assess"],p=0;for(let[x,T]of a.phases.entries()){let I=[],R=[];for(let[A,P]of T.tasks.entries()){p++;let C=`adaptive-p${x+1}-t${A+1}`,M=`adaptive-${x+1}-${A+1}-${fv(P.role)}`,$=`adaptive-${String(p).padStart(2,"0")}-${fv(P.role)}`,B=P.task.split(`
716
716
  `).map(V=>V.trim()).filter(Boolean).find(V=>!V.startsWith("#"))??"",L=(P.title??B??M).slice(0,120);R.push(C),l.push({id:C,ref:M,title:L,taskIds:[],specIds:[],acceptance:[],status:"pending"}),c.push({id:M,role:P.role,dependsOn:f,parallelGroup:`adaptive-${fv(T.name)}`,task:P.task}),u.push({id:$,runId:e.manifest.runId,stepId:M,role:P.role,agent:e.team.roles.find(V=>V.name===P.role)?.agent??P.role,title:L,description:P.task!==L?P.task:void 0,status:"queued",dependsOn:f,cwd:e.manifest.cwd,adaptive:{phase:T.name,task:P.task},planItem:C,graph:{taskId:$,dependencies:f,children:[],queue:"blocked"}}),I.push(M)}d.push({id:`adaptive-phase-${x+1}`,title:T.name,itemIds:R,status:"pending"}),f=I}let m=new Map([["assess",n.id],...u.map(x=>[x.stepId??x.id,x.id])]),g=u.map(x=>({...x,dependsOn:x.dependsOn.map(T=>m.get(T)??T),graph:x.graph?{...x.graph,dependencies:x.dependsOn.map(T=>m.get(T)??T),queue:"blocked"}:x.graph})),w=vf([...e.tasks,...g]),b={id:Iqe(),runId:e.manifest.runId,version:1,title:`Adaptive plan (${a.phases.length} phase(s))`,phases:d,items:l,createdAt:new Date().toISOString(),authorTaskId:n.id},h=is(e.manifest);h||wh(e.manifest,b);let S=h?{id:h.id,version:h.version}:{id:b.id,version:b.version};return await kt({...r,updatedAt:new Date().toISOString(),plan:S}),await vr(r,w),await Q(e.manifest.eventsPath,{type:"adaptive.plan_injected",runId:e.manifest.runId,taskId:n.id,message:`Injected ${g.length} adaptive subagent task(s) across ${a.phases.length} phase(s).`,data:{phases:a.phases.map(x=>({name:x.name,count:x.tasks.length,roles:x.tasks.map(T=>T.role)}))}}),{tasks:w,workflow:{...e.workflow,steps:[...e.workflow.steps,...c]},injected:!0,missingPlan:!1}}var cse,pse,mse,M1=v(()=>{"use strict";Ue();Te();pr();gc();we();Ry();_1();cse=12;pse=dse,mse=lse});function _qe(e){let t=new Set;for(let n of e)n.parallelGroup!==void 0&&t.add(n.parallelGroup);return t}function Pqe(e){let t=new Map;for(let r of e)r.parallelGroup!==void 0&&t.set(r.parallelGroup,(t.get(r.parallelGroup)??0)+1);let n=0;for(let r of t.values())r>n&&(n=r);return n}function Mqe(e){if(e.length===0)return 0;let t=new Set(e.map(a=>a.id)),n=new Map,r=new Map;for(let a of e){let c=(a.dependsOn??[]).filter(u=>t.has(u));n.set(a.id,c.length),r.set(a.id,r.get(a.id)??[]);for(let u of c){let d=r.get(u)??[];d.push(a.id),r.set(u,d)}}let o=new Map,s=[];for(let[a,c]of n)c===0&&(o.set(a,1),s.push(a));let i=0;for(;s.length>0;){let a=s.shift(),c=o.get(a)??0;c>i&&(i=c);for(let u of r.get(a)??[]){let d=c+1;d>(o.get(u)??0)&&o.set(u,d),n.set(u,(n.get(u)??0)-1),(n.get(u)??0)===0&&s.push(u)}}return i}function $qe(e){for(let t of e)if((t.dependsOn?.length??0)>=2)return!0;return!1}function gse(e){if(e.runtime==="dynamic")return{topology:"dynamic",stepCount:0,parallelGroupCount:0,fanOutDegree:0,dagDepth:0,recommendation:"any",reason:"Chain/dynamic workflow \u2014 runtime decides topology"};let t=e.steps,n=t.length,r=_qe(t).size,o=Pqe(t),s=Mqe(t);if(e.topology!==void 0&&e.topology!=="dynamic"){let u=e.topology==="single"||e.topology==="sequential"?"raw_agent":e.topology==="concurrent"?"parallel_research":e.topology==="complex-dag"?"implementation_adaptive":"any";return{topology:e.topology,stepCount:n,parallelGroupCount:r,fanOutDegree:o,dagDepth:s,recommendation:u,reason:`Explicit topology from frontmatter: '${e.topology}'`}}let i,a,c;return n===1?(i="single",a="raw_agent",c="Single-task workflow: no concurrency or DAG structure to justify pi-crew overhead."):r>=1&&o>=3?(i="concurrent",a="parallel_research",c=`Concurrent fan-out: ${o} steps in parallel group(s) of size \u22653.`):n>=4&&$qe(t)?(i="complex-dag",a="implementation_adaptive",c=`Complex DAG: ${n} steps with branching (\u22652 deps on \u22651 node), depth ${s}.`):(i="sequential",n<=3?(a="raw_agent",c=`Sequential chain of ${n} steps \u2014 raw Agent calls are faster.`):(a="fast_fix",c=`Sequential chain of ${n} steps \u2014 audit-trail-justified, but raw calls remain faster.`)),{topology:i,stepCount:n,parallelGroupCount:r,fanOutDegree:o,dagDepth:s,recommendation:a,reason:c}}var hse=v(()=>{"use strict"});var $1={};ve($1,{validateWorkflowUsage:()=>Oqe});function yse(e,t,n,r){return{level:"info",message:r,suggestion:"",topology:e,stepCount:t,recommendation:n}}function wse(e,t,n,r){return{level:"note",message:r,suggestion:"Validated use case \u2014 proceeding.",topology:e,stepCount:t,recommendation:n}}function n_(e,t,n,r,o){return{level:"warn",message:r,suggestion:o,topology:e,stepCount:t,recommendation:n}}function Oqe(e,t={}){let n=gse(e),{topology:r,stepCount:o,recommendation:s}=n;return r==="dynamic"?yse(r,o,s,"Dynamic workflow \u2014 runtime decides topology."):t.force===!0?yse(r,o,s,`Force-bypassed preflight acknowledged (topology=${r}, stepCount=${o}). Proceeding as requested.`):r==="single"?n_(r,o,s,"Single-task workflow: pi-crew overhead exceeds benefit; raw Agent tool would be ~30\xD7 faster and ~5\xD7 cheaper. Proceeding anyway \u2014 proceed only if audit trail or team coordination matters here.","Consider using the raw Agent tool instead. If proceeding, no action needed \u2014 pi-crew will run the workflow as configured."):r==="sequential"?o===2?n_(r,o,s,"2-step sequential chain: pi-crew adds overhead; 2 raw Agent calls would be faster. Proceeding anyway.","Consider 2 raw Agent calls in one turn if speed matters. Otherwise, no action needed."):o===3?n_(r,o,s,"3-step sequential chain: measured 5.7\xD7 slower and 1.9\xD7 costlier than 3 raw Agent calls (Run #3 in .crew/state/runs/). Proceeding anyway.","Consider 3 raw Agent calls. If audit trail justifies overhead, proceed."):n_(r,o,s,`${o}-step sequential chain: longer chains may justify pi-crew for audit/dag-context reasons, but raw Agent calls remain faster. Proceeding anyway.`,"Consider chaining raw Agent calls if speed matters. Otherwise, no action needed."):r==="concurrent"?wse(r,o,s,`Validated use case: ${n.fanOutDegree}-way parallel fan-out. pi-crew's parallelism wins here.`):wse(r,o,s,`Validated use case: complex DAG with ${o} steps, depth ${n.dagDepth}. pi-crew's dependency-context injection and adaptive-plan support wins here.`)}var O1=v(()=>{"use strict";hse()});var r_={};ve(r_,{__test__advanceWorkflowPhases:()=>rse,__test__cancelPlanTasks:()=>jqe,__test__ensurePlanApprovalRequested:()=>EX,__test__finalizeRun:()=>Yoe,__test__lastProgressContentHash:()=>zoe,__test__mergeTaskUpdates:()=>vte,__test__mergeUnitResult:()=>Boe,__test__parseAdaptivePlan:()=>pse,__test__repairAdaptivePlan:()=>mse,__test__requiresPlanApproval:()=>xX,__test__selectDispatchBatch:()=>_re,__test__shouldMergeTaskUpdate:()=>Ste,__test__writeProgress:()=>Joe,batchSummarySlug:()=>Rse,checkPerTaskBudget:()=>S1,drainPendingUnits:()=>iv,executeTeamRun:()=>L1,externalTerminalDecision:()=>Ise,hasPendingMutatingTaskAtBoundary:()=>N1,setRunStatusRunning:()=>Tse,shouldUseRetry:()=>e1});import{spawn as Sse}from"node:child_process";import*as By from"node:fs";import*as ji from"node:path";import{fileURLToPath as kse}from"node:url";function Dqe(e,t){let n=ji.join(e,"heartbeat.json"),r=()=>{try{let s=new Date().toISOString();he(n,JSON.stringify({pid:process.pid,at:Date.now(),runId:t,kind:"team-runner",lastTaskUpdateAt:s}),{mode:384})}catch{}};r();let o=setInterval(r,6e4);return()=>clearInterval(o)}function vse(e){try{return[kse(new URL(`../../scripts/${e}`,import.meta.url)),kse(new URL(`../scripts/${e}`,import.meta.url))].find(n=>By.existsSync(n))}catch{return}}function Fqe(e,t,n){let r=c=>{try{By.appendFileSync(ji.join(e.artifactsRoot,"perf-obs.log"),`[${new Date().toISOString()}] ${c}
@@ -872,15 +872,20 @@ team action='cache' action='clear'
872
872
  `}function Ace(e){if(!e||e[0]==="/")return"/";if(/^[A-Za-z]:[\\/]/.test(e))return e.slice(0,3);if(e.startsWith("\\\\")||e.startsWith("//")){let t=e.slice(2),n=Math.max(t.indexOf("\\"),t.indexOf("/"));if(n===-1)return e;let r=Math.max(t.indexOf("\\",n+1),t.indexOf("/",n+1));return r===-1?e:e.slice(0,2+r)}return e}function uo(...e){let t=e.filter(Boolean);if(t.length===0)return"";let n=t.some(u=>u.includes("\\"))?"\\":"/",r=t[0],o="";n==="\\"?r.startsWith("\\\\")?o="\\\\":r.startsWith("\\")&&(o="\\"):r.startsWith("/")&&(o="/");let s=n==="\\"?r.replace(/^\\{1,2}/,""):r.replace(/^\/+/,""),i=t.slice(1),c=[s,...i].filter(Boolean).join(n).replace(new RegExp(`${n==="\\"?"\\\\":"/"}{2,}`,"g"),n);return o+c}function _ce(e){let t=Math.max(e.lastIndexOf("/"),e.lastIndexOf("\\"));return t===-1?e:t===0?e[0]==="/"||e[0]==="\\"?e[0]:e:t===2&&/[A-Za-z]:/.test(e.slice(0,2))?e.slice(0,3):e.slice(0,t)}function Pce(e,t){let n=t??yJe;return n&&typeof n.resolve=="function"?n.resolve(e):e}function iP(e,t){function n(){try{if(Array.isArray(Tw)&&Array.isArray(Rw))return{dirs:Tw,files:Rw}}catch{}return{dirs:[".git"],files:[]}}let r=n(),o=d=>r.dirs.some(l=>fs.existsSync(uo(d,l)))||r.files.some(l=>fs.existsSync(uo(d,l))),s=Pce(e,t);try{s=fs.realpathSync(s)}catch{}let i=Ace(s),a,c;try{a=Cce(sP.homedir()),c=Cce(sP.tmpdir())}catch{a=void 0,c=void 0}let u=d=>a!==void 0&&d===a||c!==void 0&&d===c;for(;s!==i;){if(u(s))return;if(o(s))return s;let d=_ce(s);if(d===s)break;s=d}if(!u(i)&&o(i))return i}function Cce(e){try{return fs.realpathSync(e)}catch{return e}}function kJe(e){let t=iP(e)??e,n=uo(t,".crew");if(fs.existsSync(n))return n;let r=uo(t,".pi");return fs.existsSync(r)?uo(r,"teams"):n}function vJe(e){let t=(n,r)=>{let o;try{o=fs.readdirSync(n,{withFileTypes:!0})}catch{return!1}for(let s of o)if(s.isDirectory()){if(!bJe.has(s.name)||!t(uo(n,s.name),r+1))return!1}else if(s.isFile()||s.isSymbolicLink()){if(s.name===".gitkeep"||r===0&&SJe.has(s.name))continue;return!1}else return!1;return!0};return t(e,0)}function TJe(e,t){try{let n=iP(e)??e,r=uo(n,".pi","teams");if(t===r||!fs.existsSync(r))return;if(vJe(r)){fs.rmSync(r,{recursive:!0,force:!0});return}console.info(`[pi-crew] legacy ${r} still contains data \u2014 kept in place (auto-migration would change the run-lookup path); remove manually once you no longer need it`)}catch(n){console.info(`[pi-crew] legacy .pi/teams residue sweep skipped: ${n instanceof Error?n.message:String(n)}`)}}async function RJe(e){let t=kJe(e);TJe(e,t);let n=[t,uo(t,"state","runs"),uo(t,"state","subagents"),uo(t,"artifacts"),uo(t,"cache"),uo(t,"graphs"),uo(t,"audit")];for(let s of n)fs.mkdirSync(s,{recursive:!0});let r=[uo(t,"artifacts",".gitkeep"),uo(t,"cache",".gitkeep"),uo(t,"graphs",".gitkeep"),uo(t,"audit",".gitkeep")];for(let s of r)fs.existsSync(s)||he(s,"");he(uo(t,"README.md"),wJe());let o=iP(e);if(o){let s=uo(o,".gitignore"),{updateGitignore:i}=await Promise.resolve().then(()=>(eB(),Ece));await i(s)}}var bJe,SJe,IJe,$ce=v(()=>{"use strict";A0();Ge();eB();bJe=new Set(["state","subagents","runs","artifacts","cache","graphs","audit","worktrees","agents","teams","workflows","imports"]),SJe=new Set(["README.md",".gitignore"]);IJe={parseRoot:Ace,safeJoin:uo,safeDirname:_ce,safeResolve:Pce,findProjectRoot:iP}});var Oce={};ve(Oce,{summarizeModelBudget:()=>xJe});function xJe(e){let t=Wi.maxAttempts,n=[];try{let{config:s}=te(e);n=yd({cwd:e,policy:s.runtime?.modelFallback}).candidates,s.reliability?.retryPolicy?.maxAttempts!==void 0&&(t=s.reliability.retryPolicy.maxAttempts)}catch{}let r=_j(Math.max(1,n.length),t),o=n.length?n.join(" \u2192 "):"(default pi model)";return{chain:n,worstCaseSpawnsPerTask:r,maxAttempts:t,line:`[team-tool.run] model routing: ${o} \xB7 worst-case ${r} spawns/task (chain=${Math.max(1,n.length)} \xD7 maxAttempts+1=${t+1})`}}var Dce=v(()=>{"use strict";at();Ey();SA();ou()});import*as ow from"node:fs";function EJe(e,t){if(e.specStrict===!0||e.steps.some(r=>r.specStrict===!0)){if(e.runtime==="dynamic")return`Workflow '${e.name}' uses specStrict, but dynamic workflows do not support strict spec mode in v0.10.x (ctx.agent() tasks have no verifier-role gate). Drop specStrict for DWF runs (ADR-6 erratum \xA711).`;if(!e.steps.some(r=>r.role==="verifier"))return`Workflow '${e.name}' enables specStrict (workflow or step level) but has no verifier-role step \u2014 strict mode requires independent verification (ADR-6 \xA75). Add a verifier step or drop specStrict.`;if(t){let r=[...e.specStrict===!0?e.steps:e.steps.filter(o=>o.specStrict===!0)].flatMap(o=>o.specRefs??[]).map(o=>({id:o,resolved:qE(t,o)!==void 0})).filter(o=>!o.resolved);if(r.length>0)return`Workflow '${e.name}' is strict but these specRefs resolve to nothing in state/specs (typo, not imported, or corrupted): ${r.map(o=>o.id).join(", ")}. Import them first (scripts/spec-import.mjs) or fix the refs (ADR-6 erratum \xA711).`}}}function CJe(){return tB||(tB=Promise.resolve().then(()=>($ce(),Mce))),tB}function AJe(e,t){let n=typeof e.analysis=="string"&&e.analysis.length>0,r=typeof e.analysisPath=="string"&&e.analysisPath.length>0;if(n&&r)return{error:"`analysis` and `analysisPath` are mutually exclusive. Set exactly one.",source:"none"};if(!n&&!r)return{source:"none"};if(r){let s;try{s=de(t,e.analysisPath)}catch{return{error:`analysisPath must be within project directory: ${e.analysisPath}`,source:"none"}}if(!ow.existsSync(s))return{error:`Analysis file not found: ${s}`,source:"none"};let{size:i}=ow.statSync(s);if(i>Nce)return{error:`Analysis file too large: ${i} bytes (max ${Nce}). Trim the analysis or pass a summary inline.`,source:"none"};let a=ow.readFileSync(s,"utf-8"),c=Rd(a);return c?{text:c,source:"path"}:{source:"none"}}let o=Rd(e.analysis);return o?{text:o,source:"inline"}:{source:"none"}}async function Lce(e,t){let n=e.goal??e.task;if(!n)return{kind:"error",result:E(_t("run","goal or task","{ action: 'run', goal: '<what to achieve>' }"),{action:"run",status:"error"},!0)};let r=n.length>60?`${n.slice(0,57)}...`:n,o=t.cwd??process.cwd(),{ensureCrewDirectory:s}=await CJe();await s(o);let i=t;if(o)try{let A=await Oy(o);A&&A!==o&&(i={...t,cwd:A})}catch{}if(e.workspaceMode==="worktree"){let A;try{A=await Oy(i.cwd)}catch{}if(!A)return{kind:"error",result:E(`Worktree mode requires a git repository. '${i.cwd}' is not inside a git repo.
873
873
  Use workspaceMode: 'single' or run from a git repository.`,{action:"run",status:"error"},!0)};if(te(i.cwd).config.requireCleanWorktreeLeader!==!1)try{await jS(A)}catch(C){let M=co(C);return{kind:"error",result:E(`${M}
874
874
  Commit or stash changes before using worktree mode, or use workspaceMode: 'single'.`,{action:"run",status:"error"},!0)}}}let a=$n(nn(i.cwd)),c=On(rn(i.cwd)),u=kr(yn(i.cwd)),d=e.agent?u.find(A=>A.name===e.agent):void 0;if(e.agent&&!d)return{kind:"error",result:E(`Agent '${e.agent}' not found.`,{action:"run",status:"error"},!0)};let l=e.team??"default",f=d?{name:`direct-${d.name}`,description:`Direct subagent run for ${d.name}`,source:"builtin",filePath:"<generated>",roles:[{name:e.role??"agent",agent:d.name,description:d.description}],defaultWorkflow:"direct-agent",workspaceMode:e.workspaceMode}:a.find(A=>A.name===l);if(!f)return{kind:"error",result:E(`Team '${l}' not found.`,{action:"run",status:"error"},!0)};let p=d?"direct-agent":e.workflow==="chain"&&!e.chain?f.defaultWorkflow??"default":e.workflow??f.defaultWorkflow??"default",m=d?{name:"direct-agent",description:`Direct task for ${d.name}`,source:"builtin",filePath:"<generated>",steps:[{id:"01_agent",role:e.role??"agent",task:"{goal}",model:e.model,reads:e.analysis||e.analysisPath?["analysis.md"]:void 0}]}:c.find(A=>A.name===p);if(!m)return{kind:"error",result:E(`Workflow '${p}' not found.`,{action:"run",status:"error"},!0)};let g=AJe(e,i.cwd);if(g.error)return{kind:"error",result:E(g.error,{action:"run",status:"error"},!0)};let{expandParallelResearchWorkflow:w}=await Promise.resolve().then(()=>(b1(),Poe)),b=d?m:w(m,i.cwd),h=!d&&b.runtime==="dynamic";e.runKind!==void 0&&!h&&k("team-tool.run.runKindIgnored",new Error(`Ignoring runKind='${e.runKind}' because workflow '${b.name}' is not dynamic.`),void 0,"warn");let S=d?void 0:EJe(b,i.cwd);if(S)return{kind:"error",result:E(S,{action:"run",status:"error"},!0)};if(!d&&b.specStrict===!0&&process.platform!=="linux"&&console.warn(`\u26A0\uFE0F [team-tool.run] specStrict is enabled but this platform (${process.platform}) has no unshare -rn equivalent: every strict machine-check will FAIL CLOSED (ADR-6 \xA74).`),!d)try{let{summarizeModelBudget:A}=await Promise.resolve().then(()=>(Dce(),Oce));console.warn(A(i.cwd).line)}catch{}if(!d){let{validateWorkflowUsage:A}=await Promise.resolve().then(()=>(O1(),$1)),P=A(b,{force:e.force===!0}),C=P.level==="warn"?"\u26A0\uFE0F ":P.level==="note"?"\u2139\uFE0F ":"",M=P.level.toUpperCase();console.warn(`${C}[team-tool.preflight] ${M}: ${P.message} (workflow=${b.name})`),P.suggestion&&console.warn(`[team-tool.preflight] \u2192 ${P.suggestion}`)}if(!d&&b.source==="builtin"&&Sce(i.cwd,b.name)){let A=Tce(i.cwd,b);if(A.enabled)return g.text&&console.warn(`[team-tool.run] analysis param is ignored by goal-wrapped run (workflow=${b.name}). The analysis artifact will not be written.`),{kind:"error",result:await Rce(e,t,b,n)};A.message&&k("team-tool.run.goalWrapBypassed",new Error(A.message),`workflow=${b.name} reason=${A.reason}`)}let{validateWorkflowForTeam:x}=await Promise.resolve().then(()=>(qC(),tee)),T=x(b,f);if(T.length>0)return{kind:"error",result:E([`Workflow '${b.name}' is not valid for team '${f.name}':`,...T.map(A=>`- ${A}`)].join(`
875
- `),{action:"run",status:"error"},!0)};let{normalizeSkillOverride:I}=await Promise.resolve().then(()=>(Zh(),k9)),R=I(e.skill);return{kind:"ok",intent:{goal:n,intentPrefix:r,resolvedCtx:i,directAgent:!!d,team:f,workflow:b,agents:u,analysisParam:g,isDynamicWorkflow:h,effectiveRunKind:h?e.runKind:void 0,skillOverride:R}}}var Nce,tB,Fce=v(()=>{"use strict";Qo();at();Kh();uF();ks();sv();K();Qe();bs();US();Bt();Ice();ma();Nce=1e5});function Wce(e){let t=_Je(e);return new nB(t).parse()}function _Je(e){let t=[],n=0;for(;n<e.length;){if(/\s/.test(e[n])){n++;continue}if(e[n]==="-"&&e[n+1]===">"){t.push({type:"ARROW",value:"->"}),n+=2;continue}if(e[n]==="("){t.push({type:"LPAREN",value:"("}),n++;continue}if(e[n]===")"){t.push({type:"RPAREN",value:")"}),n++;continue}if(e[n]===","){t.push({type:"COMMA",value:","}),n++;continue}if(e[n]===":"){t.push({type:"COLON",value:":"}),n++;continue}if(e[n]==='"'||e[n]==="'"){let r=e[n],o="";for(n++;n<e.length&&e[n]!==r;)e[n]==="\\"&&n+1<e.length&&n++,o+=e[n],n++;if(n>=e.length)throw new Error("Unclosed quoted string in chain DSL");n++,t.push({type:"QUOTED",value:o});continue}if(e[n]==="-"&&e[n+1]==="-"){let r="";for(n+=2;n<e.length&&/[a-zA-Z0-9_-]/.test(e[n]);)r+=e[n],n++;t.push({type:"FLAG",value:r});continue}if(/[0-9]/.test(e[n])){let r="";for(;n<e.length&&/[0-9]/.test(e[n]);)r+=e[n],n++;t.push({type:"NUMBER",value:r});continue}if(/[a-zA-Z_]/.test(e[n])||e[n]==="@"&&/[a-zA-Z_]/.test(e[n+1]??"")){let r="";for(;n<e.length&&/[a-zA-Z0-9_.@-]/.test(e[n]);)r+=e[n],n++;t.push({type:"NAME",value:r});continue}throw new Error(`Unexpected character '${e[n]}' at position ${n} in chain DSL`)}return t}var nB,jce=v(()=>{"use strict";nB=class{pos=0;tokens;constructor(t){this.tokens=t}parse(){let t=[];for(t.push(this.parseStep(0));this.peek("ARROW");)this.consume("ARROW"),t.push(this.parseStep(0));if(this.pos<this.tokens.length)throw new Error(`Unexpected token '${this.tokens[this.pos]?.value}' at position ${this.pos}`);return t}parseStep(t=0){if(t>100)throw new Error("Chain DSL nesting too deep (max 100); likely unbalanced or malicious input");if(this.peek("NAME","parallel")){this.consume("NAME"),this.consume("LPAREN");let s=[];for(s.push(this.parseStep(t+1));this.peek("COMMA");)this.consume("COMMA"),s.push(this.parseStep(t+1));this.consume("RPAREN");let i={name:"parallel",parallel:s};return this.parseModifiers(i),i}let o={name:this.consume("NAME").value};return this.parseModifiers(o),o}parseModifiers(t){for(;this.pos<this.tokens.length;)if(this.peek("COLON")){this.consume("COLON");let n=this.consume("NUMBER");t.loopCount=Number.parseInt(n.value,10)}else if(this.peek("FLAG","with-context"))this.consume("FLAG"),t.withContext=!0;else if(this.peek("QUOTED")){let n=this.consume("QUOTED");t.args=t.args??[],t.args.push(n.value)}else break}peek(t,n){let r=this.tokens[this.pos];return!(!r||r.type!==t||n!==void 0&&r.value!==n)}consume(t){let n=this.tokens[this.pos];if(!n)throw new Error(`Expected ${t} but reached end of chain DSL`);if(n.type!==t)throw new Error(`Expected ${t} but got ${n.type}('${n.value}')`);return this.pos++,n}}});function Uce(e){return new xv({runTask:()=>Promise.reject(new Error("Not initialized"))},{}).parseChain(e)}var xv,Bce=v(()=>{"use strict";sv();jce();xv=class e{static MAX_CHAIN_HISTORY_SIZE=100;static MAX_HANDOFF_ENTRY_SIZE=5e3;taskRunner;handoffManager;constructor(t,n){this.taskRunner=t,this.handoffManager=n}parseChain(t){if(this.hasDSLConstructs(t))try{let c=Wce(t);return this.dslToChainSpec(c,t)}catch{}let r=this.splitChainSteps(t).map(c=>c.trim()).map((c,u)=>this.parseStep(c,u)),o=this.extractGlobalFlag(t,"global-model"),s=this.extractGlobalFlag(t,"global-skill"),i=this.extractGlobalFlag(t,"global-thinking"),a=this.extractGlobalFlag(t,"continue-on-error")==="true";return{steps:r,globalModel:o,globalSkill:s,globalThinking:i,continueOnError:a}}async runChain(t,n={},r){let o=[],s={...n},i=Date.now(),a=0,c=[],u=!1;for(let f=0;f<t.steps.length;f++){let p=t.steps[f],m=Date.now();try{let g=this.getEffectiveConfig(p,t),w=this.enrichContextFromHandoffs(s,o),b=await this.executeStep(g,w);b.usage?.totalTokens&&(a+=b.usage.totalTokens);let h=await this.handoffManager.generateSummary(this.createMinimalPacket(p,f),b);if(o.push({step:f+1,name:p.name,outcome:b.outcome,result:b,handoff:h,duration:Date.now()-m}),h!==null&&c.push(h),b.outcome==="success")s={...s,[`step_${f}_result`]:b,[`step_${f}_handoff`]:h};else if(!t.continueOnError&&!p.continueOnError){u=!0;break}if(r){let{appendEventAsync:S}=await Promise.resolve().then(()=>(Te(),F8));await S(r,{type:"chain.step_completed",runId:"chain",taskId:`step-${f+1}`,data:{step:f+1,name:p.name,outcome:b.outcome,duration:Date.now()-m}})}}catch(g){let w=co(g);if(o.push({step:f+1,name:p.name,outcome:"failure",duration:Date.now()-m,error:w}),!t.continueOnError&&!p.continueOnError){u=!0;break}}}let d=o.length===t.steps.length,l=o.every(f=>f.outcome==="success");return{steps:o,totalDuration:Date.now()-i,success:t.steps.length>0&&!u&&d&&l,totalTokens:a>0?a:void 0,totalHandoffs:c}}splitChainSteps(t){let n=[],r="",o=!1,s="";for(let i=0;i<t.length;i++){let a=t[i];if(o&&a==="\\"&&i+1<t.length){r+=a+(t[i+1]??""),i++;continue}if(a==='"'||a==="'"){o?a===s&&(o=!1):(o=!0,s=a),r+=a;continue}if(!o&&a==="-"&&t[i+1]===">"){n.push(r),r="",i++;continue}r+=a}return n.push(r),n}parseStep(t,n){let r=t.match(/^@([a-zA-Z][a-zA-Z0-9_]*)/),o=t.match(/^workflow:([a-zA-Z][a-zA-Z0-9_]*)/),s=t.match(/^template:([a-zA-Z][a-zA-Z0-9_]*)/),i=t.match(/"([^"]{1,10000})"/),a=t.split(/\s+/),u={name:a[0]&&a[0].length>0&&a[0].length<=100?a[0]:`step-${n}`};r?.[1]&&(u.team=this.sanitizeIdentifier(r[1])),o?.[1]&&(u.workflow=this.sanitizeIdentifier(o[1])),s?.[1]&&(u.template=this.sanitizeIdentifier(s[1])),i?.[1]&&(u.inlineGoal=this.sanitizeInlineGoal(i[1]));let d=this.extractFlag(t,"model");d&&this.isValidModelName(d)&&(u.model=d);let l=this.extractFlag(t,"skill");l&&this.isValidIdentifier(l)&&(u.skill=l);let f=this.extractFlag(t,"thinking");f&&this.isValidThinkingMode(f)&&(u.thinking=f);let p=this.extractFlag(t,"timeout");if(p){let m=parseInt(p,10);!Number.isNaN(m)&&m>0&&m<=864e5&&(u.timeout=m*1e3)}return this.extractFlag(t,"continue-on-error")==="true"&&(u.continueOnError=!0),u}hasDSLConstructs(t){return/\bparallel\s*\(/.test(t)||/\w+:\d+\b/.test(t)||/--with-context/.test(t)}dslToChainSpec(t,n){let r=[],o=u=>{if(u.parallel){for(let l of u.parallel)o(l);return}let d={name:u.name};if(u.name.startsWith("@")){let l=this.sanitizeIdentifier(u.name.slice(1));l.length>0&&(d.team=l)}u.loopCount&&(d.context={...d.context,loopCount:u.loopCount}),u.withContext&&(d.context={...d.context,withContext:!0}),u.args&&u.args.length>0&&(d.context={...d.context,args:u.args}),r.push(d)};for(let u of t)o(u);let s=this.extractGlobalFlag(n,"global-model"),i=this.extractGlobalFlag(n,"global-skill"),a=this.extractGlobalFlag(n,"global-thinking"),c=this.extractGlobalFlag(n,"continue-on-error")==="true";return{steps:r,globalModel:s,globalSkill:i,globalThinking:a,continueOnError:c}}sanitizeIdentifier(t){return t.replace(/[^a-zA-Z0-9_]/g,"_").substring(0,100)}sanitizeInlineGoal(t){return t.replace(/[\x00-\x1F\x7F]/g,"").substring(0,1e4)}isValidModelName(t){return/^[a-zA-Z][a-zA-Z0-9_-]{0,50}$/.test(t)}isValidIdentifier(t){return/^[a-zA-Z][a-zA-Z0-9_]{0,50}$/.test(t)}isValidThinkingMode(t){return["fast","standard","deep"].includes(t)}extractFlag(t,n){let r=n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return t.match(new RegExp(`--${r}\\s+(\\S+)`))?.[1]}extractGlobalFlag(t,n){let r=n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),o="--"+r+"=\\s*(\\S+)",s=t.match(new RegExp(o,"i"));if(s)return s[1];let i="--"+r+"\\s+(\\S+)",a=t.match(new RegExp(i,"i"));if(a)return a[1]}getEffectiveConfig(t,n){return{...t,model:t.model??n.globalModel,skill:t.skill??n.globalSkill,thinking:t.thinking??n.globalThinking}}enrichContextFromHandoffs(t,n){let r=n.filter(d=>d.handoff).map(d=>d.handoff);if(r.length===0)return t;let o=[],s=r;if(r.length>e.MAX_CHAIN_HISTORY_SIZE){let d=r.length-e.MAX_CHAIN_HISTORY_SIZE;o.push(`[chain history limited to last ${e.MAX_CHAIN_HISTORY_SIZE} entries; ${d} older entr${d===1?"y":"ies"} omitted]`),s=r.slice(-e.MAX_CHAIN_HISTORY_SIZE)}let i=s.filter(d=>JSON.stringify(d).length<=e.MAX_HANDOFF_ENTRY_SIZE),a=s.length-i.length;a>0&&o.push(`[${a} handoff entr${a===1?"y":"ies"} omitted (> ${e.MAX_HANDOFF_ENTRY_SIZE} bytes each)]`);let c=[],u=i.map(d=>{let l=[];return d.filesCreated&&d.filesCreated.length>50&&l.push(`filesCreated=${d.filesCreated.length}`),d.filesModified&&d.filesModified.length>50&&l.push(`filesModified=${d.filesModified.length}`),d.decisions&&d.decisions.length>20&&l.push(`decisions=${d.decisions.length}`),d.nextSteps&&d.nextSteps.length>20&&l.push(`nextSteps=${d.nextSteps.length}`),l.length>0&&c.push(`step ${d.taskId}: ${l.join(", ")} (capped)`),{step:d.taskId,outcome:d.outcome,filesCreated:d.filesCreated?.slice(0,50),filesModified:d.filesModified?.slice(0,50),decisions:d.decisions?.slice(0,20),nextSteps:d.nextSteps?.slice(0,20),...d.outputText?{outputText:d.outputText.slice(0,5e3)}:{}}});return c.length>0&&o.push(`[list caps applied: ${c.join("; ")}]`),{...t,__chainHistory:u,...o.length>0?{__chainHistoryNotes:o}:{}}}async executeStep(t,n){let r={taskId:`chain-${Date.now()}-${t.name}`,runId:"chain",goal:t.inlineGoal??t.name,summarizeThreshold:3e3,collapseContext:!0,context:{...n,__chainStepTeam:t.team,__chainStepWorkflow:t.workflow,__chainStepModel:t.model}};return this.taskRunner.runTask(r)}createMinimalPacket(t,n){return{taskId:`chain-step-${n}`,runId:"chain",sessionId:"chain",goal:t.inlineGoal??t.name}}}});function PJe(e){if(!e||typeof e!="object")return!1;let t=e;if(typeof t.taskId!="string"||!t.taskId||typeof t.runId!="string"||!t.runId||typeof t.timestamp!="number"||typeof t.task!="string"||!t.task||typeof t.outcome!="string"||!["success","failure","partial"].includes(t.outcome)||!Array.isArray(t.filesCreated)||!Array.isArray(t.filesModified)||!Array.isArray(t.filesDeleted)||!Array.isArray(t.decisions)||!Array.isArray(t.blockers)||!Array.isArray(t.nextSteps)||!t.metrics||typeof t.metrics!="object")return!1;let n=t.metrics;return!(typeof n.tokensUsed!="number"||typeof n.duration!="number"||typeof n.iterations!="number"||!Array.isArray(n.toolsUsed)||typeof t.contextSnapshot!="string")}var aP,Gce=v(()=>{"use strict";aP=class{pendingHandoffs=new Map;options;handoffTimestamps=new Map;cleanupTimer=null;disposed=!1;constructor(t={}){this.options={defaultSummarizeThreshold:5e3,handoffTimeoutMs:3e5,cleanupIntervalMs:6e4,...t},this.startCleanupTimer()}startCleanupTimer(){this.disposed||this.cleanupTimer||(this.cleanupTimer=setInterval(()=>{this.cleanupStaleHandoffs()},this.options.cleanupIntervalMs),typeof this.cleanupTimer.unref=="function"&&this.cleanupTimer.unref())}cleanupStaleHandoffs(){if(this.disposed)return;let t=Date.now(),n=this.options.handoffTimeoutMs??3e5,r=t-n,o=[];for(let[s,i]of this.handoffTimestamps.entries())i<r&&o.push(s);for(let s of o)this.pendingHandoffs.delete(s),this.handoffTimestamps.delete(s);if(this.pendingHandoffs.size>1e3){let s=[...this.handoffTimestamps.entries()].sort((a,c)=>a[1]-c[1]),i=s.length-1e3;for(let a=0;a<i;a++){let c=s[a][0];this.pendingHandoffs.delete(c),this.handoffTimestamps.delete(c)}}}async onAgentEnd(t,n){if(this.disposed||!this.shouldSummarize(t,n).shouldSummarize)return null;let r=await this.generateSummary(t,n);return PJe(r)?(t.sessionId&&(this.pendingHandoffs.set(t.sessionId,r),this.handoffTimestamps.set(t.sessionId,Date.now())),this.options.eventEmitter?.emit("handoff:generated",{packet:t,summary:r}),t.collapseContext&&await this.collapseContext(t,r),r):(this.options.eventEmitter?.emit("handoff:validation_failed",{packet:t,error:"Generated summary failed structure validation"}),null)}async onBeforeTreeNavigation(t,n){if(this.disposed)return null;let r=this.pendingHandoffs.get(t);return r?(this.pendingHandoffs.delete(t),this.handoffTimestamps.delete(t),r):null}shouldSummarize(t,n){if(!t||typeof t.taskId!="string"||!t.taskId)return{shouldSummarize:!1,reason:"Invalid task packet structure",tokenCount:0};if(!n||typeof n.outcome!="string")return{shouldSummarize:!1,reason:"Invalid task result structure",tokenCount:0};let r=t.summarizeThreshold??this.options.defaultSummarizeThreshold??5e3,o=n.usage?.totalTokens??0;if(o>r)return{shouldSummarize:!0,reason:`Token count ${o} exceeds threshold ${r}`,tokenCount:o};if(n.outcome==="success"&&(n.toolsUsed?.length??0)>=3)return{shouldSummarize:!0,reason:`Task used ${n.toolsUsed?.length??0} tools, exceeding minimum of 3`,tokenCount:o};if(t.forceSummarize===!0)return{shouldSummarize:!0,reason:"Forced summarization requested",tokenCount:o};let s=(n.filesCreated?.length??0)>0||(n.filesModified?.length??0)>0,i=(n.decisions?.length??0)>0;return s||i?{shouldSummarize:!0,reason:"Task produced significant artifacts or decisions",tokenCount:o}:n.outcome!=="success"?{shouldSummarize:!0,reason:`Task outcome is ${n.outcome}`,tokenCount:o}:{shouldSummarize:!1,reason:"Task below summarization threshold",tokenCount:o}}async generateSummary(t,n){let r=this.extractArtifacts(n),o=this.extractDecisionsFromResult(n),s=await this.generateContextSnapshot(t.runId,t.taskId,n);return{taskId:t.taskId,runId:t.runId,timestamp:Date.now(),task:t.goal,outcome:n.outcome,filesCreated:r.created,filesModified:r.modified,filesDeleted:r.deleted,decisions:o,blockers:n.blockers??[],nextSteps:n.nextSteps??[],metrics:{tokensUsed:n.usage?.totalTokens??0,duration:n.duration??0,iterations:n.iterations??1,toolsUsed:n.toolsUsed??[]},contextSnapshot:s,...n.outputText?{outputText:n.outputText}:{}}}async collapseContext(t,n){globalThis.__boomerangCollapseInProgress=!0;try{this.options.eventEmitter?.emit("handoff:context_collapse",{sessionId:t.sessionId,taskId:t.taskId,summary:n})}finally{globalThis.__boomerangCollapseInProgress=!1}}getPendingHandoff(t){return this.pendingHandoffs.get(t)}clearPendingHandoff(t){this.pendingHandoffs.delete(t),this.handoffTimestamps.delete(t)}clearAllPendingHandoffs(){this.pendingHandoffs.clear(),this.handoffTimestamps.clear()}getPendingCount(){return this.pendingHandoffs.size}extractArtifacts(t){return{created:t.filesCreated??[],modified:t.filesModified??[],deleted:t.filesDeleted??[]}}extractDecisionsFromResult(t){return t.decisions&&t.decisions.length>0?t.decisions:t.outcome==="failure"?[{rationale:"Task failed",outcome:t.error??"Unknown error",alternativesConsidered:[]}]:[]}async generateContextSnapshot(t,n,r){let o=[];return o.push(`Task: ${n}`),o.push(`Outcome: ${r.outcome}`),r.usage?.totalTokens&&o.push(`Tokens: ${r.usage.totalTokens}`),r.toolsUsed?.length&&o.push(`Tools: ${r.toolsUsed.join(", ")}`),r.blockers?.length&&o.push(`Blockers: ${r.blockers.join("; ")}`),r.nextSteps?.length&&o.push(`Next Steps: ${r.nextSteps.join("; ")}`),o.join(`
875
+ `),{action:"run",status:"error"},!0)};let{normalizeSkillOverride:I}=await Promise.resolve().then(()=>(Zh(),k9)),R=I(e.skill);return{kind:"ok",intent:{goal:n,intentPrefix:r,resolvedCtx:i,directAgent:!!d,team:f,workflow:b,agents:u,analysisParam:g,isDynamicWorkflow:h,effectiveRunKind:h?e.runKind:void 0,skillOverride:R}}}var Nce,tB,Fce=v(()=>{"use strict";Qo();at();Kh();uF();ks();sv();K();Qe();bs();US();Bt();Ice();ma();Nce=1e5});function Wce(e){let t=_Je(e);return new nB(t).parse()}function _Je(e){let t=[],n=0;for(;n<e.length;){if(/\s/.test(e[n])){n++;continue}if(e[n]==="-"&&e[n+1]===">"){t.push({type:"ARROW",value:"->"}),n+=2;continue}if(e[n]==="("){t.push({type:"LPAREN",value:"("}),n++;continue}if(e[n]===")"){t.push({type:"RPAREN",value:")"}),n++;continue}if(e[n]===","){t.push({type:"COMMA",value:","}),n++;continue}if(e[n]===":"){t.push({type:"COLON",value:":"}),n++;continue}if(e[n]==='"'||e[n]==="'"){let r=e[n],o="";for(n++;n<e.length&&e[n]!==r;)e[n]==="\\"&&n+1<e.length&&n++,o+=e[n],n++;if(n>=e.length)throw new Error("Unclosed quoted string in chain DSL");n++,t.push({type:"QUOTED",value:o});continue}if(e[n]==="-"&&e[n+1]==="-"){let r="";for(n+=2;n<e.length&&/[a-zA-Z0-9_-]/.test(e[n]);)r+=e[n],n++;t.push({type:"FLAG",value:r});continue}if(/[0-9]/.test(e[n])){let r="";for(;n<e.length&&/[0-9]/.test(e[n]);)r+=e[n],n++;t.push({type:"NUMBER",value:r});continue}if(/[a-zA-Z_]/.test(e[n])||e[n]==="@"&&/[a-zA-Z_]/.test(e[n+1]??"")){let r="";for(;n<e.length&&/[a-zA-Z0-9_.@-]/.test(e[n]);)r+=e[n],n++;t.push({type:"NAME",value:r});continue}throw new Error(`Unexpected character '${e[n]}' at position ${n} in chain DSL`)}return t}var nB,jce=v(()=>{"use strict";nB=class{pos=0;tokens;constructor(t){this.tokens=t}parse(){let t=[];for(t.push(this.parseStep(0));this.peek("ARROW");)this.consume("ARROW"),t.push(this.parseStep(0));if(this.pos<this.tokens.length)throw new Error(`Unexpected token '${this.tokens[this.pos]?.value}' at position ${this.pos}`);return t}parseStep(t=0){if(t>100)throw new Error("Chain DSL nesting too deep (max 100); likely unbalanced or malicious input");if(this.peek("NAME","parallel")){this.consume("NAME"),this.consume("LPAREN");let s=[];for(s.push(this.parseStep(t+1));this.peek("COMMA");)this.consume("COMMA"),s.push(this.parseStep(t+1));this.consume("RPAREN");let i={name:"parallel",parallel:s};return this.parseModifiers(i),i}if(this.peek("QUOTED")){let i={name:this.consume("QUOTED").value};return this.parseModifiers(i),i}let o={name:this.consume("NAME").value};return this.parseModifiers(o),o}parseModifiers(t){for(;this.pos<this.tokens.length;)if(this.peek("COLON")){this.consume("COLON");let n=this.consume("NUMBER");t.loopCount=Math.min(10,Math.max(1,Number.parseInt(n.value,10)))}else if(this.peek("FLAG","with-context"))this.consume("FLAG"),t.withContext=!0;else if(this.peek("QUOTED")){let n=this.consume("QUOTED");t.args=t.args??[],t.args.push(n.value)}else break}peek(t,n){let r=this.tokens[this.pos];return!(!r||r.type!==t||n!==void 0&&r.value!==n)}consume(t){let n=this.tokens[this.pos];if(!n)throw new Error(`Expected ${t} but reached end of chain DSL`);if(n.type!==t)throw new Error(`Expected ${t} but got ${n.type}('${n.value}')`);return this.pos++,n}}});function Uce(e){return new xv({runTask:()=>Promise.reject(new Error("Not initialized"))},{}).parseChain(e)}var xv,Bce=v(()=>{"use strict";sv();jce();xv=class e{static MAX_CHAIN_HISTORY_SIZE=100;static MAX_HANDOFF_ENTRY_SIZE=5e3;static MAX_WITH_CONTEXT_OUTPUT_CHARS=2e4;taskRunner;handoffManager;constructor(t,n){this.taskRunner=t,this.handoffManager=n}parseChain(t){if(this.hasDSLConstructs(t))try{let c=Wce(t);return this.dslToChainSpec(c,t)}catch{}let r=this.splitChainSteps(t).map(c=>c.trim()).map((c,u)=>this.parseStep(c,u)),o=this.extractGlobalFlag(t,"global-model"),s=this.extractGlobalFlag(t,"global-skill"),i=this.extractGlobalFlag(t,"global-thinking"),a=this.extractGlobalFlag(t,"continue-on-error")==="true";return{steps:r,globalModel:o,globalSkill:s,globalThinking:i,continueOnError:a}}async runChain(t,n={},r){let o=[],s={...n},i=Date.now(),a=0,c=[],u=!1,d=this.buildExecutionPlan(t),l=d.length;for(let m of d){let{step:g,stepIndex:w,displayName:b,iterations:h}=m,S=Date.now();try{let x=this.getEffectiveConfig(g,t),T=this.enrichContextFromHandoffs(s,o),I=await this.executeStep(x,T,o);I.usage?.totalTokens&&(a+=I.usage.totalTokens);let R=await this.handoffManager.generateSummary(this.createMinimalPacket(g,w),I);if(o.push({step:w+1,name:b,outcome:I.outcome,result:I,handoff:R,duration:Date.now()-S}),R!==null&&c.push(R),I.outcome==="success")s={...s,[`step_${w}_result`]:I,[`step_${w}_handoff`]:R};else if(!t.continueOnError&&!g.continueOnError){u=!0;break}if(r){let{appendEventAsync:A}=await Promise.resolve().then(()=>(Te(),F8));await A(r,{type:"chain.step_completed",runId:"chain",taskId:h>1?`step-${w+1}#${m.iter}`:`step-${w+1}`,data:{step:w+1,name:b,outcome:I.outcome,duration:Date.now()-S}})}}catch(x){let T=co(x);if(o.push({step:w+1,name:b,outcome:"failure",duration:Date.now()-S,error:T}),!t.continueOnError&&!g.continueOnError){u=!0;break}}}let f=o.length===l,p=o.every(m=>m.outcome==="success");return{steps:o,totalDuration:Date.now()-i,success:t.steps.length>0&&!u&&f&&p,totalTokens:a>0?a:void 0,totalHandoffs:c}}splitChainSteps(t){let n=[],r="",o=!1,s="";for(let i=0;i<t.length;i++){let a=t[i];if(o&&a==="\\"&&i+1<t.length){r+=a+(t[i+1]??""),i++;continue}if(a==='"'||a==="'"){o?a===s&&(o=!1):(o=!0,s=a),r+=a;continue}if(!o&&a==="-"&&t[i+1]===">"){n.push(r),r="",i++;continue}r+=a}return n.push(r),n}parseStep(t,n){let r=t.match(/^@([a-zA-Z][a-zA-Z0-9_]*)/),o=t.match(/^workflow:([a-zA-Z][a-zA-Z0-9_]*)/),s=t.match(/^template:([a-zA-Z][a-zA-Z0-9_]*)/),i=t.match(/"([^"]{1,10000})"/),a=t.split(/\s+/),u={name:a[0]&&a[0].length>0&&a[0].length<=100?a[0]:`step-${n}`};r?.[1]&&(u.team=this.sanitizeIdentifier(r[1])),o?.[1]&&(u.workflow=this.sanitizeIdentifier(o[1])),s?.[1]&&(u.template=this.sanitizeIdentifier(s[1])),i?.[1]&&(u.inlineGoal=this.sanitizeInlineGoal(i[1]));let d=this.extractFlag(t,"model");d&&this.isValidModelName(d)&&(u.model=d);let l=this.extractFlag(t,"skill");l&&this.isValidIdentifier(l)&&(u.skill=l);let f=this.extractFlag(t,"thinking");f&&this.isValidThinkingMode(f)&&(u.thinking=f);let p=this.extractFlag(t,"timeout");if(p){let m=parseInt(p,10);!Number.isNaN(m)&&m>0&&m<=86400&&(u.timeout=m*1e3)}return this.extractFlag(t,"continue-on-error")==="true"&&(u.continueOnError=!0),u}hasDSLConstructs(t){return/\bparallel\s*\(/.test(t)||/:\d+\b/.test(t)||/--with-context/.test(t)}dslToChainSpec(t,n){let r=[],o=u=>{if(u.parallel){for(let l of u.parallel)o(l);return}let d={name:u.name};if(u.name.startsWith("@")){let l=this.sanitizeIdentifier(u.name.slice(1));l.length>0&&(d.team=l)}u.loopCount&&(d.context={...d.context,loopCount:u.loopCount}),u.withContext&&(d.context={...d.context,withContext:!0}),u.args&&u.args.length>0&&(d.context={...d.context,args:u.args}),r.push(d)};for(let u of t)o(u);let s=this.extractGlobalFlag(n,"global-model"),i=this.extractGlobalFlag(n,"global-skill"),a=this.extractGlobalFlag(n,"global-thinking"),c=this.extractGlobalFlag(n,"continue-on-error")==="true";return{steps:r,globalModel:s,globalSkill:i,globalThinking:a,continueOnError:c}}sanitizeIdentifier(t){return t.replace(/[^a-zA-Z0-9_]/g,"_").substring(0,100)}sanitizeInlineGoal(t){return t.replace(/[\x00-\x1F\x7F]/g,"").substring(0,1e4)}isValidModelName(t){return/^[a-zA-Z][a-zA-Z0-9_-]{0,50}$/.test(t)}isValidIdentifier(t){return/^[a-zA-Z][a-zA-Z0-9_]{0,50}$/.test(t)}isValidThinkingMode(t){return["fast","standard","deep"].includes(t)}extractFlag(t,n){let r=n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return t.match(new RegExp(`--${r}\\s+(\\S+)`))?.[1]}extractGlobalFlag(t,n){let r=n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),o="--"+r+"=\\s*(\\S+)",s=t.match(new RegExp(o,"i"));if(s)return s[1];let i="--"+r+"\\s+(\\S+)",a=t.match(new RegExp(i,"i"));if(a)return a[1]}getEffectiveConfig(t,n){return{...t,model:t.model??n.globalModel,skill:t.skill??n.globalSkill,thinking:t.thinking??n.globalThinking}}enrichContextFromHandoffs(t,n){let r=n.filter(d=>d.handoff).map(d=>d.handoff);if(r.length===0)return t;let o=[],s=r;if(r.length>e.MAX_CHAIN_HISTORY_SIZE){let d=r.length-e.MAX_CHAIN_HISTORY_SIZE;o.push(`[chain history limited to last ${e.MAX_CHAIN_HISTORY_SIZE} entries; ${d} older entr${d===1?"y":"ies"} omitted]`),s=r.slice(-e.MAX_CHAIN_HISTORY_SIZE)}let i=s.filter(d=>JSON.stringify(d).length<=e.MAX_HANDOFF_ENTRY_SIZE),a=s.length-i.length;a>0&&o.push(`[${a} handoff entr${a===1?"y":"ies"} omitted (> ${e.MAX_HANDOFF_ENTRY_SIZE} bytes each)]`);let c=[],u=i.map(d=>{let l=[];return d.filesCreated&&d.filesCreated.length>50&&l.push(`filesCreated=${d.filesCreated.length}`),d.filesModified&&d.filesModified.length>50&&l.push(`filesModified=${d.filesModified.length}`),d.decisions&&d.decisions.length>20&&l.push(`decisions=${d.decisions.length}`),d.nextSteps&&d.nextSteps.length>20&&l.push(`nextSteps=${d.nextSteps.length}`),l.length>0&&c.push(`step ${d.taskId}: ${l.join(", ")} (capped)`),{step:d.taskId,outcome:d.outcome,filesCreated:d.filesCreated?.slice(0,50),filesModified:d.filesModified?.slice(0,50),decisions:d.decisions?.slice(0,20),nextSteps:d.nextSteps?.slice(0,20),...d.outputText?{outputText:d.outputText.slice(0,5e3)}:{}}});return c.length>0&&o.push(`[list caps applied: ${c.join("; ")}]`),{...t,__chainHistory:u,...o.length>0?{__chainHistoryNotes:o}:{}}}async executeStep(t,n,r){let o=Array.isArray(t.context?.args)?t.context.args:void 0,s=t.inlineGoal??t.name,i=o&&o.length>0?[s,...o].join(" "):s,a=t.context?.withContext===!0,c;if(a){let d=[...r].reverse().find(l=>l.outcome==="success"&&l.result?.outputText);d?.result?.outputText&&(c=d.result.outputText.slice(0,e.MAX_WITH_CONTEXT_OUTPUT_CHARS))}let u={taskId:`chain-${Date.now()}-${t.name}`,runId:"chain",goal:i,summarizeThreshold:3e3,collapseContext:!0,context:{...n,__chainStepTeam:t.team,__chainStepWorkflow:t.workflow,__chainStepModel:t.model,...c!==void 0?{__chainPrevOutput:c}:{},...t.timeout!==void 0?{__chainStepTimeoutMs:t.timeout}:{}}};return this.taskRunner.runTask(u)}plannedIterations(t){let n=t.context?.loopCount;return typeof n=="number"&&Number.isInteger(n)&&n>=1?Math.min(10,n):1}buildExecutionPlan(t){let n=[];return t.steps.forEach((r,o)=>{let s=this.plannedIterations(r);for(let i=1;i<=s;i++)n.push({step:r,stepIndex:o,iter:i,iterations:s,displayName:i>1?`${r.name}#${i}`:r.name})}),n}createMinimalPacket(t,n){return{taskId:`chain-step-${n}`,runId:"chain",sessionId:"chain",goal:t.inlineGoal??t.name}}}});function PJe(e){if(!e||typeof e!="object")return!1;let t=e;if(typeof t.taskId!="string"||!t.taskId||typeof t.runId!="string"||!t.runId||typeof t.timestamp!="number"||typeof t.task!="string"||!t.task||typeof t.outcome!="string"||!["success","failure","partial"].includes(t.outcome)||!Array.isArray(t.filesCreated)||!Array.isArray(t.filesModified)||!Array.isArray(t.filesDeleted)||!Array.isArray(t.decisions)||!Array.isArray(t.blockers)||!Array.isArray(t.nextSteps)||!t.metrics||typeof t.metrics!="object")return!1;let n=t.metrics;return!(typeof n.tokensUsed!="number"||typeof n.duration!="number"||typeof n.iterations!="number"||!Array.isArray(n.toolsUsed)||typeof t.contextSnapshot!="string")}var aP,Gce=v(()=>{"use strict";aP=class{pendingHandoffs=new Map;options;handoffTimestamps=new Map;cleanupTimer=null;disposed=!1;constructor(t={}){this.options={defaultSummarizeThreshold:5e3,handoffTimeoutMs:3e5,cleanupIntervalMs:6e4,...t},this.startCleanupTimer()}startCleanupTimer(){this.disposed||this.cleanupTimer||(this.cleanupTimer=setInterval(()=>{this.cleanupStaleHandoffs()},this.options.cleanupIntervalMs),typeof this.cleanupTimer.unref=="function"&&this.cleanupTimer.unref())}cleanupStaleHandoffs(){if(this.disposed)return;let t=Date.now(),n=this.options.handoffTimeoutMs??3e5,r=t-n,o=[];for(let[s,i]of this.handoffTimestamps.entries())i<r&&o.push(s);for(let s of o)this.pendingHandoffs.delete(s),this.handoffTimestamps.delete(s);if(this.pendingHandoffs.size>1e3){let s=[...this.handoffTimestamps.entries()].sort((a,c)=>a[1]-c[1]),i=s.length-1e3;for(let a=0;a<i;a++){let c=s[a][0];this.pendingHandoffs.delete(c),this.handoffTimestamps.delete(c)}}}async onAgentEnd(t,n){if(this.disposed||!this.shouldSummarize(t,n).shouldSummarize)return null;let r=await this.generateSummary(t,n);return PJe(r)?(t.sessionId&&(this.pendingHandoffs.set(t.sessionId,r),this.handoffTimestamps.set(t.sessionId,Date.now())),this.options.eventEmitter?.emit("handoff:generated",{packet:t,summary:r}),t.collapseContext&&await this.collapseContext(t,r),r):(this.options.eventEmitter?.emit("handoff:validation_failed",{packet:t,error:"Generated summary failed structure validation"}),null)}async onBeforeTreeNavigation(t,n){if(this.disposed)return null;let r=this.pendingHandoffs.get(t);return r?(this.pendingHandoffs.delete(t),this.handoffTimestamps.delete(t),r):null}shouldSummarize(t,n){if(!t||typeof t.taskId!="string"||!t.taskId)return{shouldSummarize:!1,reason:"Invalid task packet structure",tokenCount:0};if(!n||typeof n.outcome!="string")return{shouldSummarize:!1,reason:"Invalid task result structure",tokenCount:0};let r=t.summarizeThreshold??this.options.defaultSummarizeThreshold??5e3,o=n.usage?.totalTokens??0;if(o>r)return{shouldSummarize:!0,reason:`Token count ${o} exceeds threshold ${r}`,tokenCount:o};if(n.outcome==="success"&&(n.toolsUsed?.length??0)>=3)return{shouldSummarize:!0,reason:`Task used ${n.toolsUsed?.length??0} tools, exceeding minimum of 3`,tokenCount:o};if(t.forceSummarize===!0)return{shouldSummarize:!0,reason:"Forced summarization requested",tokenCount:o};let s=(n.filesCreated?.length??0)>0||(n.filesModified?.length??0)>0,i=(n.decisions?.length??0)>0;return s||i?{shouldSummarize:!0,reason:"Task produced significant artifacts or decisions",tokenCount:o}:n.outcome!=="success"?{shouldSummarize:!0,reason:`Task outcome is ${n.outcome}`,tokenCount:o}:{shouldSummarize:!1,reason:"Task below summarization threshold",tokenCount:o}}async generateSummary(t,n){let r=this.extractArtifacts(n),o=this.extractDecisionsFromResult(n),s=await this.generateContextSnapshot(t.runId,t.taskId,n);return{taskId:t.taskId,runId:t.runId,timestamp:Date.now(),task:t.goal,outcome:n.outcome,filesCreated:r.created,filesModified:r.modified,filesDeleted:r.deleted,decisions:o,blockers:n.blockers??[],nextSteps:n.nextSteps??[],metrics:{tokensUsed:n.usage?.totalTokens??0,duration:n.duration??0,iterations:n.iterations??1,toolsUsed:n.toolsUsed??[]},contextSnapshot:s,...n.outputText?{outputText:n.outputText}:{}}}async collapseContext(t,n){globalThis.__boomerangCollapseInProgress=!0;try{this.options.eventEmitter?.emit("handoff:context_collapse",{sessionId:t.sessionId,taskId:t.taskId,summary:n})}finally{globalThis.__boomerangCollapseInProgress=!1}}getPendingHandoff(t){return this.pendingHandoffs.get(t)}clearPendingHandoff(t){this.pendingHandoffs.delete(t),this.handoffTimestamps.delete(t)}clearAllPendingHandoffs(){this.pendingHandoffs.clear(),this.handoffTimestamps.clear()}getPendingCount(){return this.pendingHandoffs.size}extractArtifacts(t){return{created:t.filesCreated??[],modified:t.filesModified??[],deleted:t.filesDeleted??[]}}extractDecisionsFromResult(t){return t.decisions&&t.decisions.length>0?t.decisions:t.outcome==="failure"?[{rationale:"Task failed",outcome:t.error??"Unknown error",alternativesConsidered:[]}]:[]}async generateContextSnapshot(t,n,r){let o=[];return o.push(`Task: ${n}`),o.push(`Outcome: ${r.outcome}`),r.usage?.totalTokens&&o.push(`Tokens: ${r.usage.totalTokens}`),r.toolsUsed?.length&&o.push(`Tools: ${r.toolsUsed.join(", ")}`),r.blockers?.length&&o.push(`Blockers: ${r.blockers.join("; ")}`),r.nextSteps?.length&&o.push(`Next Steps: ${r.nextSteps.join("; ")}`),o.join(`
876
876
  `)}dispose(){this.disposed=!0,this.cleanupTimer&&(clearInterval(this.cleanupTimer),this.cleanupTimer=null),this.pendingHandoffs.clear(),this.handoffTimestamps.clear()}isDisposed(){return this.disposed}}});function MJe(e){let t=e.__chainHistory;if(!Array.isArray(t)||t.length===0)return"";let n=["# Previous Steps in This Chain",""];for(let o of t){if(!o||typeof o!="object")continue;let s=o,i=s.step??"unknown",a=s.outcome??"unknown";if(n.push(`## Step ${i}: ${a}`),n.push(`Files created: ${s.filesCreated?.length?s.filesCreated.join(", "):"none"}`),n.push(`Files modified: ${s.filesModified?.length?s.filesModified.join(", "):"none"}`),s.decisions?.length){n.push("Decisions:");for(let c of s.decisions){let u=c&&typeof c=="object"&&"rationale"in c?String(c.rationale):"(undocumented)",d=c&&typeof c=="object"&&"outcome"in c?String(c.outcome):"";n.push(`- ${u}${d?` \u2192 ${d}`:""}`)}}if(s.nextSteps?.length){n.push("Next steps:");for(let c of s.nextSteps)n.push(`- ${c}`)}s.outputText&&(n.push("Output:"),n.push(s.outputText)),n.push("")}let r=e.__chainHistoryNotes;if(Array.isArray(r))for(let o of r)typeof o=="string"&&o.length>0&&n.push(o);return n.join(`
877
877
  `).trimEnd()}function $Je(e,t){let n;e.status==="completed"?n="success":e.status==="failed"||e.status==="blocked"||e.status==="cancelled"?n="failure":n="partial";let r=t.some(l=>l.status==="failed"||l.status==="needs_attention"),o=t.some(l=>l.status==="completed");r&&(o||n==="success")&&(n="partial");let s=0;for(let l of t)s+=(l.usage?.input??0)+(l.usage?.output??0);let i=0,a=Date.parse(e.createdAt),c=Date.parse(e.updatedAt);!Number.isNaN(a)&&!Number.isNaN(c)&&c>=a&&(i=c-a);let u;n!=="success"&&(u=t.find(f=>f.status==="failed")?.error??e.summary);let d={outcome:n,usage:{totalTokens:s},duration:i};return u&&(d.error=u),d}function OJe(e,t){let n=[];for(let r of t){if(r.status!=="completed"||!r.resultArtifact?.path)continue;let o=Jh(r.resultArtifact.path,{baseDir:e.artifactsRoot});o?.content&&o.content.trim().length>0&&n.push(o.content.trim())}return n.length>0?n.join(`
878
878
 
879
- `):void 0}var cP,Hce=v(()=>{"use strict";Qp();Ge();we();jl();cP=class{stepRunIds=[];handleRunRef;ctx;overrides;constructor(t){this.handleRunRef=t.handleRun,this.ctx=t.ctx,this.overrides=t.overrides??{}}async runTask(t){let n=t.context??{},r=MJe(n),o=r?`${r}
879
+ `):void 0}var cP,Hce=v(()=>{"use strict";Qp();Ge();we();jl();cP=class{stepRunIds=[];handleRunRef;ctx;overrides;constructor(t){this.handleRunRef=t.handleRun,this.ctx=t.ctx,this.overrides=t.overrides??{}}async runTask(t){let n=t.context??{},r=MJe(n),o=typeof n.__chainPrevOutput=="string"?n.__chainPrevOutput.trim():"",s=o?`# Previous Step Output (--with-context)
880
+
881
+ ${o}`:"",i=[r,s].filter(x=>x.length>0),a=i.length>0?`${i.join(`
882
+
883
+ ---
884
+ `)}
880
885
 
881
886
  ---
882
887
  # Current Chain Step
883
- ${t.goal}`:t.goal,s=n.__chainStepTeam??this.overrides.team??"default",i=n.__chainStepWorkflow??this.overrides.workflow,a=i==="chain"?void 0:i,c=n.__chainStepModel??this.overrides.model,u={action:"run",goal:o,team:s,async:!1,...a?{workflow:a}:{},...c?{model:c}:{}},d=await this.handleRunRef(u,this.ctx),l=d.details?.runId;if(!l)return{outcome:"failure",error:Wl(d)||"Chain step produced no runId"};this.stepRunIds.push(l);let f=this.ctx.cwd??process.cwd(),p=F(f,l);if(!p)return{outcome:d.details?.status==="error"?"failure":"partial"};let m=$Je(p.manifest,p.tasks),g=OJe(p.manifest,p.tasks);return g&&(m.outputText=g),m}}});var qce={};ve(qce,{handleChainRun:()=>DJe});async function DJe(e,t,n){let r=e.chain;if(!r||r.trim().length===0)return E("Chain expression is empty.",{action:"run",status:"error"},!0);if(e.workflow==="chain")return E("Workflow 'chain' cannot be combined with a chain run: the chain runner owns step execution and has no per-step workflow. Omit `workflow` (steps use the team's defaultWorkflow) or use @team references in the chain expression.",{action:"run",status:"error"},!0);let o=Uce(r);if(o.steps.length===0)return E('Chain must contain at least one step. Use the form: "step1 -> step2 -> step3".',{action:"run",status:"error"},!0);let s=new cP({handleRun:n,ctx:t,overrides:{team:e.team,...e.model?{model:e.model}:{}}}),a=await new xv(s,new aP).runChain(o,{},void 0),c=[`Chain ${a.success?"completed":"ended"}: ${o.steps.length} step(s), ${a.totalHandoffs.length} handoff(s).`,""];for(let u of a.steps){let d=s.stepRunIds[u.step-1],l=u.outcome==="success"?"\u2713":u.outcome==="failure"?"\u2717":u.outcome==="partial"?"\u2248":"\u2298";c.push(`${l} Step ${u.step} [${u.name}]: ${u.outcome} (${u.duration}ms)${d?` runId=${d}`:""}${u.error?` | ${u.error}`:""}`)}return c.push(""),c.push(`Total: ${a.totalDuration}ms${a.totalTokens!==void 0?`, ${a.totalTokens} tokens`:""}`),E(c.join(`
888
+ ${t.goal}`:t.goal,c=n.__chainStepTeam??this.overrides.team??"default",u=n.__chainStepWorkflow??this.overrides.workflow,d=u==="chain"?void 0:u,l=n.__chainStepModel??this.overrides.model,f=typeof n.__chainStepTimeoutMs=="number"?n.__chainStepTimeoutMs:void 0,p={action:"run",goal:a,team:c,async:!1,...d?{workflow:d}:{},...l?{model:l}:{},...f!==void 0&&Number.isFinite(f)?{timeoutMs:f}:{}},m=await this.handleRunRef(p,this.ctx),g=m.details?.runId;if(!g)return{outcome:"failure",error:Wl(m)||"Chain step produced no runId"};this.stepRunIds.push(g);let w=this.ctx.cwd??process.cwd(),b=F(w,g);if(!b)return{outcome:m.details?.status==="error"?"failure":"partial"};let h=$Je(b.manifest,b.tasks),S=OJe(b.manifest,b.tasks);return S&&(h.outputText=S),h}}});var qce={};ve(qce,{handleChainRun:()=>DJe});async function DJe(e,t,n){let r=e.chain;if(!r||r.trim().length===0)return E("Chain expression is empty.",{action:"run",status:"error"},!0);if(e.workflow==="chain")return E("Workflow 'chain' cannot be combined with a chain run: the chain runner owns step execution and has no per-step workflow. Omit `workflow` (steps use the team's defaultWorkflow) or use @team references in the chain expression.",{action:"run",status:"error"},!0);let o=Uce(r);if(o.steps.length===0)return E('Chain must contain at least one step. Use the form: "step1 -> step2 -> step3".',{action:"run",status:"error"},!0);let s=new cP({handleRun:n,ctx:t,overrides:{team:e.team,...e.model?{model:e.model}:{}}}),a=await new xv(s,new aP).runChain(o,{},void 0),c=[`Chain ${a.success?"completed":"ended"}: ${o.steps.length} step(s), ${a.totalHandoffs.length} handoff(s).`,""];for(let u of a.steps){let d=s.stepRunIds[u.step-1],l=u.outcome==="success"?"\u2713":u.outcome==="failure"?"\u2717":u.outcome==="partial"?"\u2248":"\u2298";c.push(`${l} Step ${u.step} [${u.name}]: ${u.outcome} (${u.duration}ms)${d?` runId=${d}`:""}${u.error?` | ${u.error}`:""}`)}return c.push(""),c.push(`Total: ${a.totalDuration}ms${a.totalTokens!==void 0?`, ${a.totalTokens} tokens`:""}`),E(c.join(`
884
889
  `),{action:"run",status:a.success?"ok":"error",data:{chain:!0,steps:a.steps.length,totalTokens:a.totalTokens,runIds:s.stepRunIds}},!a.success)}var Kce=v(()=>{"use strict";Bce();Gce();Hce();Bt()});var Yce={};ve(Yce,{handleRun:()=>Jce});import*as Ec from"node:fs";import*as zce from"node:path";async function Vce(...e){return(await Promise.resolve().then(()=>(pv(),r_))).executeTeamRun(...e)}function NJe(e,t=4096){try{let n=Math.min(t,524288),r=Ec.statSync(e),o=Math.max(0,r.size-n),s=Ec.openSync(e,"r");try{let i=Buffer.alloc(r.size-o);return Ec.readSync(s,i,0,i.length,o),i.toString("utf-8").trim()}finally{Ec.closeSync(s)}}catch{return}}function LJe(e,t,n,r){if(Y("PI_CREW_ASYNC_EARLY_EXIT_GUARD")==="0")return;setTimeout(()=>{let s=F(e,t);if(!s||!Ln(s.manifest.status)||LI(s.manifest)||so(s.manifest.eventsPath).events.some(a=>a.type==="async.started"||a.type==="async.completed"||a.type==="async.failed"))return;let i=wn(n);if(!i.alive)try{Le(s.manifest,()=>{let a=F(e,t);if(!a||!Ln(a.manifest.status)||LI(a.manifest)||so(a.manifest.eventsPath).events.some(l=>l.type==="async.started"||l.type==="async.completed"||l.type==="async.failed"))return;let c=NJe(r),u=`Background runner exited within 3s; see background.log${c?`
885
890
  ${c}`:""}`,d=$e(a.manifest,"failed","Background runner exited within 3s; see background.log");Q(d.eventsPath,{type:"async.failed",runId:d.runId,message:u,data:{pid:n,detail:i.detail}}).catch(l=>k("team-tool.run.asyncFailedEvent",l,`runId=${d.runId}`))})}catch(a){k("team-tool.run.earlyExitGuard",a instanceof Error?a:new Error(String(a)),`runId=${t}`)}},3e3).unref()}function rB(e,t){let{tasks:n,metrics:r,goal:o,team:s,workflow:i,workspaceId:a,runtime:c,mode:u="waited"}=t;if(u==="scaffold"){let f=c?`Runtime: ${c.kind}${c.fallback?` (fallback from ${c.requestedMode})`:""}${c.reason?` - ${c.reason}`:""}`:"Runtime: unknown",p=c?c.kind==="child-process"?"Child Pi worker execution is enabled by default; each task is launched as a separate Pi process. Set runtime.mode=scaffold or executeWorkers=false only for dry runs.":c.kind==="live-session"?"Experimental live-session worker execution was enabled.":"Safe scaffold mode: child Pi workers were not launched because runtime.mode=scaffold or executeWorkers=false was configured.":"",m=[Cn("team.run.created",{runId:e.runId}),`Team: ${s}`,`Workflow: ${i}`,`Status: ${e.status}`,`Tasks: ${n.length}`,`State: ${e.stateRoot}`,`Artifacts: ${e.artifactsRoot}`,"",f,p].filter(w=>w!=="").join(`
886
891
  `),g=e.status==="failed";return E(m,{action:"run",status:g?"error":"ok",runId:e.runId,artifactsRoot:e.artifactsRoot,metrics:r,...a?{data:{workspaceId:a}}:{}},g)}let d=[Cn("team.run.completed",{status:e.status,runId:e.runId,team:s}),`Goal: ${o.slice(0,100)}`];if(r&&(d.push(""),d.push(`Metrics: ${r.completedCount}/${r.taskCount} tasks, ${r.totalTokens} tokens, ${r.durationMs}ms, consistency=${r.consistencyScore}`)),n.length>0){let f,p=e.artifacts?.find(b=>b.kind==="summary");if(p)try{let b=zce.join(e.artifactsRoot,p.path);f=Ec.readFileSync(b,"utf-8").trim().slice(0,4e3)}catch{}let m=[],g=0,w=[];for(let b of n){let h="";if(b.resultArtifact?.path)try{let I=de(e.artifactsRoot,b.resultArtifact.path);h=Ec.readFileSync(I,"utf-8").trim().slice(0,2e3)}catch{h="(result unavailable)"}let S=h.slice(0,500),x=b.status==="completed"?"\u2713":b.status==="failed"?"\u2717":b.status==="cancelled"?"\u2298":"\xB7",T=b.status==="failed"&&b.failureCause?`${b.status} (${HC(b.failureCause)})`:b.status;m.push(`- ${x} ${b.id} [${b.role}]: ${T}${S?" \u2014 "+S:""}${b.error?` | Error: ${b.error.slice(0,200)}`:""}`),(b.status==="failed"||b.status==="needs_attention")&&(g++,w.push(b.id))}d.push(""),d.push(`Tasks (${n.length}):`),d.push(...m),f&&(d.push(""),d.push("Summary:"),d.push(f.slice(0,2e3))),g===0?(d.push(""),d.push(Cn("team.run.allCompleted"))):(d.push(""),d.push(Cn("team.run.tasksFailed",{count:g,ids:w.join(", ")})))}else d.push(e.status==="completed"?"Run completed with no task results.":`The run ended with status: ${e.status}. Check the run artifacts for details.`);let l=e.status==="failed"||e.status==="blocked";return E(d.join(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-crew",
3
- "version": "0.11.25",
3
+ "version": "0.11.27",
4
4
  "description": "Pi extension for coordinated AI teams, workflows, worktrees, and async task orchestration",
5
5
  "author": "baphuongna",
6
6
  "license": "MIT",
@@ -235,7 +235,14 @@ export class ChainTeamRunExecutor implements ChainTaskRunner {
235
235
  // 1. Format chain history into the goal — this is how context reaches the worker.
236
236
  // Mirrors the parentContext pattern in child-pi.ts (parent context + task delimiter).
237
237
  const historyPrefix = formatChainHistory(context);
238
- const enrichedGoal = historyPrefix ? `${historyPrefix}\n\n---\n# Current Chain Step\n${packet.goal}` : packet.goal;
238
+ // v0.11.27 (R14-C1 tail): `--with-context` carries the previous step's FULL
239
+ // output as __chainPrevOutput (runner-capped); render it as its own block so
240
+ // the worker sees raw output, not just the size-capped handoff summary.
241
+ const prevOutput = typeof context.__chainPrevOutput === "string" ? context.__chainPrevOutput.trim() : "";
242
+ const prevOutputBlock = prevOutput ? `# Previous Step Output (--with-context)\n\n${prevOutput}` : "";
243
+ const headerParts = [historyPrefix, prevOutputBlock].filter((part) => part.length > 0);
244
+ const enrichedGoal =
245
+ headerParts.length > 0 ? `${headerParts.join("\n\n---\n")}\n\n---\n# Current Chain Step\n${packet.goal}` : packet.goal;
239
246
 
240
247
  // 2. Resolve team/workflow/model: step config (set by executeStep) → overrides → default.
241
248
  // BUG-44 (github #44): a workflow override of "chain" is a dispatcher-only marker
@@ -250,6 +257,11 @@ export class ChainTeamRunExecutor implements ChainTaskRunner {
250
257
  // 3. Call handleRun for the heavy lifting. async:false forces each step to
251
258
  // complete synchronously (overrides asyncByDefault) so the chain is sequential.
252
259
  // NO `chain` key here — so the run.ts guard does not re-enter chain dispatch.
260
+ // v0.11.27 (R14-C2): forward the previously-dead `--timeout N` (s) flag.
261
+ // resolveRunDeadline honors params.timeoutMs (CORE-8 unified deadline:
262
+ // params > config.limits.maxRunMinutes > 1h default) for foreground runs.
263
+ const stepTimeoutMs = typeof context.__chainStepTimeoutMs === "number" ? context.__chainStepTimeoutMs : undefined;
264
+
253
265
  const runParams: TeamToolParamsValue = {
254
266
  action: "run",
255
267
  goal: enrichedGoal,
@@ -257,6 +269,7 @@ export class ChainTeamRunExecutor implements ChainTaskRunner {
257
269
  async: false,
258
270
  ...(stepWorkflow ? { workflow: stepWorkflow } : {}),
259
271
  ...(stepModel ? { model: stepModel } : {}),
272
+ ...(stepTimeoutMs !== undefined && Number.isFinite(stepTimeoutMs) ? { timeoutMs: stepTimeoutMs } : {}),
260
273
  };
261
274
  const runRes = await this.handleRunRef(runParams, this.ctx);
262
275
 
@@ -6,6 +6,12 @@
6
6
  * step1:3 -> step2 --with-context -> step3
7
7
  * parallel(a, b, parallel(c, d)) -> e
8
8
  *
9
+ * `:N` loop counts are CLAMPED to 1..10 (v0.11.27): N=0/absent would silently
10
+ * skip nothing, N>10 would queue unbounded sequential runs. Clamping (not
11
+ * throwing) is deliberate — a throw here makes chain-runner fall back to the
12
+ * simple splitter, which turns `step:99` into ONE literal step named "step:99"
13
+ * (the exact R14-C1 silent-corruption class this parser exists to prevent).
14
+ *
9
15
  * Pattern origin: pi-prompt-template-model chain-parser.ts
10
16
  */
11
17
 
@@ -193,6 +199,21 @@ class ChainParser {
193
199
  return step;
194
200
  }
195
201
 
202
+ // v0.11.27 (probe-caught): a QUOTED string is a valid step too —
203
+ // `"polish output":2` is the natural way to combine an inline goal with
204
+ // DSL modifiers. Previously only bare NAMEs were accepted here, so any
205
+ // quoted-goal chain with `:N`/`--with-context` threw and chain-runner
206
+ // silently fell back to the simple splitter — the constructs died for
207
+ // the MOST COMMON goal syntax. A quoted step keeps its text as `name`
208
+ // (executeStep uses it as the goal, mirroring the simple path's
209
+ // inlineGoal semantics).
210
+ if (this.peek("QUOTED")) {
211
+ const quoted = this.consume("QUOTED");
212
+ const quotedStep: ChainStep = { name: quoted.value };
213
+ this.parseModifiers(quotedStep);
214
+ return quotedStep;
215
+ }
216
+
196
217
  // Normal step name
197
218
  const name = this.consume("NAME").value;
198
219
  const step: ChainStep = { name };
@@ -207,7 +228,9 @@ class ChainParser {
207
228
  if (this.peek("COLON")) {
208
229
  this.consume("COLON");
209
230
  const num = this.consume("NUMBER");
210
- step.loopCount = Number.parseInt(num.value, 10);
231
+ // v0.11.27: clamp 1..10 (see header). Clamp-not-throw: a throw silently
232
+ // degrades the whole chain to the simple parser (literal step names).
233
+ step.loopCount = Math.min(10, Math.max(1, Number.parseInt(num.value, 10)));
211
234
  } else if (this.peek("FLAG", "with-context")) {
212
235
  this.consume("FLAG");
213
236
  step.withContext = true;
@@ -105,6 +105,10 @@ export class ChainRunner {
105
105
  /** Maximum size per handoff entry to prevent memory issues from large artifacts */
106
106
  private static readonly MAX_HANDOFF_ENTRY_SIZE = 5000; // bytes per entry
107
107
 
108
+ /** v0.11.27: `--with-context` full-output cap (default history carries only
109
+ * 5000-char summaries; this is the explicit full-output channel, bounded). */
110
+ private static readonly MAX_WITH_CONTEXT_OUTPUT_CHARS = 20000; // chars
111
+
108
112
  private taskRunner: ChainTaskRunner;
109
113
  private handoffManager: HandoffManager;
110
114
 
@@ -186,8 +190,16 @@ export class ChainRunner {
186
190
  // success predicate cannot report a truncated chain as complete.
187
191
  let brokeEarly = false;
188
192
 
189
- for (let i = 0; i < spec.steps.length; i++) {
190
- const step = spec.steps[i];
193
+ // v0.11.27 (R14-C1 tail): expand `:N` loop steps into an execution plan —
194
+ // one entry per ITERATION. Each iteration is its own ChainStepResult
195
+ // (name#k for k>1) so a failing iteration stays visible; the success
196
+ // predicate counts planned EXECUTIONS, so a chain that broke inside a
197
+ // loop cannot pass unexecuted iterations off as done (R14-C5 class).
198
+ const plan = this.buildExecutionPlan(spec);
199
+ const plannedExecutions = plan.length;
200
+
201
+ for (const entry of plan) {
202
+ const { step, stepIndex: i, displayName, iterations } = entry;
191
203
  const stepStart = Date.now();
192
204
 
193
205
  try {
@@ -198,7 +210,7 @@ export class ChainRunner {
198
210
  const stepContext = this.enrichContextFromHandoffs(accumulatedContext, stepResults);
199
211
 
200
212
  // Execute step
201
- const result = await this.executeStep(effectiveConfig, stepContext);
213
+ const result = await this.executeStep(effectiveConfig, stepContext, stepResults);
202
214
 
203
215
  // Track tokens
204
216
  if (result.usage?.totalTokens) {
@@ -210,7 +222,7 @@ export class ChainRunner {
210
222
 
211
223
  stepResults.push({
212
224
  step: i + 1,
213
- name: step.name,
225
+ name: displayName,
214
226
  outcome: result.outcome,
215
227
  result,
216
228
  handoff,
@@ -243,10 +255,10 @@ export class ChainRunner {
243
255
  await appendEventAsync(eventsPath, {
244
256
  type: "chain.step_completed",
245
257
  runId: "chain",
246
- taskId: `step-${i + 1}`,
258
+ taskId: iterations > 1 ? `step-${i + 1}#${entry.iter}` : `step-${i + 1}`,
247
259
  data: {
248
260
  step: i + 1,
249
- name: step.name,
261
+ name: displayName,
250
262
  outcome: result.outcome,
251
263
  duration: Date.now() - stepStart,
252
264
  },
@@ -257,7 +269,7 @@ export class ChainRunner {
257
269
 
258
270
  stepResults.push({
259
271
  step: i + 1,
260
- name: step.name,
272
+ name: displayName,
261
273
  outcome: "failure",
262
274
  duration: Date.now() - stepStart,
263
275
  error: errMsg,
@@ -277,7 +289,7 @@ export class ChainRunner {
277
289
  // for a chain whose remaining steps never ran. An empty spec was vacuously
278
290
  // green for the same reason. Success now requires: at least one step, no
279
291
  // early break, every planned step executed, and every outcome `success`.
280
- const allStepsExecuted = stepResults.length === spec.steps.length;
292
+ const allStepsExecuted = stepResults.length === plannedExecutions;
281
293
  const allOutcomesSuccessful = stepResults.every((s) => s.outcome === "success");
282
294
 
283
295
  return {
@@ -393,9 +405,14 @@ export class ChainRunner {
393
405
  // Parse step timeout
394
406
  const timeoutStr = this.extractFlag(step, "timeout");
395
407
  if (timeoutStr) {
396
- const timeoutMs = parseInt(timeoutStr, 10);
397
- if (!Number.isNaN(timeoutMs) && timeoutMs > 0 && timeoutMs <= 86400000) {
398
- parsed.timeout = timeoutMs * 1000; // Convert seconds to ms
408
+ // v0.11.27 (R14-C2): the flag is SECONDS — the old bound compared the
409
+ // seconds value against 86400000 (a 1000-day ms bound) before
410
+ // multiplying, so `--timeout 99999999` was silently accepted. Now
411
+ // 1..86400 s (1 day), and the value is actually CONSUMED (chain-executor
412
+ // forwards it as runParams.timeoutMs).
413
+ const timeoutSec = parseInt(timeoutStr, 10);
414
+ if (!Number.isNaN(timeoutSec) && timeoutSec > 0 && timeoutSec <= 86400) {
415
+ parsed.timeout = timeoutSec * 1000;
399
416
  }
400
417
  }
401
418
 
@@ -412,7 +429,12 @@ export class ChainRunner {
412
429
  * DSL features: parallel(...), :loopCount, --with-context flag
413
430
  */
414
431
  private hasDSLConstructs(chainString: string): boolean {
415
- return /\bparallel\s*\(/.test(chainString) || /\w+:\d+\b/.test(chainString) || /--with-context/.test(chainString);
432
+ // v0.11.27 (probe-caught): `:\d+` no longer requires a leading \w — a
433
+ // QUOTED goal followed by `:2` (`"polish":2`) must route to the DSL
434
+ // parser too. Broadening is safe: time-like false positives
435
+ // ("deploy at 10:30") still throw inside the DSL parser and fall back to
436
+ // the simple splitter exactly as before.
437
+ return /\bparallel\s*\(/.test(chainString) || /:\d+\b/.test(chainString) || /--with-context/.test(chainString);
416
438
  }
417
439
 
418
440
  /**
@@ -613,7 +635,29 @@ export class ChainRunner {
613
635
  /**
614
636
  * Execute a single step.
615
637
  */
616
- private async executeStep(config: ChainStep, context: Record<string, unknown>): Promise<TaskResult> {
638
+ private async executeStep(
639
+ config: ChainStep,
640
+ context: Record<string, unknown>,
641
+ previousResults: ChainStepResult[],
642
+ ): Promise<TaskResult> {
643
+ // v0.11.27 (R14-C1 tail): DSL `args` append to the goal — positional goal
644
+ // arguments (`"research" "topic X"` -> goal "research topic X").
645
+ const dslArgs = Array.isArray(config.context?.args) ? (config.context.args as string[]) : undefined;
646
+ const baseGoal = config.inlineGoal ?? config.name;
647
+ const goal = dslArgs && dslArgs.length > 0 ? [baseGoal, ...dslArgs].join(" ") : baseGoal;
648
+
649
+ // v0.11.27 (R14-C1 tail): DSL `--with-context` passes the PREVIOUS step's
650
+ // full worker output (capped) — distinct from the default __chainHistory,
651
+ // which carries only size-capped handoff summaries.
652
+ const withContext = config.context?.withContext === true;
653
+ let chainPrevOutput: string | undefined;
654
+ if (withContext) {
655
+ const prev = [...previousResults].reverse().find((r) => r.outcome === "success" && r.result?.outputText);
656
+ if (prev?.result?.outputText) {
657
+ chainPrevOutput = prev.result.outputText.slice(0, ChainRunner.MAX_WITH_CONTEXT_OUTPUT_CHARS);
658
+ }
659
+ }
660
+
617
661
  // Pass step config (team/workflow/model) into the packet context so the
618
662
  // concrete ChainTaskRunner can resolve which team/workflow to run. Without
619
663
  // this, a step parsed to a @teamName reference would lose its team because
@@ -622,7 +666,7 @@ export class ChainRunner {
622
666
  const packet: TaskPacket = {
623
667
  taskId: `chain-${Date.now()}-${config.name}`,
624
668
  runId: "chain",
625
- goal: config.inlineGoal ?? config.name,
669
+ goal,
626
670
  summarizeThreshold: 3000,
627
671
  collapseContext: true,
628
672
  context: {
@@ -630,12 +674,53 @@ export class ChainRunner {
630
674
  __chainStepTeam: config.team,
631
675
  __chainStepWorkflow: config.workflow,
632
676
  __chainStepModel: config.model,
677
+ ...(chainPrevOutput !== undefined ? { __chainPrevOutput: chainPrevOutput } : {}),
678
+ // v0.11.27 (R14-C2): wire the previously-dead `--timeout` flag into
679
+ // the step run's deadline (ms; consumed by chain-executor as
680
+ // runParams.timeoutMs -> CORE-8 resolveRunDeadline).
681
+ ...(config.timeout !== undefined ? { __chainStepTimeoutMs: config.timeout } : {}),
633
682
  },
634
683
  };
635
684
 
636
685
  return this.taskRunner.runTask(packet);
637
686
  }
638
687
 
688
+ /** v0.11.27: iterations planned for a step — `:N` DSL (parser-clamped 1..10). */
689
+ private plannedIterations(step: ChainStep): number {
690
+ const n = step.context?.loopCount;
691
+ return typeof n === "number" && Number.isInteger(n) && n >= 1 ? Math.min(10, n) : 1;
692
+ }
693
+
694
+ /** v0.11.27: expand steps into per-iteration plan entries. */
695
+ private buildExecutionPlan(spec: ChainSpec): Array<{
696
+ step: ChainStep;
697
+ stepIndex: number;
698
+ iter: number;
699
+ iterations: number;
700
+ displayName: string;
701
+ }> {
702
+ const plan: Array<{
703
+ step: ChainStep;
704
+ stepIndex: number;
705
+ iter: number;
706
+ iterations: number;
707
+ displayName: string;
708
+ }> = [];
709
+ spec.steps.forEach((step, stepIndex) => {
710
+ const iterations = this.plannedIterations(step);
711
+ for (let iter = 1; iter <= iterations; iter++) {
712
+ plan.push({
713
+ step,
714
+ stepIndex,
715
+ iter,
716
+ iterations,
717
+ displayName: iter > 1 ? `${step.name}#${iter}` : step.name,
718
+ });
719
+ }
720
+ });
721
+ return plan;
722
+ }
723
+
639
724
  /**
640
725
  * Create minimal packet for handoff generation.
641
726
  */
@@ -141,7 +141,7 @@ registerPlanTemplate({
141
141
  name: "verify",
142
142
  role: "verifier",
143
143
  taskTemplate:
144
- "Verify that all review findings are addressed. Run FAST checks (completes in <2 min): `npm run test:critical && npx tsc --noEmit`. Do NOT run `npm run test:unit` or `npm test` — too slow (642 files, >4 min). Confirm: {{goal}} is achieved.",
144
+ "Verify that all review findings are addressed. Run FAST checks (completes in <2 min): `npm run test:critical && npx tsc --noEmit`. Do NOT run `npm run test:unit` or `npm test` — too slow (642 files, >4 min). Confirm: {{goal}} is achieved. Start the report with the verdict line `PASS: <what verified> — <evidence>` or `FAIL: <what failed> — <reason>` (the green-contract consumer reads it; no verdict line = UNVERIFIED).",
145
145
  maxTasks: 1,
146
146
  dependsOn: ["review"],
147
147
  verificationCommand: "npm run test:critical && npx tsc --noEmit",
@@ -189,7 +189,7 @@ registerPlanTemplate({
189
189
  name: "verify",
190
190
  role: "verifier",
191
191
  taskTemplate:
192
- "Verify the complete implementation of: {{goal}}. Run FAST checks (`npm run test:critical && npx tsc --noEmit`, completes in <2 min). Do NOT run `npm run test:unit` or `npm test` — too slow for in-loop verification (642 files, >4 min). Validate all acceptance criteria.",
192
+ "Verify the complete implementation of: {{goal}}. Run FAST checks (`npm run test:critical && npx tsc --noEmit`, completes in <2 min). Do NOT run `npm run test:unit` or `npm test` — too slow for in-loop verification (642 files, >4 min). Validate all acceptance criteria. Start the report with the verdict line `PASS: <what verified> — <evidence>` or `FAIL: <what failed> — <reason>` (the green-contract consumer reads it; no verdict line = UNVERIFIED).",
193
193
  maxTasks: 1,
194
194
  dependsOn: ["review"],
195
195
  verificationCommand: "npm run test:critical && npx tsc --noEmit",
@@ -127,11 +127,17 @@ export type VerifierVerdict = "pass" | "fail" | "none";
127
127
  * (`live-session-runtime.ts` buildOutputContract → "PASS: <what verified> —
128
128
  * <evidence>" / "FAIL: <what failed> — <reason>"). Tolerates the markdown
129
129
  * decorations real workers emit (`**PASS:**`, `- FAIL:`, `> PASS:`,
130
- * `` `PASS:` ``, `# PASS:`), but only at line start — a bare mention of the
131
- * word inside prose does NOT count, and the colon is REQUIRED (the contract
132
- * has one; a colon-less "PASS" is prose, not a verdict).
130
+ * `` `PASS:` ``, `# PASS:`) AND the bare-prose verdicts the child-process
131
+ * workflow prompts used to ask for ("Give PASS or FAIL with evidence" →
132
+ * `PASS`, `**PASS**`, `PASS — evidence`, `PASS. Evidence: …`): a wave-6 T7
133
+ * live probe caught a FAILED-gate run blocking as `green_unsatisfied /
134
+ * observed=none` because the verifier followed its prose prompt and wrote a
135
+ * bare verdict. A token only counts at LINE START and only when followed by
136
+ * punctuation/EOL/`(` — a bare mention inside prose ("the verifier said
137
+ * PASS: that") still does NOT count, and a word continuation ("PASSED all
138
+ * checks") does not either.
133
139
  */
134
- const VERIFIER_VERDICT_LINE = /^[\s*_>#`=-]*(PASS|FAIL)\s*:/i;
140
+ const VERIFIER_VERDICT_LINE = /^[\s*_>#`=-]*(PASS|FAIL)[\s*_`]*(?=[:.\u2014\u2013-]|$|\()/i;
135
141
 
136
142
  /**
137
143
  * M3-2 (R47-3/V4, fix-wave 6): read the verifier verdict out of the
@@ -36,6 +36,6 @@ Rules:
36
36
  - **MAXIMIZE PARALLELISM**: Put independent tasks in the SAME phase so they run concurrently. Never create sequential phases when tasks are independent.
37
37
  - Task titles name the concrete piece of work — they become the task list the user watches.
38
38
  - Choose the smallest effective number of tasks per phase; a simple goal may have 1-2 phases with 1-2 tasks.
39
- - End implementation plans with a verification phase (`verifier` role): run FAST targeted checks only (e.g. the affected test files), never the full suite.
39
+ - End implementation plans with a verification phase (`verifier` role): run FAST targeted checks only (e.g. the affected test files), never the full suite. The verifier's report MUST start with the verdict line — `PASS: <what verified> — <evidence>` or `FAIL: <what failed> — <reason>` (the green-contract consumer reads it; a report with no verdict line is treated as UNVERIFIED).
40
40
  - Tasks within the same phase run in parallel; phases run sequentially.
41
41
  - Do not include more than 12 tasks per phase; split or summarize oversized plans instead.
@@ -21,4 +21,4 @@ dependsOn: execute
21
21
  verify: true
22
22
 
23
23
  Verify the fix with available evidence.
24
- Run FAST checks ONCE and cache output WITH provenance to `.crew/cache/` (per `agents/verifier.md`: unique per-attempt filename, `set -o pipefail` so the recorded exit code is the command's — not `tee`'s — and a sibling `.meta` recording command, git revision, tree fingerprint): `npm run test:critical && npx tsc --noEmit` (completes in <60s; if this repo lacks these scripts, use its fastest documented check instead). Do NOT run `npm run test:unit` or `npm test` — too slow (642 files, >4 min). Cross-reference cached output with the fix — reuse a cached log only when its provenance matches. Do NOT re-run tests. Give PASS or FAIL with specific test evidence.
24
+ Run FAST checks ONCE and cache output WITH provenance to `.crew/cache/` (per `agents/verifier.md`: unique per-attempt filename, `set -o pipefail` so the recorded exit code is the command's — not `tee`'s — and a sibling `.meta` recording command, git revision, tree fingerprint): `npm run test:critical && npx tsc --noEmit` (completes in <60s; if this repo lacks these scripts, use its fastest documented check instead). Do NOT run `npm run test:unit` or `npm test` — too slow (642 files, >4 min). Cross-reference cached output with the fix — reuse a cached log only when its provenance matches. Do NOT re-run tests. Start your report with the verdict line — `PASS: <what verified> — <evidence>` or `FAIL: <what failed> — <reason>` (exact single-line format; the leader's green-contract consumer reads this line — a report with no verdict line is treated as UNVERIFIED). Then give details.
@@ -27,4 +27,4 @@ dependsOn: execute
27
27
  verify: true
28
28
 
29
29
  Verify completion for: {goal}
30
- Run FAST checks ONCE and cache output WITH provenance to `.crew/cache/` (per `agents/verifier.md`: unique per-attempt filename, `set -o pipefail` so the recorded exit code is the command's — not `tee`'s — and a sibling `.meta` recording command, git revision, tree fingerprint): `npm run test:critical && npx tsc --noEmit` (completes in <60s; if this repo lacks these scripts, use its fastest documented check instead). Do NOT run `npm run test:unit` or `npm test` — too slow (642 files, >4 min). Cross-reference cached output with the changes — reuse a cached log only when its provenance matches. Do NOT re-run tests. Give PASS or FAIL with specific test evidence.
30
+ Run FAST checks ONCE and cache output WITH provenance to `.crew/cache/` (per `agents/verifier.md`: unique per-attempt filename, `set -o pipefail` so the recorded exit code is the command's — not `tee`'s — and a sibling `.meta` recording command, git revision, tree fingerprint): `npm run test:critical && npx tsc --noEmit` (completes in <60s; if this repo lacks these scripts, use its fastest documented check instead). Do NOT run `npm run test:unit` or `npm test` — too slow (642 files, >4 min). Cross-reference cached output with the changes — reuse a cached log only when its provenance matches. Do NOT re-run tests. Start your report with the verdict line — `PASS: <what verified> — <evidence>` or `FAIL: <what failed> — <reason>` (exact single-line format; the leader's green-contract consumer reads this line — a report with no verdict line is treated as UNVERIFIED). Then give details.
@@ -28,4 +28,4 @@ role: verifier
28
28
  dependsOn: code-review, security-review
29
29
  verify: true
30
30
 
31
- Run FAST checks ONCE and cache output WITH provenance to `.crew/cache/` (per `agents/verifier.md`: unique per-attempt filename, `set -o pipefail` so the recorded exit code is the command's — not `tee`'s — and a sibling `.meta` recording command, git revision, tree fingerprint): `npm run test:critical && npx tsc --noEmit` (completes in <60s; if this repo lacks these scripts, use its fastest documented check instead). Do NOT run `npm run test:unit` or `npm test` — too slow (642 files, >4 min). Cross-reference cached output with reviewer and security-reviewer findings — reuse a cached log only when its provenance matches. Confirm each finding against real test output. Give PASS if findings match evidence, FAIL if critical findings are false positives or tests reveal new issues.
31
+ Run FAST checks ONCE and cache output WITH provenance to `.crew/cache/` (per `agents/verifier.md`: unique per-attempt filename, `set -o pipefail` so the recorded exit code is the command's — not `tee`'s — and a sibling `.meta` recording command, git revision, tree fingerprint): `npm run test:critical && npx tsc --noEmit` (completes in <60s; if this repo lacks these scripts, use its fastest documented check instead). Do NOT run `npm run test:unit` or `npm test` — too slow (642 files, >4 min). Cross-reference cached output with reviewer and security-reviewer findings — reuse a cached log only when its provenance matches. Confirm each finding against real test output. Start your report with the verdict line — `PASS: <what verified> — <evidence>` or `FAIL: <what failed> — <reason>` (exact single-line format; the leader's green-contract consumer reads this line — a report with no verdict line is treated as UNVERIFIED). Then give details.
@@ -23,4 +23,4 @@ dependsOn: execute
23
23
  verify: true
24
24
 
25
25
  Verify the fix with available evidence, AND cross-reference the SPEC-EVIDENCE footer from explore+execute against the spec's requirements (machine-check the citations vs the spec id set).
26
- Run FAST checks ONCE and cache output WITH provenance to `.crew/cache/` (per `agents/verifier.md`: unique per-attempt filename, `set -o pipefail` so the recorded exit code is the command's — not `tee`'s — and a sibling `.meta` recording command, git revision, tree fingerprint): `npm run test:critical && npx tsc --noEmit` (completes in <60s; if this repo lacks these scripts, use its fastest documented check instead). Do NOT run `npm run test:unit` or `npm test` — too slow (642 files, >4 min). Cross-reference cached output with the fix — reuse a cached log only when its provenance matches. Do NOT re-run tests. Give PASS or FAIL with specific test evidence + spec gate verdict.
26
+ Run FAST checks ONCE and cache output WITH provenance to `.crew/cache/` (per `agents/verifier.md`: unique per-attempt filename, `set -o pipefail` so the recorded exit code is the command's — not `tee`'s — and a sibling `.meta` recording command, git revision, tree fingerprint): `npm run test:critical && npx tsc --noEmit` (completes in <60s; if this repo lacks these scripts, use its fastest documented check instead). Do NOT run `npm run test:unit` or `npm test` — too slow (642 files, >4 min). Cross-reference cached output with the fix — reuse a cached log only when its provenance matches. Do NOT re-run tests. Start your report with the verdict line — `PASS: <what verified> — <evidence>` or `FAIL: <what failed> — <reason>` (exact single-line format; the leader's green-contract consumer reads this line — a report with no verdict line is treated as UNVERIFIED). Then give details. Include the spec-gate verdict too.